Sign in to follow this  

c-string vs Strings

This topic is 3861 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I swear that I think I get it but then I get it all confuzzed A c-string is a collection of characters stored in an array right and C++ places a null terminator at the end of it right? A String type from the String class is different how? I mean I know that itis an object and has member functions and all but does it have a null terminator?
Legal or illegal?
char cString[]= "This is a Cstring";//Legal?
char array[]= "";//Illegal?
String myStr = "Hello GameDev.net members!"//null terminated?

I know that a String type can use .at() to access a Strings elementsso does that mean that it too is an array? Help me, help me please!!1 Show me the lite...........BFX

Share this post


Link to post
Share on other sites
The C++ string class is std::string (note the lowercase). It does not use a NUL terminator as C-style strings do, it stores the length of the string instead. A C++ string is not an array, but it does implement (like many other classes) a subscript operator. The main difference is that std::string is a first-class object, while C arrays (and strings in particular) are not.

Share this post


Link to post
Share on other sites
Quote:
Original post by bluefox25
A c-string is a collection of characters stored in an array right
and C++ places a null terminator at the end of it right?

Yes. (C also places a null terminator at the end of it though)

Quote:
A String type from the String class is different how? I mean I know that itis an object and has member functions and all but does it have a null terminator?

It might or it might not. It doesn't matter because it encapsulates its implementation details. It does, however, store the length of the string as a separate value (which is a much better idea)
You, as the programmer, do not need to use *how* it represents the string, as long as it gives you the functions you need to access it.
In particular, it has the c_str() function which gives you the corresponding C-style string, allowing you to easily convert from one to the other.)

Quote:

I know that a String type can use .at() to access a Strings elementsso does that mean that it too is an array?

It can use .at() or it can use the [] operator, but it's not an array. It just acts a bit like one. But again, the exact implementation don't matter. That's why it's a class. It promises to do what you expect, and you don't need to know exactly *how* it's done.

Share this post


Link to post
Share on other sites
Great!!
I guess part of the confusion is that sometimes people refer to c-strings as strings so I get confused as to which type they are referring to. Can you initialize a c-string as
char word[]= "";
.

PS
I picked up Beginning Game Programming by Harbour and he tlks about the basics of Windows programming and DirectX. Can I program these two usiing C++, some of his example use C but since I don't know C, I wanna use C++. I like it better than C anyways from of the C code I've seen so far

Share this post


Link to post
Share on other sites
Quote:
Original post by bluefox25 Can you initialize a c-string as *blah*?
Sure. There won't be a whole lot you can do with it, though. I imagine it would just make an array of length one with just a zero in it.

A null terminator is basically just a zero. Nothing more, nothing less. A cstring just lists a bunch of char's, and when you're reading the array and reach a zero, that's the end of the string. So really, the size of the array you allocate when do you something like char * blah = "hi" is actually three, for 'h', 'i', and the number zero.

It's worth nothing what's happening in the program when you do something like char * blah = "Hello!". What's happening is that when you run your program, in the location where your program is in memory, there is your static area of memory. Strings you specify in the middle of your code - anything in "quotes" will be kept in a cstring in this area of memory. So here's the thing - you can't alter this memory. Your program will crash. So -

char * blah = "hello!";
blah[0] = 'H'; // crash

Yeah : )

vvvvvvvvv maybe it's different for if you do char[] or char *. I usually just use char *, and I know then that the pointer you get will be a pointer to static memory. When you do char[] it copies it to the stack? I guess it probably will since an array will take up space for the array right there, where a pointer will just be a pointer. There's still that string in static memory, though, since the program needs to keep that data somewhere.

So! Updatedly;

char blah1[] = "hello!";
blah1[0] = 'H'; // okay?
char * blah2 = "hello!";
blah2[0] = 'H'; // totally crash.]

This distinction isn't entirely relevant to the OP, but it's worth nothing, I guess.

