Sign in to follow this  

Copying a string literal in a char array to a different char array

This topic is 2537 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

Finally decided to pick up programming for real, so I've been doing it for two weeks now (although last week I didn't get much done due to Christmas and stuff). The language is C++ and I'm using Xcode on my MacBook.

I have to "write a program that reads words from the keyboard to a char array. The program should then copy the text string in that char array to another char array". I'm not allowed to use strcpy.


const int max = 100;
char myArray[max];
string myString;

getline(cin, myString);
int size = myString.size();

for (int i = 0; i < size; i++)
myArray[i] = myString[i];




I'm not sure what code I should be using to copy the string to another array. In fact, I'm not entirely sure I'm doing this right, since my string is stored in a string object, and then I put each char in that string in a char array.


for (int i = 0; cin.get(c); i++)
myArray[i] = c;




Above code would be reading each char and store it directly in an array, but I don't know how to break this for-loop. If I wanted to break it once it reads a space character then I'd declare a variable char space = ' '; and then make something like: if (cin >> space) { break; } but that doesn't work either. Most likely because it reads one char at a time and pressing ENTER to execute the program would count as a space.


So, in short: How do I directly store what I type in in an array?

Thanks for any and all help!

[Edited by - Metallon on December 29, 2010 2:40:53 AM]

Share this post


Link to post
Share on other sites
Before trying to answer your other questions, I have a question about this:
Quote:
"write a program that reads words from the keyboard to a char array. The program should then copy the string literal in that char array to another char array".
How can words 'read from the keyboard' (presumably using std::cin) be in the form of a string literal? As far as I know, in C++, the term 'string literal' refers to a string that appears in double quotation marks in your code (there's more to it than that, of course, but that's the basic idea). So it's not immediately clear to me why text read from an input device at run time would be referred to as a string literal.

Where is this assignment from?

Share this post


Link to post
Share on other sites
Ugh, translation error, and it's 1 AM.

Let me rephrase. I'm supposed to type a word or many words. Whatever I type in should be stored in a char array. Then I need to copy whatever I typed in from that char array to a different char array.

The "problem" is from a book called C++ Direkt, it's a Swedish book.

Share this post


Link to post
Share on other sites
Quote:
Original post by Alpha_ProgDes
Well you should be using StringBuilder not String to grab the input from the keyboard.
I believe the language in question is C++.

Share this post


Link to post
Share on other sites
A lot of people will (correctly!) tell you that using char arrays to store strings is a bad idea.

This is because its really easy to make mistakes that cause major problems in your application like memory corruption, hard to debug intermittent crashes, and problems in unrelated areas of code.

But, since the book is giving you an assignment to use char arrays, that's sort of different than you going out of your way to use them (you should learn them eventually anyhow!).

Anyways...

Yes, its totally doable without a string builder and without strcpy.

how char * strings work (and how String strings work behind the scenes) is that they have 0 or more characters for the string and then a null character to mark that you've reached the end of the string. The null character is just literally a 0. It isn't '0' (the character 0), it's actually just 0 like this:

char cNull = 0; //this is the null character

So to copy a string from one array to another, you first make sure you have memory enough to store a copy of the string (it should be strlen(sourceString)+1 in size since strlen returns the length without the null character).

Next up, you loop through the source string starting at index 0 until you reach the null character in the source string.

For each iteration of the loop, copy the current positions character from the source string to the destination string.

Lastly, after the loop, make sure and put a null character at the end of your copy if you haven't already handled that.

Here's a little example to help you out!


const char *srcString = "This is a string";
char destString[100];
int nIndex = 0;

do
{
destString[nIndex] = srcString[nIndex];
nIndex++;
}
while(srcString[nIndex]);



There's plenty of stuff you'd wand to do in "the real world", like making sure srcString wasn't null before copying, and making sure destString was large enough to hold the source string, but hopefully this should give you an idea.

Also note that the loop above copies the null character so you don't need to explicitly add a null to the end of destString.

HTH!

Share this post


Link to post
Share on other sites
Quote:
Original post by Metallon
It should be doable without stringstream though, right?
By my understanding of the question, you aren't supposed to be using std::string either.

The exercise is to read characters from stdin (hint: use std::cin.get() to read a character), and store them in a char array (not a string). Once you have read in a newline character (indicating that you are done reading), you need to copy the contents of the first char array into a second char array (one character at a time).

