为什么这个C++程序的输出在cmd中产生了巨大的混乱

Why does the output of this C++ program produce a giant mess in cmd?

本文关键字:cmd 产生了 混乱 巨大 输出 C++ 程序 为什么      更新时间:2023-10-16

我已经想好了如何使这个程序正确,但我只是想知道为什么这个不正确的程序只会产生一大堆字符和不同的机器信息,以及这样的错误是否会损坏机器:

练习3.10:编写一个读取字符串的程序包括标点符号和书写所读内容,但使用标点符号已删除。

#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;

int main()
{
    string s("Some! string!s.");
     for (decltype(s.size()) index = 0;
        index != s.size(); ++index){
            if (!ispunct(s[index])){
                cout << s[index];
                ++index;
            }
            else {
                ++index;
            }
        }
    return 0;
}

现在,我知道这是不正确的,并且已经制作了这个版本来正确地输出所需的内容:

#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;

int main()
{
    string s("Some! string!s.");
     for (decltype(s.size()) index = 0;
        index != s.size(); ++index){
            if (!ispunct(s[index])){
                cout << s[index];
            }
        }
    return 0;
}

为什么第一个产生了那么混乱的代码?此外,当存在if而没有else时,我认为当它达到"空的"或不存在的else时就会停止;为什么在第二个程序中,它成功地移动到下一个字符,并在命中空的else后重新启动循环?

  • 你的字符串有15个字符长
  • 错误的代码在每次迭代中将字符索引增加2,而不是1
  • 只有当索引恰好等于字符串(15)的长度时,才终止循环,而不是测试越界条件
  • 当字符索引为14(对应于"."字符)时,索引将增加到16,但字符串的长度为15,因为16 != 15循环继续,并且读取字符串末尾之后的未定义内存并将其写入输出流

您的字符串有奇数个字符,因为每次迭代都会将index增加两个,所以index总是偶数,因此index != s.size()总是true,并且您访问的索引超出范围,这就是Undefined Behavior。

第一个被破坏,因为您的循环可以简化为:

for (size_t index = 0; index != s.size(); ++index) {
    ++index;
}

由于s.size()很奇怪,你在循环中经过size(),但你的条件没有抓住它……index从来都不是== 15,它从1416,一直持续到发生不好的事情。

您可以通过检查index < s.size()并注意到您只打印每隔一个字符来发现这一点。

在第一个代码中,每次迭代增加索引两次:一次在if或else子句中;在for迭代上一次。

因此,您正在访问字符串之外的值,从而打印内存中的垃圾。

要了解发生了什么,您应该考虑字符串是如何生成的,它们是字符指针,所以当您打印字符串时,您实际上是在遍历字符串并打印每个字符,直到找到\0字符。在第一个例子中,你多次递增索引,所以你不是移动到下一个字符,而是移动到2个字符,所以你"退出"字符串的范围,并以字符的形式读取一些其他内存,或者你甚至可能有一些Segmentation错误,事实上,最好是索引<尺寸条件。

无论如何,在c++中,你可以有一个if而没有else,而不会有任何问题,所以因为你在for循环中,并且不满足退出条件(index==size),所以它会增加索引变量并移动到下一个循环。

如果您想要其他条件,可以使用continue指令。