You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++嵌套do-while与外层for循环异常问题排查

菜单驱动程序循环问题修复:解决无限循环与逻辑错误

问题根源分析

  1. 重复询问名字的逻辑错误:原代码在每次do-while循环迭代时都会请求用户输入名字,既不符合“一个用户输入一次名字、多次选品直到退出”的交互逻辑,还会因频繁调用cin.ignore()打乱输入缓冲区,引发后续读取异常,间接导致循环逻辑混乱。
  2. 输入缓冲区残留字符干扰:使用cin >>读取数字后,缓冲区会遗留换行符,后续getline会直接读取空行,导致名字输入异常,进而引发后续输入错误,让循环无法正常终止。
  3. 变量未初始化风险:mainChoice和subChoice未初始化,可能触发未定义行为,干扰循环判断逻辑。

修复后的完整代码

#include <iostream>
#include <string>
#include <iomanip>
#include <limits>

using namespace std;

int main() {
    // 变量声明与初始化
    string lineOfStars(60, '*');
    int numA1 = 0, numA2 = 0, numA3 = 0;
    int numD1 = 0, numD2 = 0, numD3 = 0;
    int numM1 = 0, numM2 = 0, numM3 = 0, numM4 = 0;
    double total = 0;
    string name;
    int numPeople;
    int mainChoice = 0;
    int subChoice = 0;

    // 打印标题
    cout << endl << lineOfStars << endl;
    cout << setw(40) << "HOGWARTS RESTAURANT";
    cout << endl << lineOfStars << endl;

    // 输入用餐人数
    cout << "How many people are included in your order? ";
    cin >> numPeople;
    // 清除输入后的换行符,避免干扰后续getline
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    // 用餐人数输入验证
    while(numPeople < 1 || numPeople > 3) {
        cout << "Oops! Please select 1, 2, or 3." << endl;
        cout << "How many people are included in your order? ";
        cin >> numPeople;
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }

    // 外层循环:遍历每个用户
    for(int i = 1; i <= numPeople; i++) {
        // 每个用户仅输入一次名字,移至do-while循环外
        cout << "Person " << i << ", what is your name? ";
        getline(cin, name);

        // 内层循环:当前用户的选品流程
        do {
            cout << "\nHi, " << name << ". What would you like to order?" << endl;
            cout << "1. Appetizer\n2. Drinks\n3. Meal\n4. I'm done!\n";
            cout << "Enter 1-4: ";
            cin >> mainChoice;
            cin.ignore(numeric_limits<streamsize>::max(), '\n');

            // 主菜单选项验证
            while(mainChoice < 1 || mainChoice > 4) {
                cout << "Oops! That isn't a valid choice." << endl;
                cout << "Enter 1-4: ";
                cin >> mainChoice;
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
            }

            // 处理主菜单选择
            switch(mainChoice) {
                case 1: // 开胃菜
                    cout << "\nGreat, you have selected Appetizer!" << endl;
                    cout << "Choose from the following appetizers:" << endl;
                    cout << "1. Dumbledonuts\t$2.99\n2. Potterfries\t$5.99\n3. Griffintoes\t$4.99\n";
                    cout << "Choose 1-3: ";
                    cin >> subChoice;
                    cin.ignore(numeric_limits<streamsize>::max(), '\n');

                    while(subChoice < 1 || subChoice > 3) {
                        cout << "Oops! That isn't a valid choice." << endl;
                        cout << "Choose 1-3: ";
                        cin >> subChoice;
                        cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    }

                    switch(subChoice) {
                        case 1:
                            cout << "How many Dumbledonuts do you want? ";
                            cin >> numA1;
                            cin.ignore(numeric_limits<streamsize>::max(), '\n');
                            total += (numA1 * 2.99);
                            break;
                        case 2:
                            cout << "How many Potterfries do you want? ";
                            cin >> numA2;
                            cin.ignore(numeric_limits<streamsize>::max(), '\n');
                            total += (numA2 * 5.99);
                            break;
                        case 3:
                            cout << "How many Griffintoes do you want? ";
                            cin >> numA3;
                            cin.ignore(numeric_limits<streamsize>::max(), '\n');
                            total += (numA3 * 4.99);
                            break;
                    }
                    break;
                case 2: // 饮品
                    cout << "\nGreat, you have selected Drinks!" << endl;
                    cout << "Choose from the following drinks:" << endl;
                    cout << "1. Polyjuice Potion\t$5.99\n2. Death Eater Negroni\t$6.99\n3. Butter Beer\t$4.99\n";
                    cout << "Choose 1-3: ";
                    cin >> subChoice;
                    cin.ignore(numeric_limits<streamsize>::max(), '\n');

                    while(subChoice < 1 || subChoice > 3) {
                        cout << "Oops! That isn't a valid choice." << endl;
                        cout << "Choose 1-3: ";
                        cin >> subChoice;
                        cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    }

                    switch(subChoice) {
                        case 1:
                            cout << "How many Polyjuice Potions do you want? ";
                            cin >> numD1;
                            cin.ignore(numeric_limits<streamsize>::max(), '\n');
                            total += (numD1 * 5.99);
                            break;
                        case 2:
                            cout << "How many Death Eater Negronis do you want? ";
                            cin >> numD2;
                            cin.ignore(numeric_limits<streamsize>::max(), '\n');
                            total += (numD2 * 6.99);
                            break;
                        case 3:
                            cout << "How many Butter Beers do you want? ";
                            cin >> numD3;
                            cin.ignore(numeric_limits<streamsize>::max(), '\n');
                            total += (numD3 * 4.99);
                            break;
                    }
                    break;
                case 3: // 主餐
                    cout << "\nGreat, you have selected Meal!" << endl;
                    cout << "Choose from the following meals:" << endl;
                    cout << "1. Griffinwings (10pcs)\t$10.99\n2. Voldenose\t$14.99\n3. Hufflemuffin\t$8.99\n4. Ravenclaw Meat\t$19.99\n";
                    cout << "Choose 1-4: ";
                    cin >> subChoice;
                    cin.ignore(numeric_limits<streamsize>::max(), '\n');

                    while(subChoice < 1 || subChoice > 4) {
                        cout << "Oops! That isn't a valid choice." << endl;
                        cout << "Choose 1-4: ";
                        cin >> subChoice;
                        cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    }

                    switch(subChoice) {
                        case 1:
                            cout << "How many Griffinwings (10pcs) do you want? ";
                            cin >> numM1;
                            cin.ignore(numeric_limits<streamsize>::max(), '\n');
                            total += (numM1 * 10.99);
                            break;
                        case 2:
                            cout << "How many Voldenoses do you want? ";
                            cin >> numM2;
                            cin.ignore(numeric_limits<streamsize>::max(), '\n');
                            total += (numM2 * 14.99);
                            break;
                        case 3:
                            cout << "How many Hufflemuffins do you want? ";
                            cin >> numM3;
                            cin.ignore(numeric_limits<streamsize>::max(), '\n');
                            total += (numM3 * 8.99);
                            break;
                        case 4:
                            cout << "How many Ravenclaw Meats do you want? ";
                            cin >> numM4;
                            cin.ignore(numeric_limits<streamsize>::max(), '\n');
                            total += (numM4 * 19.99);
                            break;
                    }
                    break;
                case 4: // 显式处理退出逻辑
                    cout << "\nThanks for your order, " << name << "!" << endl;
                    break;
            }
        } while(mainChoice != 4);
    }

    // 打印总金额
    cout << "\n" << lineOfStars << endl;
    cout << setw(30) << "TOTAL: $" << fixed << setprecision(2) << total << endl;
    cout << lineOfStars << endl;

    return 0;
}

核心修复说明

  • 调整名字输入逻辑:将名字输入移至do-while循环外,每个用户仅输入一次,符合正常交互流程。
  • 彻底清理输入缓冲区:每次使用cin >>读取数字后,调用cin.ignore(numeric_limits<streamsize>::max(), '\n')清除缓冲区所有残留字符,避免干扰后续getline读取。
  • 初始化变量:为mainChoice和subChoice赋初始值,消除未定义行为风险。
  • 完善退出逻辑:在switch中显式处理case4,提升代码可读性,明确退出流程。
  • 新增总金额打印:循环结束后输出订单总金额,完善程序功能完整性。

内容的提问来源于stack exchange,提问作者Atlaszzz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 12:40:56