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

发布于 2024-11-29 15:28:12 字数 679 浏览 2 评论 0原文

我正在使用《使用 C++ 进行编程原理和实践》一书来学习编程,其中一个练习是使用 while 循环遍历字符 az。

现在,我之前已经使用 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 循环来完成,我也这样做了(它有效)。但我仍然不明白这段代码有什么问题,这真的很烦人。

看起来好像我已经告诉它输出“ch+1”,因为它在应该打印“a”的地方打印出“b”。直到 ch 的整数值被放入输出流(后增量)之后,增量才会完成。即使我之前增加了它,至少打印的字符和它们的整数值应该对应。

关于为什么这段代码不起作用的任何想法?

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 main(){
    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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

残花月 2024-12-06 15:28:12

运算符<< 调用的顺序已明确指定,但其操作数的求值顺序却未明确指定。

ch 的增量可能发生在“第一次”输出 ch 之前或之后,并且由于交错的读/写操作,仅仅运行该程序无论如何都是未定义的:

[2003: 1.9/12]: 完整表达式是一个不是
另一个表达式的子表达式。 [..]

[2003: 1.9/16]: 完成时有一个序列点
每个完整表达式的评估。

[2003: 5/4]: 除非另有说明,操作数的求值顺序
各个运算符和各个表达式的子表达式,
并且副作用发生的顺序未指定。
在前一个和下一个序列点之间,标量对象应
通过评估其存储值最多修改一次
表达。此外,先前的值只能被访问
确定要存储的值。本款的要求
应满足 a 的子表达式的每个允许的排序
充分表达; 否则行为未定义。


相反,要明确:

std::cout << ch << '\t' << int(ch) << std::endl;
++ch;

您的编译器应该就您的代码发出警告。这并不表明您没有将诊断设置在有用的级别。

对于 GCC,请使用 -Wall -Wextra -std=c++98 -pedantic (或对于 C++ 使用 -Wall -Wextra -std=c++0x -pedantic 0x)。

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).

南街九尾狐 2024-12-06 15:28:12

简短的回答是,您有一些未定义的行为,因为您在同一表达式中通过单独的子表达式修改和使用变量 ch 的值。

这里要做的正确的事情是使用最实用的循环来完成手头的任务:

#include <iostream>
int main(){
    for(char ch = 'a'; ch <= 'z'; ++a){
        std::cout << ch << '\t' << ch+0 << std::endl;
    }
}

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;
    }
}
深海少女心 2024-12-06 15:28:12

首先评估代码中的 ch++。更具可读性和正确性的版本是:

#include <iostream>
int main(){
    char ch = 'a';
    while(ch <= 'z') {
        std::cout << ch << '\t' << int(ch) << std::endl;
        ++ch;
    }
    return 0;
}

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;
}
丢了幸福的猪 2024-12-06 15:28:12

当您在一个命令或表达式中使用一个变量两次时,一次使用 ++(或 --),一次不使用,则会出现未定义的行为。

而是使用:

while(ch <= 'z')
{
   std::cout << ch << '\t' << (int) ch << std::endl;
   ch++;
}

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++;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文