Share this post


Link to post
Share on other sites
Yeah, I figured that using string objects (that's what they're called?) was kind of wrong for the exercise. Nevertheless, using it helped me get some experience with string objects so that's fine, but arrays I hear are a good thing to know about, but I also hear that char arrays mostly suck compared to string object (oh wait are they called string objects because they're objects of the string class? That makes sense.) Well how much they suck is relative I suppose and probably depends on when and how you use them but that's not important, I'm digressing.

Is there some "default" way of reading in a newline character, or is that something I'll have to figure out on my own? Getting really late here (3:30 AM) so I'm going to recharge my batteries and solve this tomorrow. I do have one question before I go to bed.


for (int i = 0; i < size; i++)
{
myArray[i] = myString[i];
otherArray[i] = myArray[i];
}





If you then std::cout otherArray it shows up with these odd things like /219 and /340 or something. Why?

I have a programmer friend that said that "using namespace std;" is the devil's invention. Good programming habits are welcome, so anything I can pick up along the way is just on the plus side.

This exercise really shouldn't be hard, I've found a way (I think) of making it read a char at a time and then store it in a char array, I just couldn't figure out how to break the loop the way I want it to. I should look into your post more, Atrix256, gave me idea to ditch the for-loop there and try a different type of loop.


BRB =D

Share this post


Link to post
Share on other sites
I think you should be able to do something like



char yourCharacterArray[] = howeveryougotyourarray;
//Depending on how much you are allowed to use
char outputArray[sizeof(yourCharacterArray)/sizeof(char)];
//or
char outputArray[strlen(yourCharacterArray)];
char* charPtr = yourCharacterArray;
int count = 0;
do{
//I'm not positive if I'm remembering when the ++ is applied
//in both these situations, but I think it's after both are already
//used. Someone will hopefully correct me if not.
//I'd probably break it into 2 or 3 lines in normal use.
outputArray[count++] = *charPtr++;
}while(*charPtr != 0);



can someone tell me how to add indents in this window? I hate opening up notepad to write code snippets because tab doesn't work :(

Share this post


Link to post
Share on other sites
@OP, an off topic post but how is developing in Xcode. I have a mac and use eclipse(java) but am debating whether to install it or not. I like eclipse but I also want to develop in C++, and there is a lot of trouble getting C++ to work with eclipse.

Share this post


Link to post
Share on other sites
Regarding null terminating: My book does mention it, however, not a single example in the book is shown how to do this. So I'm not really sure where I should include the \0, if anyone could clarify this, it would be very much appreciated.

Atrix256: Thank you for your code snippet, and your tips was very, very helpful without being outright explicit in what I should do. Is there any way to check the length of the string other than strlen? The exercise doesn't forbid me from using it, I'm just asking out of curiosity.

way2lazy2care: I just use spaces to indent, but I'm pretty sure that can get annoying the more you want to indent.

