简体   繁体   English

for和while循环中的C ++定点计数。 陷入无限循环

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

I keep getting stuck in an infinite loop with the code. 我一直陷入代码的无限循环中。 I have to make it so you can exit using the sentinel 'q' but not iterate more than 20 times. 我必须这样做,以便您可以使用前哨'q'退出,但不能重复20次以上。 Any help will be appreciated as I'm only new to programming. 任何帮助将不胜感激,因为我只是编程的新手。

#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 member\n";
        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;
        }
    } 
}
}

You need to do the following: 您需要执行以下操作:

  1. Get rid of the while loop. 摆脱while循环。 You need to use one loop that has multiple conditions or break from it within the loop. 您需要使用一个具有多个条件的循环,或者在循环中break它。
  2. Make option a char instead of an int . option设为char而不是int It doesn't make sense to compare option against SENTINEL because they are different types. optionSENTINEL进行比较没有意义,因为它们是不同的类型。 Making option a char will fix this problem. optionchar将解决此问题。
  3. Use the string class instead of char array with 20 elements. 使用string类代替具有20个元素的char数组。 Anyone whose first and last names are longer than 20 characters will cause a buffer overrun. 名字和姓氏长于20个字符的任何人都将导致缓冲区溢出。 string safer and will automatically expand if needed. 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 member\n";
        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
        }
    } 
}

Check this: Need to take newline character using getchar() 检查此:需要使用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 member\n";
        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);
        }
    }
}
}

You can have multiple conditions on your for loop so that it exits when count exceeds 20 or option equals 'q'. for循环上可以有多个条件,以便当count超过20或选项等于“ q”时退出。 It'll look something like this: 它看起来像这样:

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 member\n";
       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;
       }
   } 

} }

Test the sentinel condition in the for loop as well? 还要在for循环中测试前哨条件吗?

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

Note that to avoid undefined behavior, you should initialize option to some value (other than SENTINEL ) or you're working with whatever garbage was left on the stack. 请注意,为避免发生未定义的行为,应将option初始化为某个值( SENTINEL除外),否则,您将使用堆栈上剩下的任何垃圾。

First of all : 首先 :

option != SENTINEL this line does not make sense you cannot compare an integer to a character, either you make both variables int or char data types option != SENTINEL此行没有意义,您无法将整数与字符进行比较,因为您将两个变量都设置为intchar数据类型

Change char new_name[20]; 更改char new_name[20]; to an string array to save from a lot of trouble. 转换为string array可以避免很多麻烦。

In addition when the user inputs q you should exit from the loop or the program so why not use the exit(1) method. 另外,当用户输入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 member\n";
    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  
    }
} 

May you just... 愿你...

#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 member\n";
            std::cout << "2. An existing member\n";
            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!\n\n";
                    std::cin.clear();
                    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

                    invalid = true;
                    continue;
            }
        } while(invalid);
    }

    std::cout << "Exiting...\n";
    return 0;
}

Pitfalls 陷阱

You had several issues... including: 您遇到了几个问题...包括:

  • using namespace std; : Not a good idea any day of the week. :一周中的任何一天都不是个好主意。
  • Your while() loop didn't made any sense. 您的while()循环没有任何意义。 It simply wouldn't "override" or otherwise take control over the for loop. 它根本不会“覆盖”或以其他方式控制for循环。
  • If option is of type int , there's no way for it to notice the sentinel input. 如果option的类型为int ,则它无法注意到sentinel输入。 std::cin would simply set the fail bit and you would not notice it. std::cin只会设置fail位,而您不会注意到它。
  • You had a char[20] somewhere. 您在某处有一个char[20] That's sugar for stack overflows/buffer overruns and other subtle bugs, not to even mention security issues... std::string fixes that. 这可以解决堆栈溢出/缓冲区溢出和其他细微的错误,更不用说安全问题了…… std::string解决此问题。
  • Boolean flags (such as invalid and quit ) are useful to get out of long-nested loops. 布尔标志(例如invalidquit )对于摆脱长时间嵌套循环很有用。
  • std::cin.clear() cleans up any errors. std::cin.clear()清除所有错误。 Meanwhile, std::cin.ignore() allows you to ignore all the contents of a previous garbage input line. 同时, std::cin.ignore()允许您忽略上一个垃圾输入行的所有内容。
  • "Minor" design issues all over the place. “次要”设计问题到处都是。

I want to complement the other answers because 我想补充其他答案,因为

  1. they do not explain why you entered an infinite loop when you made "option" and integer instead of a char. 他们没有解释为什么当您使用“ option”和整数而不是char时,为什么会进入无限循环。
  2. there is still a possibly undesirable behaviour. 仍然可能存在不良行为。

1-) Try this snippet: 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;

If you input a number (like 123), it will receive it's value correctly. 如果输入数字(如123),它将正确接收其值。 If you type a letter (like q), it will become 0. If you type a mix of numbers and letters, it will try to extract a number from it until you reach a letter ( say, if you type 12q34, option will become 12 and "q34" will remain in cin's buffer) 如果键入字母(例如q),它将变为0。如果键入数字和字母的混合字母,它将尝试从中提取一个数字,直到找到一个字母为止(例如,如果键入12q34,则选项将变为12和“ q34”将保留在cin的缓冲区中)

In your code, whenever you type 'q', cin will make option go to 0, but won't forget its value. 在您的代码中,无论何时键入“ q”,cin都会使option变为0,但不会忘记其值。 So after an iteration, it won't take any input from you anymore because it still has the previous value in its memory and won't get rid of it. 因此,在迭代之后,它将不再从您那里获取任何输入信息,因为它在内存中仍具有先前的值,并且也不会摆脱它。


2-) So should you make option a char? 2-)所以你应该选择一个字符? Yes and no. 是的,没有。 If you do, typing something like "123" will create a new member with the name "23", because your program would take the '1' from "123", enter the conditional for a new member, automatically dump "23" to name and immediately go back to your first prompt. 如果这样做,则键入类似“ 123”的名称将创建一个名称为“ 23”的新成员,因为您的程序将从“ 123”中获取“ 1”,输入新成员的条件,然后自动将“ 23”转储至命名并立即返回您的第一个提示。 If that's acceptable( if you trust your user that much), go ahead. 如果可以接受(如果您非常信任用户),请继续。 Otherwise, use something like std::string and it's compare method. 否则,使用类似std :: string之类的东西,它是compare方法。

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

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