Unexpected result when looping chars in C++
I'm using the book "Programming Principles and Practice using C++" to learn programming and one of the exercises is looping through the characters a-z using a while-loop.
Now, I have programmed with C++ and other languages before, so I decided to try to use as few lines as possible (while still using a while-loop). However, this came with the cost of my output being kind of messed up.
Code:
#include <iostream>
int mai开发者_StackOverflow中文版n(){
char ch = 'a';
while(ch <= 'z')
std::cout << ch << '\t' << (int) ch++ << std::endl;
return 0;
}
Output:
b 97
c 98
d 99
e 100
...
x 119
y 120
z 121
{ 122
Now I do realize that this could've been done with a for-loop instead, and I did that as well (it worked). But I still don't get what's wrong with this code, and it's really annoying me.
It appears as if I've told it to output "ch+1", since it prints out 'b' where it should print 'a'. The incrementing isn't done until after the integer value of ch has been put into the out-stream (post-increment). And even if I had incremented it earlier, at least the printed characters and their integer values should correspond.
Any ideas of why this code isn't working?
The order of the operator<<
calls is well-specified, but the order in which their operands is evaluated is not.
The increment of ch
may happen before or after you output ch
"the first time", and merely running this program is Undefined anyway because of the interleaved read/write operations:
[2003: 1.9/12]:
A full-expression is an expression that is not a subexpression of another expression. [..]
[2003: 1.9/16]:
There is a sequence point at the completion of evaluation of each full-expression.
[2003: 5/4]:
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.
Instead, be explicit:
std::cout << ch << '\t' << int(ch) << std::endl;
++ch;
Your compiler should have warned you about your code. That it didn't indicates that you do not have your diagnostics set at a useful level.
With GCC, use -Wall -Wextra -std=c++98 -pedantic
(or -Wall -Wextra -std=c++0x -pedantic
for C++0x).
Short answer is that you have a bit of Undefined Behavior because you're both modifying and using the value of the variable ch
, via separate sub-expressions, in the same expression.
The Right Thing(TM) to do here is to use the most practical loop for the task at hand:
#include <iostream>
int main(){
for(char ch = 'a'; ch <= 'z'; ++a){
std::cout << ch << '\t' << ch+0 << std::endl;
}
}
The ch++ in your code gets evaluated first. A more readable and correct version would be:
#include <iostream>
int main(){
char ch = 'a';
while(ch <= 'z') {
std::cout << ch << '\t' << int(ch) << std::endl;
++ch;
}
return 0;
}
When you use one variable twice in one command or expression, once with ++ (or --) and once without, you get undefined behavour.
Instead use:
while(ch <= 'z')
{
std::cout << ch << '\t' << (int) ch << std::endl;
ch++;
}
精彩评论