带有计数的for和while循环中的c++哨兵.陷入无限循环

C++ sentinel in a for and while loop with a count. Stuck in infinite loop

本文关键字:哨兵 c++ 无限循环 循环 while for      更新时间:2023-10-16

我一直陷入代码的无限循环中。我必须这样做,以便您可以使用哨兵'q'退出,但迭代次数不超过20次。任何帮助将不胜感激,因为我只是新的编程。

#include <iostream>
using namespace std;
int main()
{
    int option; // If new member or existing member or exit
    char SENTINEL = 'q';
while(option != SENTINEL)
{
    for(int count = 0; count <= 20; count++)
    {   
        // Display menu
        cout << "Welcome to the forum.n";
        cout << "Are you:n";
        cout << "1. A new membern";
        cout << "2. An existing member" << endl;
        cout << "To exit press 'q'n";
        cin >> option;
        if (option == 1)
        {
            char new_name[20]; // Array to hold new member 
            cout << "You're a new member.n"; 
            cout << "Please enter your first name followed ";
            cout << "by your last name.n";
            cout << "Then press return.n";
            cin >> new_name; // User enter their name
        }
        else if (option == 2)
        {
            cout << "You're an existing member." << endl;
        }
    } 
}
}

您需要做以下操作:

  1. 去掉while环。您需要使用一个具有多个条件的循环或循环内的break
  2. 使option为字符而不是int。比较optionSENTINEL是没有意义的,因为它们是不同的类型。把option改成char可以解决这个问题。
  3. 使用string类代替char数组的20个元素。任何名字和姓氏超过20个字符的人都会导致缓冲区溢出。string更安全,如果需要会自动展开。

#include <iostream>
#include <string>
using namespace std;
int main()
{
    char option; // If new member or existing member or exit
    char SENTINEL = 'q';
    for(int count = 0; count <= 20; count++)
    {   
        // Display menu
        cout << "Welcome to the forum.n";
        cout << "Are you:n";
        cout << "1. A new membern";
        cout << "2. An existing member" << endl;
        cout << "To exit press 'q'n";
        cin >> option;
        cin.get(); // discard newline char
        if (option == '1')
        {
            string new_name; // string to hold new member 
            cout << "You're a new member.n"; 
            cout << "Please enter your first name followed ";
            cout << "by your last name.n";
            cout << "Then press return.n";
            getline(cin, new_name); // User enter their name
        }
        else if (option == '2')
        {
            cout << "You're an existing member." << endl;
        }
        else if (option == SENTINEL) {
            break; // break from the loop
        }
    } 
}

检查这个:需要使用getchar()换行符

#include <iostream>
using namespace std;
int main()
{
    int option; // If new member or existing member or exit
    char SENTINEL = 'q';
while(option != SENTINEL)
{
    for(int count = 0; count <= 20; count++)
    {
        // Display menu
        cout << "Welcome to the forum.n";
        cout << "Are you:n";
        cout << "1. A new membern";
        cout << "2. An existing member" << endl;
        cout << "3. To exit press '3'n";
        cin >> option;
        getchar();
        if (option == 1)
        {
            char new_name[20]; // Array to hold new member
            cout << "You're a new member.n";
            cout << "Please enter your first name followed ";
            cout << "by your last name.n";
            cout << "Then press return.n";
            cin >> new_name; // User enter their name
        }
        else if (option == 2)
        {
            cout << "You're an existing member." << endl;
        }else if(option == 3)
        {
            exit(0);
        }
    }
}
}

for循环可以设置多个条件,以便在count超过20或option等于'q'时退出。它看起来像这样:

int main()
{
    int option; // If new member or existing member or exit
    char SENTINEL = 'q';
    for(int count = 0; ((count <= 20)&&(option != SENTINEL)); count++)
   {   
       // Display menu
       cout << "Welcome to the forum.n";
       cout << "Are you:n";
       cout << "1. A new membern";
       cout << "2. An existing member" << endl;
       cout << "To exit press 'q'n";
       cin >> option;
       if (option == '1')
       {
           char new_name[20]; // Array to hold new member 
           cout << "You're a new member.n"; 
           cout << "Please enter your first name followed ";
           cout << "by your last name.n";
           cout << "Then press return.n";
           cin >> new_name; // User enter their name
       }
       else if (option == '2')
       {
           cout << "You're an existing member." << endl;
       }
   } 

}

也测试for循环中的哨兵条件吗?

for(int count = 0; count <= 20 && option != SENTINEL; count++)

