[try Beta version]
Not logged in

 
Enquiry about cout for char

Mar 7, 2018 at 12:51pm
Third cout statement prints two Hello instead of one!!!


#include <iostream>
#include <string>
using namespace std;
//Ctrl+Shift+C to comment
//Ctrl+Shift+X to uncomment

int main()
{
char foo[] = "Hello";
char bar[] = "World!";
char foo1[6] = "Hello";
char myword[5] = {'H','e','l','l','o'};
//char once initialized cannot be assigned values (again)
cout<<foo<<endl;
cout<<bar[0]<<endl;
cout<<myword<<endl;
cout<<myword[0]<<endl;

cout<<sizeof(foo)<<endl;
cout<<sizeof(foo1)<<endl;

string monkey ("My name is");
string house ("Mohammad");
string monkeys = monkey +" " + house; //Try concatenation
cout<<monkeys<<endl;

return 0;
}
Mar 7, 2018 at 1:52pm
Well, I get that output, actually.

1
2
3
4
5
6
7
8
9
10
11
xxx@yyy:~/Android$ c++ test.cpp
xxx@yyy:~/Android$ ./a.out
Hello
W
Hello
H
6
6
My name is Mohammad
xxx@yyy:~/Android$ 
Mar 7, 2018 at 1:54pm
The cout << operator assumes the string is null terminated (i.e. ends with '\0').

This should work better:
 
char myword[6] = {'H','e','l','l','o','\0'};
Mar 7, 2018 at 1:57pm
A C-string needs to be null-terminated (char '\0'). The third cout statement will keep writing out chars until it reaches one (i.e. it will continue into whatever is next in memory).

If you want to see what it is doing change the foo1 definition (or perhaps the foo definition) to
char foo1[6] = "Hiyah";

If you want to fix the problem change your myword statement to
char myword[6] = {'H','e','l','l','o','\0'};

Note that if you want it to be a null-terminated C-string (and that is what you are doing here) then the size of the array needs to be large enough to include that null character.
Mar 7, 2018 at 6:35pm
OK, the terminating character is clear to me, but then I don't get why the compiler of mine (gcc 5.4.0, ubuntu, amd64) doesn't put it out twice, but adds that


sign to the end (seems like it has been destroyed by copy and paste in my post above)?
Last edited on Mar 7, 2018 at 6:36pm
Mar 7, 2018 at 6:55pm
Shouldn't the compiler add the '\0' to the char array?
When I run the following code on the shell it prints Hello world as expected. http://cpp.sh/7auzi
1
2
3
4
5
6
7
8
#include <iostream>

int main()
{
  char msg[] = "Hello world";
  
  std::cout << msg;
}
Mar 7, 2018 at 7:03pm
Shouldn't the compiler add the '\0' to the char array?

Only if you initialize the array with a string. If you initialize your array with single characters you need to be sure that you add the terminating character if you actually want a string, remember it is perfectly acceptable to have an array of char that is not terminated (not a string).

Mar 7, 2018 at 9:39pm
all the standard C functions for strings maintain the terminal zero. Hands on manipulation or using things like memcpy instead of strcpy won't. string solves the problem by doing it for you as well.

you can also initialize it with

sprintf(msg,"hello world"); //this is more powerful as you can inject variables into the string.
or
strcpy(msg, "hello world"); //less powerful.

Mar 7, 2018 at 11:07pm
all the standard C functions for strings maintain the terminal zero.

No, all the C-string functions require C-strings (terminated arrays of char), if you call the C-string functions without a C-string you invoke undefined behavior.

Mar 8, 2018 at 2:08pm
Maintain = terminal is there going in, the function processes the array, and it returns an array with a correct terminal after. They correctly maintain it. If it isn't there going in, there is nothing to maintain.

this is the answer to


Shouldn't the compiler add the '\0' to the char array?

the compiler does not do anything at all, but if you use the string routines, it maintains the \0 if it was there to begin with. If its not there to begin with, its simply wrong; correct the initializer for the 'string'.

the reason nothing is done for you is that it is perfectly ok to have an array of data as bytes via char data[10000] or whatever. this isnt a string, but its the same syntax, and the compile can't second guess you.
Last edited on Mar 8, 2018 at 2:11pm
Mar 8, 2018 at 3:19pm
> all the standard C functions for strings maintain the terminal zero.

>> Maintain = terminal is there going in, the function processes the array, and it returns an array with a
>> correct terminal after. They correctly maintain it. If it isn't there going in, there is nothing to maintain.

Not necessarily.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <cstring>

int main()
{
    const char srce[] = "hello world!!!" ;
    char dest[8] = "fine!!\n" ; 

    std::cout << sizeof(dest) << ' ' << std::strlen(dest) << ' ' << dest << '\n' ; // fine (dest is null terminated)

    // dest is null terminated "going in" (though this is not required by std::strncpy)
    std::strncpy( dest, srce, sizeof(dest) ) ;
    // dest is not null terminated "coming out" (the null terminator is not maintained)

    // microsoft: *** warning: The prior call to 'strncpy' might not zero-terminate string 'dest'.
    // (note that null-terminating dest would have been a gross violation of both the C and the C++ standards)
    // undefined behaviour (dest is not null terminated)
    // for instance, strlen(dest) may return a value greater than the entire size of the array
    std::cout << sizeof(dest) << ' ' << std::strlen(dest) << ' ' << dest << '\n' ; 
}

http://rextester.com/IQEP26266
Mar 8, 2018 at 6:52pm
That's what I have been confused about as well because I got "Hello World", followed by an extra character I can't explain myself :-)
Mar 9, 2018 at 3:19am
> followed by an extra character I can't explain myself :-)

It is undefined behaviour.
"Undefined behaviour: Renders the entire program meaningless ..." http://en.cppreference.com/w/cpp/language/ub
Mar 10, 2018 at 6:23pm
Ah! Thanks ;-) I see, I never stop learning :-D
Topic archived. No new replies allowed.