[Edited by - Kimani on May 19, 2007 2:17:31 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Kimani
I'll be located in static memory, though, so there's very little you can do with it.


Actually, it would be located in static memory only if the definition is at global scope. It would be located on the stack otherwise. Either way, it's still an array of length 1, so it is not of much use.

Share this post


Link to post
Share on other sites
Thanks for clearing that up for me.

Another concept I am having a bit of trouble is, visualizing the stack? Is it a function stack? What does thee stack do? Someone said to think of it as a stack of plates but itt still is unclear to me

Share this post


Link to post
Share on other sites
Quote:
Original post by bluefox25
Thanks for clearing that up for me.

Another concept I am having a bit of trouble is, visualizing the stack? Is it a function stack? What does thee stack do? Someone said to think of it as a stack of plates but itt still is unclear to me


Where do variables live? In this function:

void bar( int argument )
{
float local;
// ...
}

Where in memory are "argument" or "local" stored?

The stack is all about temporary data. This includes all variables you declare inside a function. When you allocate with new, you use a stack variable (the pointer) to remember the address of the heap variable.

int *ptr = new int(42);

ptr is on the stack, the integers address is held in that variable.

However, C++ also needs to use the stack. When you call a function, some or all of the arguments to the function can be placed on the stack. In addition, the "return address" is stored on the stack, so when your function ends or when you use the return statement C++ knows where to resume in the function that called it.

Sharing the stack data with C++'s temporary data can lead to bad things, as I will explain later.

Lets take an example:

void foo( int a )
{
char buffer[100];
}


On the stack, this would look like:

--------------------------------------------
buffer[0]
buffer[1]
// ...
buffer[98]
buffer[99]
value of a
return address of calling function

--------------------------------------------
locals for calling code
arguments for calling code
return address for code that called here too

--------------------------------------------
etc ...
retrun address inside main

--------------------------------------------
main locals
main arguments (argc and argv)
return address for main

--------------------------------------------


I hope you can see the stack of plates analogy a bit better now. By that we mean, we have a bunch of things piled on top of one another. We can only add a new plate to the top (call another function), or remove the current plate (return from the current function). All the temporary data is stored on the plates, and you can only access data on the plate you are on (although you can cheat around this with pointers an references, but thats the idea anyway). [smile]

Imagine now your code accidentally writes beyond the bounds of an array. With C strings, this is all too easy to do. First of all, you may overwrite the value of the variable "a". If your program tries to use "a" later on it will get wrong results. However, what if your program continues to write and overwrite the return address? When your function finishes, where will it return? Anywhere, depending on the data you overwrite it with (the end of a string, which is often input from the programs user!).

Then a hacker may see this stack layout. They may find that feeding a certain string to part of your program may crash it. Or worse, they may actually construct a special string that returns "inside" itself, or to somewhere else they can write data, allowing them to start executing arbitrary code!

Moral of the story, never use c strings unless you are literally forced too.

Share this post


Link to post
Share on other sites
I love stories with lessons to be learned.....
So since the main function is the first and last function to be used, are all other function calls and their local variables, "stacked" on top of the main. Is the main function, the largest plate with each function reserved their own plate?

For the life of me, I can't get getline to read a line from my text file:
Isn't that format, getline(readFile,line) where readFile is my ifstream and line is my string

Share this post


Link to post
Share on other sites
Quote:
Original post by bluefox25
I love stories with lessons to be learned.....
So since the main function is the first and last function to be used, are all other function calls and their local variables, "stacked" on top of the main. Is the main function, the largest plate with each function reserved their own plate?

For the life of me, I can't get getline to read a line from my text file:
Isn't that format, getline(readFile,line) where readFile is my ifstream and line is my string


Well, the largest stack frame could be any function that has lots of locals. Most large applications have a pretty short main() function.

Incidentally, this stacking of frames is what allows functions to be recursive. For example:
void recurseTillZero( unsigned i ) {
if( i > 0 ) {
recureTillZero(i - 1);
} else {
std::cout << "got to zero\n";
}
}

int main( int argc, char **argv ) {
recurseTillZero(3);
}

Might have a stack like this:
--------------------------------------------
i = 0
return address recurseTillZero, line 2

--------------------------------------------
i = 1
return address recurseTillZero, line 2

--------------------------------------------
i = 2
return address recurseTillZero, line 2

--------------------------------------------
i = 3
return address main, line 1

--------------------------------------------
argv = 1
argc = {"myProgramsName.exe"}
return address for main

--------------------------------------------

What isn't working with std::getline for you? Post compile errors, or example code with the input file and what you expected to output versus what you actually output.

Share this post


Link to post
Share on other sites
I want to store each individual word into a variable but it isnt working

int main(){
using namespace std;
string word[100];
ifstream readFile("story.txt");//File contains blocks of text like paragraphs.
if(readFile.fail()){
cout << "File failed to open!";
exit(1);
}
getline(readFile,str);//Will this read words into word[0],word[55], etc?

cout << word[5];//Should output a word
//Suppose the 1st line of text is,
"I love baseball and beer nuts"
Shouldn't:
word[0]= "I"
word[1]= "love"
word[2]= "baseball"
word[3]= "and"
word[4]= "beer"
word[5]= "nuts"


I'd say Character I/O is the hardest thing I have encountered in my class, even arrays and pointers were not as hrd to undeerstand

}

Share this post


Link to post
Share on other sites
Quote:
Original post by bluefox25
I want to store each individual word into a variable but it isnt working
*** Source Snippet Removed ***
I'd say Character I/O is the hardest thing I have encountered in my class, even arrays and pointers were not as hrd to undeerstand

}