请注意,为了避免未定义的行为,您应该将option初始化为某个值(而不是SENTINEL),否则您将使用堆栈上剩余的任何垃圾。

首先:

option != SENTINEL这一行没有意义,你不能比较一个整数和一个字符,要么你使intchar数据类型

char new_name[20];更改为string array以节省很多麻烦。

另外,当用户输入q时,您应该退出循环或程序,所以为什么不使用exit(1)方法呢?

  char option ;
char SENTINEL = 'q';
while(option != SENTINEL)
{
    // Display menu
    cout << "Welcome to the forum.n";
    cout << "Are you:n";
    cout << "1. A new membern";
    cout << "2. An existing member" << endl;
    cout << "To exit press 'q'n";
    cin >> option; //<-- 1 and 2 will be char variable 
    if (option == '1')  
    {
        string new_name[20]; 
       for(int count = 0; count < 20; count++)
       {
        cout << "You're a new member.n"; 
        cout << "Please enter your first name followed ";
        cout << "by your last name.n";
        cout << "Then press return.n";
        cin >> new_name[count]; 
      }
    }
    else if (option == '2')
    {
        cout << "You're an existing member." << endl;
    }
    else if (option == 'q')
    {
       exit(1);   // to exit from the loop  
    }
} 

请你……

#include <iostream>
#include <string>
#include <limits>
int main() {
    char option;
    const char sentinel = 'q';
    bool quit = false;
    for(int count = 0; count <= 20 && !quit; count++) {   
        std::string name;
        bool invalid;
        do {
            invalid = false;
            // Display menu
            std::cout << "Welcome to the forum.n";
            std::cout << "Are you:n";
            std::cout << "1. A new membern";
            std::cout << "2. An existing membern";
            std::cout << "To exit press '" << sentinel << "'n";
            std::cin >> option;
            switch(option) {
                case '1':
                    std::cout << "You're a new member.n"; 
                    std::cout << "Please enter your first name followed ";
                    std::cout << "by your last name.n";
                    std::cout << "Then press return.n";
                    std::cin >> name;
                    break;
                case '2':
                    std::cout << "You're an existing member.n";
                    break;
                case sentinel:
                    quit = true;
                    break;
                default:
                    std::cout << "You entered invalid input!nn";
                    std::cin.clear();
                    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
                    invalid = true;
                    continue;
            }
        } while(invalid);
    }
    std::cout << "Exiting...n";
    return 0;
}

陷阱

你有几个问题…包括:

  • using namespace std;:任何一天都不是一个好主意。
  • 你的while()循环没有任何意义。它根本不会"覆盖"或以其他方式控制for循环。
  • 如果option类型为int,则它无法注意到sentinel的输入。std::cin会简单地设置fail位,你不会注意到它。
  • 你有一个char[20]。这是堆栈溢出/缓冲区溢出和其他微妙错误的糖,更不用说安全问题了……std::string修复了这个问题。
  • 布尔标志(如invalidquit)对于摆脱长嵌套循环很有用。
  • std::cin.clear()清除所有错误。同时,std::cin.ignore()允许您忽略之前垃圾输入行的所有内容。
  • "次要"设计问题无处不在。

我想补充一下其他的答案,因为

  1. 它们没有解释为什么当你使用"option"和integer而不是char时进入了一个无限循环。
  2. 仍可能存在不良行为。

1-)试试这个片段:

    int option=-1;
    cout<<"The initial value of option is: "<<option<<endl;
    cout<<"Input a new value, please: "<<endl;
    cin >> option;
    cout<<"After your input, it is: "<<option<<endl;

如果你输入一个数字(如123),它将正确接收它的值。如果你输入一个字母(比如q),它就会变成0。如果您键入数字和字母的混合,它将尝试从中提取一个数字,直到您到达一个字母(例如,如果您键入12q34, option将变为12,并且"q34"将保留在cin的缓冲区中)

在你的代码中,当你输入'q'时,cin将使option变为0,但不会忘记它的值。因此,在一次迭代之后,它不会再从你那里接受任何输入,因为它的内存中仍然有前一个值,并且不会删除它。


2-)那么你应该让选项一个字符吗?是也不是。如果你这样做,输入类似"123"的东西将创建一个名为"23"的新成员,因为你的程序将从"123"中获取"1",输入新成员的条件,自动转储"23"的名称,并立即返回到你的第一个提示符。如果这是可以接受的(如果你非常信任你的用户),那就继续吧。否则,使用std::string和它的比较方法