-2

After trying for about 1 hour, my code didn't work because of this:

void s_s(string const& s, char data[10])
{
    for (int i = 0; i < 10; i++)
        data[i] = s[i];
}

int main()
{
    string ss = "1234567890";
    char data[10];
    s_s("1234567890", data);

    cout << data << endl;//why junk
}

I simply don't understand why the cout displays junk after the char array. Can someone please explain why and how to solve it?

SkyRipper
  • 155
  • 5
  • 15
  • Please include the output. Does it print '1234567890' and then junk, or only junk? `cout` prints everything up to the '\0' character, which is not present in your `data` array; thus it might print additional junk between '1234567890' and the next `\0` it bumps into in the memory. – EyalAr Dec 08 '13 at 03:23
  • it does printadditional junk after 0. – SkyRipper Dec 08 '13 at 03:25
  • There you go. Also, did you mean to write `s_s(ss, data);` in the 3rd line of your `main`? otherwise the `ss` string is useless. And, you send a `const char` to your `s_s` function, which actually expects to receive a const string reference.... – EyalAr Dec 08 '13 at 03:34

4 Answers4

6

You need to null terminate your char array.
std::cout.operator<<(char*) uses \0 to know where to stop.
Your char[] decays to char* by the way.

Look here.

Community
  • 1
  • 1
ScarletAmaranth
  • 5,065
  • 2
  • 23
  • 34
2

As already mentioned you want to NUL terminate your array, but here's something else to consider:

If s is your source string, then you want to loop to s.size(), so that you don't loop past the size of your source string.

void s_s(std::string const& s, char data[20])
{
    for (unsigned int i = 0; i < s.size(); i++)
        data[i] = s[i];
    data[s.size()] = '\0';
}

Alternatively, you can try this:

std::copy(ss.begin(), ss.begin()+ss.size(),
  data);
data[ss.size()] = '\0';

std::cout << data << std::endl;
  • @SkyRipper The first one is probably faster (don't take my word for it), but the second one is practically a one-liner. –  Dec 08 '13 at 03:11
  • This will fail, he does not have space to add the '\0' in data[10] – Glenn Teitelbaum Dec 08 '13 at 03:16
  • 1
    @Glenn Yeah, I changed it to `20`, although it is implied that he will change the buffer size. –  Dec 08 '13 at 03:18
2

You have ONLY allocated 10 bytes for data

The string is actually 11 bytes since there is an implied '\0' at the end

At a minimum you should increase the size of data to 11, and change your loop to copy the '\0' as well

Glenn Teitelbaum
  • 10,108
  • 3
  • 36
  • 80
0

The function std::ostream::operator<< that you are trying to use in the last line of the main will take your char array as a pointer and will print every char until the null sentinel character is found (the character is \0).

This sentinel character is generally generated for you in statements where a C-string literal is defined:

char s[] = "123";

In the above example sizeof(s) is 4 because the actual characters stored are:

'1', '2', '3', '\0'

The last character is fundamental in tasks that require to loop on every char of a const char* string, because the condition for the loop to terminate, is that the \0 must be read.

In your example the "junk" that you see are the bytes following the 0 char byte in the memory (interpreted as char). This behavior is clearly undefined and can potentially lead the program to crash.

One solution is to obviously add the \0 char at the end of the char array (of course fixing the size).

The best solution, though, is to never use const char* for strings at all. You are correctly using std::string in your example, which will prevent this kind of problems and many others.

If you ever need a const char* (for C APIs for example) you can always use std::string::c_str and retrieve the C string version of the std::string.

Your example could be rewritten to:

int main(int, char*[]) {
    std::string ss = "1234567890";
    const char* data = ss.c_str();
    std::cout << data << std::endl;
}

(in this particular instance, a version of std::ostream::operator<< that takes a std::string is already defined, so you don't even need data at all)

Shoe
  • 74,840
  • 36
  • 166
  • 272