Reputation: 31
I'm writing a game in c++ and i want it to output a string character by character and slow down the out put with the Sleep() function. The string is :
string output = "It is Super Effective!" + '\n';
when I try cout << output
it returns "r Effective"
with no new line
the code for the display function is
void textDisplay(string s){
s = " " + s;
for (int i = 0; i < s.size(); i++){
char c = s[i];
cout << c;
Sleep(20);
}
}
Upvotes: 3
Views: 129
Reputation: 283624
When the C++ compiler encounters an operator in your program, it performs overload resolution, just like for overloaded functions. Binary operator+
has many overloads, but you care about these two:
std::string operator+(std::string, char) // string concatenation
const char* operator+(const char*, std::ptrdiff_t) // pointer arithmetic
Other answers have explained what these two alternate meanings of +
are, I will show you how the compiler determines that the second meaning is better.
Your actual parameters have type const char[N]
and char
. The first argument can implicitly convert to const char*
using array-to-pointer decay, and to std::string
, by using array-to-pointer decay followed by a "user-defined conversion" (std::string
's implicit constructor). The second argument can convert to any other integral type, including std::ptrdiff_t
, via an implicit widening.
All the different types of conversions are ranked according to a table in the C++ Standard, and in this table, user-defined conversions are used only as a last resort. So the pointer arithmetic interpretation wins.
Upvotes: 3
Reputation: 881153
It's because "It is Super Effective!" + '\n'
is being interpreted as the pointer to the C-string plus the integral value of the character \n
, which is 10 in ASCII. This is happening before the assignment to the C++-string.
You'll see, if you count ten characters in from the start of your C-string, you do indeed end up at the r
.
So here's what's happening, in detail and sequence:
"It is Super Effective!"
is being interpreted as a char pointer to the initial I
character (a C-string).\n
) to that to get a pointer to the r
(still a C-string)."r Effective!"
is then being used to construct the C++-string.In graphical form:
base + 0: | I | -------+
base + 1: | t | |
base + 2: | | |
base + 3: | i | |
base + 4: | s | |
base + 5: | | Add ten
base + 6: | S | |
base + 7: | u | |
base + 8: | p | |
base + 9: | e | |
base + 10: | r | <------+
base + 11: | |
base + 12: | E |
:
base + 21: | ! |
base + 22: | \0 |
You can change it to add the character to the C++ string rather than the C string:
string output = "It is Super Effective!";
output += '\n';
but I'm not entirely certain why you wouldn't just do:
string output = "It is Super Effective!\n";
One other thing you may want to watch out for. It's possible that the flushing of characters to standard output will only occur when a newline is sent, meaning that you'll seem to get the entire string in one hit, some seven minutes or so after you expected the first character to appear.
If that happens, remember to flush the stream after every character:
cout << c << flush;
Upvotes: 9
Reputation: 70382
In this context, the +
is not joining the character to the string literal, but is returning a pointer value offset by \n
bytes. In ASCII, this would be 0x0A
, or 10. This is because the string literal is an array of const char
, which then decays to the address of its first element. The +
operator then offsets 10 characters past that element.
1
0 1 2 3 4 5 6 7 8 9 0
|I|t| |i|s| |S|u|p|e|r| |E|f|f|e|c|t|i|v|e|!|
You can correct this by initializing the string
first, and then appending.
string output = "It is Super Effective!";
output += '\n';
Or, you can use string literal concatenation, by dropping the +
and using "\n"
instead:
string output = "It is Super Effective!" "\n";
Or just make the whole thing a string, which would be most clear.
string output = "It is Super Effective!\n";
Upvotes: 3