【问题标题】:Why does my program go into endless loop when char array is overfilled?为什么我的程序在 char 数组过满时进入无限循环?
【发布时间】:2020-09-09 17:07:20
【问题描述】:

我正在尝试用 C++ 编写一个程序,让用户在固定大小的数组中输入一个正整数和一个名称并将它们打印出来。当我从第一次启动程序时输入正确的数据时,该程序似乎可以正常工作。

我遇到的问题是为 Char 数组输入不正确的值(超过字符数)。如果我为 char 数组输入了不正确的值,它会按预期给出警告消息,但是一旦我输入了正确大小的字,程序就会进入无限循环,询问已经输入的值。 我的代码如下:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    int count = 1;
    int num = 0; // variable for positive integer
    char name[31]; //char array to store name inside

    while(count != 0){

        cout << "Please enter the number: " << endl;
        cin >> num;
        while(num < 1){
            cout << "Number must be a positive integer!" << endl;  //Loop that checks whether the 
            cin >> num;                                           // entered number is a positive 
        }                                                        //  integer.

        cout << "Please enter the name: " << endl;
        cin >> name;
        while(strlen(name) > 30){                                        //Loop that checks whether the
           cout << "Name exceeds the allowed character count!" << endl; //entered name exceeds the
           cin >> name;                                                // allowed character count.
        }

        --count;
    };

    cout << num << " " << name;

    return 0;
}

我试图了解如果我先输入错误值然后输入正确值,为什么我的程序会进入无限循环?是否与超出数组的字符数有关?

任何帮助将不胜感激,非常感谢!

【问题讨论】:

  • 如果超过了name 数组的大小,这是未定义的行为。您的代码基本上是在尝试检查 UB,这是不可能的。
  • 这就是为什么基本上每个人都使用std::string而不是固定大小的数组。
  • en.cppreference.com/w/cpp/language/ub - 也请阅读底部的链接。
  • 写入超出name 的范围会覆盖堆栈上的count,从而导致“无限”循环。只是一个可能的解释,在汇编/指令级别会发生什么。
  • @David 这是 UB,简单明了。 任何行为都是可能的。您甚至真的无法尝试对此进行推理。你不应该真的尝试。修复 UB 是唯一明智的方法。

标签: c++ arrays loops while-loop


【解决方案1】:

这个循环有问题:

 while(strlen(name) > 30) {                                        //Loop that checks whether the
       cout << "Name exceeds the allowed character count!" << endl; //entered name exceeds the
       cin >> name;                                                // allowed character count.
 }

如果'\0' 后面有 31 个字符后跟strlen() 将返回 31。所以这已经超过了你的 31 个元素的长数组可以容纳的东西。但这不是最小的问题 - 一旦从 cin 加载的字符超过数组的大小,您就会遇到一个未定义的行为领域 - 从 C++17 开始,cin 会很高兴地写入超过 c 的容量-style 数组,如果你告诉它这样做的话。

我建议您使用 std::strings 而不是原始 C 数组。他们会为您处理以 null 结尾的字符串技术问题。

【讨论】:

  • 读取char * 将始终在输入末尾附加'\0',这里没问题。唯一的问题是越界写入,因为您不可能从指针检查数组的长度。 C++17 对这一事实没有任何改变,但在 C++20 中行为将发生变化(char * 的重载将被完全删除)。
  • @churill 感谢您指出这一点。在我发布这种废话之前,我真的应该开始检查 cppreference 上的所有内容。
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 2011-04-19
  • 1970-01-01
  • 1970-01-01
  • 2012-12-10
相关资源
最近更新 更多