Not quite. First of all, you haven't declared a variable "str" anywhere.

But more to the point, std::getline stores a single line in a single string.
From there, we can parse it more.

Instead of the arbitrary limit of 100 strings in a line (which in most places will be far too much, but if it is ever too little then you'll be in trouble) we will use another std::container. I see you are already using std::string so you will be familiar with how they "just work" when it comes to sizes, they grow big enough anything you try fit in them. We have the equivalent for arrays in the form of std::vector. We can simply push_back something into the vector to add something. We can ask the std::vector how many elements it has, so we can iterator over it (or we could use iterators, but Ill try keep it as simple as possible):

#include <vector>
#include <string>
#include <fstream>
// other includes

// this example will read all the lines from the file
// and print them all.
int main() {
std::vector<std::string> lines;
std::ifstream readFile("story.txt");
std::string currentLine;
while( std::getline(readFile,currentLine) ) {
lines.push_back(currentLine);
}

// now in between here we might do something interesting.

for( int i = 0; i < lines.size() ; ++i ) {
std::cout << lines[i] << '\n';
}
}



Now we come to parsing the individual lines. The Standard C++ Library includes a class called std::stringstream. Its like a std::fstream, or std::cout/std::cin. But it works in memory, nothing need be printed or sent to a file. Also we can read and write to it. So we can throw in an string, and read it out a int.

Example:

// attempts to read the first item in the
// string as an integer
int intFromString( const std::string & input ) {
std::stringstream stream;
stream << input;
int value;
stream >> value;
return value;
}


This is a simple way to do string/integer conversions if you don't have boost.

It is used like so:

std::stringstream stream;
// a string with a string, int and float as an example:
stream << "jimmy 7 3.14";
std::string name;
int age;
float pi;

stream >> name >> age >> pi;
std::cout << "Person with name: " << name << " age: " << age << " and who thinks pi is " << pi << '\n';


Now, our needs are actually simpler. We have a bunch of words in a line.
We need to separate into a bunch of identical objects. We can store them in a std::vector instance to aid us.

std::vector<std::string> parse( const std::string &line )
{
std::vector<std::string> words;
std::stringstream stream;
stream << line;
std::string currentWord;
while( stream >> currentWord ) {
words.push_back(currentWord);
}
return words;
}



I hope you'll be able to build on this to do whatever you are trying.

Share this post


Link to post
Share on other sites
Thanks alot. That is interesting. I guess Im still learning about what techniques to best use. I try and break the problem down into small parts but sometimes I get stuck on what process to use to try and solve a subtask, sometimes I try and it works and other times it does not and I get frustrated. I will stick with it though, practice is the only wy to lear!! Trial and error.
For example, I am trying to write a simple loop to prompt a user to continue, what is the most efficient way to implement this? Within a function or in main?
I wrote this:

void promptToContinue(){
using namespace std;
char ans = 'Y'
cout << "Would you like to continue ?" << endl
<< "Press 'Y' for yes,'N' for no << endl;
cin >> ans;
if(ans =='Y'){
continue;
}else{
exit(1);
}
}


I got this code marked down b/c it needed the ans to be pass by reference param. How could I use ans referenced if I hadnot prompted user for an answer?
He probably wanted this: but how would this work?
 
void promptToContinue(ifstream& fin, char& choice){}


Share this post


Link to post
Share on other sites
Shouldn't this piece of code give me an error? It doesn't in DevC++


char cString1[] = "Man Utd won the Premiership in 2007!!!";

char cString2[] = "";

strcpy(cString2, cString1);

cout<< "cString1 = " << cString1 << endl;

cout<< "cString2 = " << cString2 << endl;



It outputs something like:
cstring1 = Man Utd won the Premiership in 2007!!!
cstring2 = Man Utd won the Premiership in 2007!!!

Share this post


Link to post
Share on other sites
Quote:
Original post by bluefox25
Shouldn't this piece of code give me an error? It doesn't in DevC++
*** Source Snippet Removed ***
It outputs something like:
cstring1 = Man Utd won the Premiership in 2007!!!
cstring2 = Man Utd won the Premiership in 2007!!!


Well, you're writing to areas of memory outside of the memory allocated for cString2, that is a very dangerous thing to do as you never know what might be stored there. I guess it was pure luck you didn't overflow or crash.

Share this post


Link to post
Share on other sites
I've been having some issues with DevC++ not catching errors that are caught in VSC++. I like using DevC++ b/c it is a small sized compiler and works well.
I thought it would cause a crash or error for the same reason. I am going to try on it VSC++ but I am almost sure it will blow up!!

Is there any way to correct this problem? Besides switching compilers

Share this post


Link to post
Share on other sites
Quote:
Original post by bluefox25
I've been having some issues with DevC++ not catching errors that are caught in VSC++. I like using DevC++ b/c it is a small sized compiler and works well.
I thought it would cause a crash or error for the same reason. I am going to try on it VSC++ but I am almost sure it will blow up!!

Is there any way to correct this problem? Besides switching compilers


The only reliable way to deal with the class of problem you just showed is not to create it in your code. Not only do neither of the compilers you mentioned *actually* catch it (if they could, you'd get an error when you tried to compile, not a crash when it runs), but playing around with the compiler options might cause it to "work" where it wasn't working before, or "stop working" where it was. And in fact, in the general case, it is impossible for the compiler writer to do anything about it. That's just how C++ is designed: you specify where to write things -ultimately - in terms of machine addresses, and the addresses you indicate don't necessarily correspond to the addresses you want, or even to memory that belongs to you.

Share this post


Link to post
Share on other sites
Thanks for all of your help guys. I would've been even more lost w/o our tips and explanations!! Just wrapped up my intro course and I will be receivingmy grade soon!!
On to Data Structures in the Fall.

So what now? I feel as if things are realy clicking in from all the stuff I learned from the start of the course up until now and I am eager to learn and practice more but I have no ideas on what to work on? I guess a game? Should I even attempt that yet or continue my pursuit of knowledge?

I had problems withh character I/O and reading lines of text and what not

How do I output different style fonts and colors in C++? Can you make text bold or in italics?

If I have a menu prompt the user, aftr their selection, how do I make the screen clear the menu and flash the new menu or text?

Share this post


Link to post
Share on other sites
Quote:
Original post by bluefox25
How do I output different style fonts and colors in C++? Can you make text bold or in italics?

If I have a menu prompt the user, aftr their selection, how do I make the screen clear the menu and flash the new menu or text?


You should check out this link.

Share this post


Link to post
Share on other sites

This topic is 3861 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this