简体   繁体   English

为什么此C ++程序的输出会在cmd中产生巨大混乱?

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

I have since figured out how to make this program correct, but I was just wondering why this incorrect program for the question that follows produces just a whole bunch of characters and different machine information, and if such an error could damage the machine: 从那以后,我就想出了如何使该程序正确的方法,但是我只是想知道为什么这个不正确的程序会产生大量的字符和不同的机器信息,并且这种错误是否会损坏机器:

Exercise 3.10: Write a program that reads a string of characters including punctuation and writes what was read but with the punctuation removed. 练习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;
}

Now, I know it is incorrect, and have since made this version to correctly output what was needed: 现在,我知道它是不正确的,并且此后使该版本正确输出了所需的内容:

#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;
}

Why did the first one produce that mess of code? 为什么第一个产生这样的混乱代码? Also, when there is an if and no else, I thought that when it reaches an "empty" or non-existing else it stops; 另外,当有一个if if and no else时,我认为当它到达“空”或不存在时,它停止了; why, in the second program, does it successfully move on to the next character and restarts the loop after hitting an empty else? 为什么在第二个程序中,它成功移动到下一个字符并在击中其他空格后重新启动循环?

  • Your string is 15 characters long. 您的字符串长度为15个字符。
  • The incorrect code increments the character index by 2 on each iteration rather than by 1. 错误的代码在每次迭代中使字符索引增加2,而不是1。
  • You're only terminating the loop when the index is exactly equal to the length of the string (15) rather than testing an out-of-bounds condition. 您仅在索引恰好等于字符串的长度(15)时才终止循环,而不是测试越界条件。
  • When the character index is 14 (corresponding to the ' . ' character) the index is increment to 16, but the length of the string is 15, as 16 != 15 the loop continues and undefined memory past the end of the string is read and is written to the output stream. 当字符索引为14(对应于' . '字符)时,索引递增为16,但是字符串的长度为15,因为16 != 15 ,循环继续进行,并且读取字符串末尾的未定义内存并写入输出流。

你的字符串中有一个奇数个字符,因为你增加index由两个每次迭代, index始终为偶数,因此index != s.size()始终是真实的,你访问了索引范围,这是不确定的行为。

The first one is broken because your loop can simplify to: 第一个中断了,因为您的循环可以简化为:

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

Since s.size() is odd, you're marching past size() in your loop and your condition doesn't catch it... index is never == 15 , it goes from 14 to 16 and keeps going until something bad happens. 由于s.size()很奇怪,因此您要在循环中前进通过size() ,而您的条件却无法捕获到它…… index从不== 15 ,它从14变为16并一直持续下去直到出现问题发生。

You could've caught this with checking index < s.size() and noticing that you're only printing every other character. 您可以通过检查index < s.size()并注意到仅打印其他所有字符来捕获此index < s.size()

On your first code you are increasing index twice per iteration: once inside the if or the else clause; 在您的第一个代码中,每次迭代都增加两次索引:一次在if或else子句中; and once on the for iteration. 然后一次进行迭代。

Because of that, you are accessing values outside the string, thus printing garbage that is in your memory. 因此,您正在访问字符串外部的值,从而打印出内存中的垃圾。

To understand what's going on you should consider how strings are made, they are char pointers, so when you print a string you are literally iterating through the string and print every character until you find the \\0 char. 要了解正在发生的情况,您应该考虑如何构造字符串,它们是char指针,因此在打印字符串时,实际上是遍历字符串并打印每个字符,直到找到\\ 0 char。 In the first example you were incrementing the index multiple times so instead of moving to the next char you were moving to 2 chars so you were "exiting" the range of the string and reading some other memory as char or you could even have some Segmentation faults, in fact it's better to have the index < size condition. 在第一个示例中,您多次增加了索引,因此不是移至下一个字符,而是移至2个字符,因此您正在“退出”字符串的范围并以char形式读取其他内存,甚至可以进行一些细分错误,实际上最好使用index <size条件。

Anyway in c++ you can have an if without an else without any problems, so because you were inside a for loop and the exiting condition (index == size) wasn't met it increments the index variable and move to the next loop. 无论如何,在c ++中,如果没有else,就可以有一个if,而没有任何问题,因此,由于您处于for循环内,并且不满足退出条件(索引==大小),因此它将递增index变量并移至下一个循环。

if you wanted to have an else condition you could use the continue instruction. 如果您想要其他条件,可以使用继续指令。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM