在C ++中循环字符时出现意外结果

时间:2011-08-14 14:56:57

标签: c++ char cout post-increment

我正在使用“使用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的整数值放入流出后(后递增)之后才进行递增。即使我之前增加了它,至少打印的字符及其整数值也应该对应。

有关此代码无效的任何想法?

4 个答案:

答案 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++;
}