我正在使用“使用C ++编程原理和练习”一书来学习编程,其中一个练习是使用while循环遍历字符a-z。
现在,我之前用C ++和其他语言编程,所以我决定尝试使用尽可能少的行(同时仍然使用while循环)。然而,这导致我的输出成本有些混乱。
代码:
#include <iostream>
int main(){
char ch = 'a';
while(ch <= 'z')
std::cout << ch << '\t' << (int) ch++ << std::endl;
return 0;
}
输出:
b 97
c 98
d 99
e 100
...
x 119
y 120
z 121
{ 122
现在我意识到这可以用for-loop完成,而且我也做了(它工作)。但是我仍然没有弄清楚这段代码有什么问题,这真让我烦恼。
看起来好像我已经告诉它输出“ch + 1”,因为它打印出'b',它应该打印'a'。直到将ch的整数值放入流出后(后递增)之后才进行递增。即使我之前增加了它,至少打印的字符及其整数值也应该对应。
有关此代码无效的任何想法?
答案 0 :(得分:5)
operator<<
调用的顺序是明确指定的,但其操作数的评估顺序不是。
ch
的增量可能在您第一次输出ch
之前或之后发生,并且由于交错的读/写操作,仅运行此程序仍然是未定义的:
[2003: 1.9/12]:
完整表达式是一个不是a的表达式 另一个表达式的子表达式。 [..]
[2003: 1.9/16]:
完成时有一个序列点 评估每个完整表达。
[2003: 5/4]:
除非另有说明,否则操作数的评估顺序除外 个体经营者和个人表达的子表达, 并且未指明副作用发生的顺序。 在前一个和下一个序列点之间,标量对象应该是 通过评估a,最多修改一次存储值 表达。此外,只能访问先前值 确定要存储的值。本段的要求 对于a的子表达式的每个允许排序,应满足 充分表达; 否则行为未定义。
相反,要明确:
std::cout << ch << '\t' << int(ch) << std::endl;
++ch;
您的编译器应该已经警告过您的代码。它没有表明您的诊断设置没有达到有用的水平。
使用GCC,使用-Wall -Wextra -std=c++98 -pedantic
(或-Wall -Wextra -std=c++0x -pedantic
表示C ++ 0x)。
答案 1 :(得分:2)
简短回答是你有一些未定义的行为,因为你在同一个表达式中通过单独的子表达式修改和使用变量ch
的值。
在这里做的正确的事(TM)是使用最实用的循环来完成手头的任务:
#include <iostream>
int main(){
for(char ch = 'a'; ch <= 'z'; ++a){
std::cout << ch << '\t' << ch+0 << std::endl;
}
}
答案 2 :(得分:2)
首先评估代码中的ch ++。更可读和更正确的版本是:
#include <iostream>
int main(){
char ch = 'a';
while(ch <= 'z') {
std::cout << ch << '\t' << int(ch) << std::endl;
++ch;
}
return 0;
}
答案 3 :(得分:1)
当你在一个命令或表达式中使用一个变量两次时,一次使用++(或 - )而一次使用没有,则会得到未定义的行为。
改为使用:
while(ch <= 'z')
{
std::cout << ch << '\t' << (int) ch << std::endl;
ch++;
}