控制流程跳回其他线路

时间:2015-02-20 18:02:35

标签: c++

在此代码中

void menu() {
    char name[MAXNAME];
    float a;
    char c;
    cout << "n\tnew transaction\n";
    cout << "v\tview all transactions\n\n";

    c = getchar();
    flushbuf();
    switch (c) {
    case 'N':
    case 'n':{
        cout << "What is the name? (press 'b' to go back to the menu)\n";
        fgets(name, sizeof name, stdin);
        replaceTrailingNl(name); // replaces trailing '\n' (from fgets) with '\0'

        if (strcasecmp(name, "b") == 0)
            menu();
        do {
            flushbuf();
            cout << "What is the amount?\n";
        } while (scanf("%f", &a) == 0);

        if (writeTransData(name, a))
            cout << "Successfully saved!\n";
        else
            cerr << "writeTransData: Error occurred\n";
        break;}
    }
}
void flushbuf()
{
    int temp;
    while ((temp = getchar()) != EOF && temp != '\n') ;
}

当输入'b'作为“名称是什么”提示的答案时,调用menu()(显示菜单),显示菜单然后按'n'创建一个新的交易。一切都按预期进行,直到breakbreak完成后,我得到“数量是多少?\ n”再次询问,我实际上可以输入内容。这是怎么回事?我做错了什么?

1 个答案:

答案 0 :(得分:2)

再次拨打menu()并不会结束当前对menu()的呼叫。呼叫#2将完成,控制流将返回呼叫#​​1并进入do循环。

最简单的解决方法是:

if (strcasecmp(name, "b") == 0) {
    menu();
    return;
}

但是,这是一个糟糕的设计,因为您正在使用递归和无用的堆栈。您可以使用goto

void menu() {
    char name[MAXNAME];
    float a;
    char c;

menu_prompt:
    cout << "n\tnew transaction\n";
    cout << "v\tview all transactions\n\n";

    c = getchar();
    flushbuf();
    switch (c) {
    case 'N':
    case 'n':{
        cout << "What is the name? (press 'b' to go back to the menu)\n";
        fgets(name, sizeof name, stdin);
        replaceTrailingNl(name);

        if (strcasecmp(name, "b") == 0)
            goto menu_prompt;

但是,通常,您将使用外部循环进行输入。然后,您将使用continuebreak,具体取决于您是否希望用户再次尝试。