Concentrate: Several months ago, when I attempted to pick up programming again, I installed both NetBeans and Eclipse. I remember preferring NetBeans over Eclipse. However, back then I was doing my stuff in Java. I also currently have Mono (I installed it because I want to, at some point, check out C# a little, out of curiosity). I would pick Xcode over any of the three beforementioned. Any day. It looks better, feels better (all very subjective of course) but mostly I find it so easy to use. I remember spending days trying to get Eclipse to work before I kind of gave up. I'd highly recommend it, but I also recommend you ask someone more experienced who has been using it for more than two weeks.


std::cin.getline(myString, max);
int i = 0, size = std::strlen(myString) + 1;

do
{
firstArray[i] = myString[i];
i++;
} while (i < size);

for (int k = 0; k < size; k++)
secondArray[k] = firstArray[k];



How does this look? I use getline and put a max number, this should keep my string from being larger than I'll want it to be (and it automatically adds that '\0'). Then I put each char of that string into an array using that do while-loop, and then I use a for-loop to copy the elements of the first array to the second array.

Share this post


Link to post
Share on other sites
Quote:
Original post by Alpha_ProgDes
Quote:
Original post by Atrix256
The null character is just literally a 0. It isn't '0' (the character 0), it's actually just 0 like this:
char cNull = 0; //this is the null character
I thought the null character for a string was '\0'? Did that change? When?
IIRC, they are entirely equivalent.

Quote:
Original post by Metallon
Regarding null terminating: My book does mention it, however, not a single example in the book is shown how to do this. So I'm not really sure where I should include the \0, if anyone could clarify this, it would be very much appreciated.
In C (and by extension, C++), the end of a string is defined by a null byte. If the null byte isn't present as the last character in the string, printf doesn't know when to stop printing, and will continue into the garbage bytes beyond.

So basically, when you finish reading your string into the character array, you need to add a '\0' byte as the next character, and the same for the second char array, when you finish copying the string.

Share this post


Link to post
Share on other sites
Alright, would this be a valid way of adding the '\0':

(Assuming the do while-loop I posted above swiftcode's latest reply is finished and the following is the line of code immediately after):

char cNull = 0;
myArray[size] = cNull;


where size == (string + 1).

Share this post


Link to post
Share on other sites
What remains now is, I suppose, a confirmation that I'm adding the '\0' correctly to the array. That aside, I've compiled a program that does what I want, and it also copies the string to another array backwards (so if I type in Metallon, it prints out Metallon and then underneath nollateM.

It looks right to me as well.

Share this post


Link to post
Share on other sites
Quote:
Original post by Alpha_ProgDes
Quote:
Original post by Atrix256
The null character is just literally a 0. It isn't '0' (the character 0), it's actually just 0 like this:

char cNull = 0; //this is the null character

I thought the null character for a string was '\0'? Did that change? When?

the null char is '\0' but it's value is 0.

On my bit of code, I was trying to get around using a count variable, and didn't realize I ended up using one anyway before going to bed. if you change the line in the while loop to:


outputArray[count] = *yourCharacterArray[count++];

it should work and null terminate if the first string null terminates.

then just get rid of the char pointer all together.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
There are no sequence points in that code, and you modify count and use count in two different places. That adds up to bad juju.


If that was directed at me, then I'm sorry, I kind of didn't get that. Could you clarify what you said?

Share this post


Link to post
Share on other sites
I was referring to this line in way2lazy2care's post:

outputArray[count] = *yourCharacterArray[count++];

Quite often when you do more than one thing in a statement there are multiple ways the compiler can order the evaluation of expressions in that statement. For example, the compiler might do:

char * temp1 = outputArray + count;
char * temp2 = yourCharacterArray + count;
count = count + 1;
*temp1 = * temp2;

It could also do:

char * temp2 = yourCharacterArray + count;
count = count + 1;
char * temp1 = outputArray + count;
*temp1 = * temp2;

The result of executing one is different from the other, but either one is completely valid. Because count is modified in the statement and read in multiple places you can't predict what the compiler will do.

Incidentally, the idiomatic C string copy loop from a pointer src to a pointer dest looks like:

while (*dest++ = *src++);

Share this post


Link to post
Share on other sites
To get the length of a string without strlen you just loop through it, counting how many characters there are before you see the null character.

strlen returns the length not including the null character.

and yep! '\0' has a value of 0.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
I was referring to this line in way2lazy2care's post:

outputArray[count] = *yourCharacterArray[count++];

Quite often when you do more than one thing in a statement there are multiple ways the compiler can order the evaluation of expressions in that statement. For example, the compiler might do:

char * temp1 = outputArray + count;
char * temp2 = yourCharacterArray + count;
count = count + 1;
*temp1 = * temp2;

It could also do:

char * temp2 = yourCharacterArray + count;
count = count + 1;
char * temp1 = outputArray + count;
*temp1 = * temp2;

The result of executing one is different from the other, but either one is completely valid. Because count is modified in the statement and read in multiple places you can't predict what the compiler will do.

I don't believe that is the case unless the compiler doesn't follow C++ syntax.

count++ will always return the value count and then increment count.

http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Companion/cxx_crib/increment.html

Quote:
Incidentally, the idiomatic C string copy loop from a pointer src to a pointer dest looks like:

while (*dest++ = *src++);

This is what I was originally going to do, but I wasn't sure if incrementing the pointer would result in having to save the pointer in another variable and then incrementing that to copy so you wouldn't lose the start of the string.

Quote:
To get the length of a string without strlen you just loop through it, counting how many characters there are before you see the null character.

that's a slow way to do it. If you are using a char array to store the string you can just get the size of the array in bits and divide by the size of bits in a char in a single operation. You'll get O(1) instead of O(n).

edit: bytes not bits -_-

Share this post


Link to post
Share on other sites

This topic is 2537 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