【问题标题】:C switch statement bug regular case and default hitC switch 语句错误常规大小写和默认命中
【发布时间】:2019-11-25 06:51:57
【问题描述】:

在接触 Java 之后,我目前正在用 C 语言编写我的第一个程序,该程序的目的是模拟一个包含 10 个整数的堆栈。用户可以要求 push('u')、pop('o')、exit('x') 或更改输出格式。我的输出方式有一个错误,但我可以稍后处理。引起关注的主要原因是我在运行程序时得到了这个输出:

欢迎来到堆栈程序。

输入选项:u
什么号码? 1
堆栈:1
输入选项:无效字符。
输入选项:u
什么号码? 2
堆栈:1 2
输入选项:无效字符。
输入选项:u
什么号码? 3
堆栈:1 2 3
输入选项:无效字符。
输入选项:

如您所见,该程序允许我将项目压入堆栈并存储它们(pop 也可以),但每次提示用户输入新选项时,我的 switch 语句中都会出现无效字符大小写并错误地创建了一条多余的线。我知道可能需要更多的程序上下文,但我的 switch 语句有什么明显的错误吗?

#include <stdio.h>
#include <stdlib.h>

char currentOption;
int *printMode = 0;

//A program to simulate a stack data type of integers.
int main()
{
    printf("Welcome to the stack program.\n");
    printf("\nEnter option: ");
    scanf ("%c", &currentOption);

    while(currentOption != 'x')
    {
        processOption(currentOption);
        printf("\nEnter option: ");
        scanf ("%c", &currentOption);
    }
    return 0;
}

//interpret the user input character as one of several options
void processOption(char option)
{
    int storedValue;

    switch(option)
    {
        case 'u' : //push to stack
            printf("What number? ");
            scanf ("%d", &storedValue);
            if(push(storedValue) == 1)
            {
                printf("Overflow!!!");
            }
            else
            {
                printf("Stack: ");
                printStack(printMode);
            }
            break;
        case 'o' : //pop, return popped value
            pop(&storedValue);
            if(storedValue == NULL)
            {
                printf("Underflow!!!");
            }
            else
            {
                printf("Popped %d", storedValue);
                printf("\nStack: ");
                printStack(printMode);
            }
            break;
        case 'd' : //change print mode to decimal and print
            printf("\nStack: ");
            *printMode = 0;
            printStack(printMode);
            break;
        case 'h' : //change print mode to hex and print
            printf("\nStack: ");
            *printMode = 1;
            printStack(printMode);
            break;
        case 'c' : //change print mode to char and print
            printf("\nStack: ");
            *printMode = 2;
            printStack(printMode);
            break;
        case 'x' : //change print mode to char and print
            printf("Goodbye!");
            exit(EXIT_SUCCESS);
        default :
            printf("Invalid character." );
            break;
    }
}

提前感谢您的宝贵时间!

【问题讨论】:

  • 显示main()函数或processOption()的调用者
  • 'els :' 是标签语句,与 switch 语句无关。正确的格式是 ' default: ... break;
  • 编译时包含所有警告和调试信息 (gcc -Wall -Wextra -g)。使用调试器 (gdb)。阅读您正在使用的每个函数的文档。使用来自scanf的返回计数
  • ^^谢谢。我修复了这个问题,因为它与我的原始问题无关,并且可能会分散“%c”问题的注意力,但感谢您的关注。

标签: c debugging stack switch-statement


【解决方案1】:

main() 更改:

scanf ("%c", &currentOption);

scanf (" %c", &currentOption);

原因是在第一个输入之后输入的杂散换行符立即被紧随其后的scanf() 消耗。
要解决此问题,请在转换说明符之前使用空格。
%c 为前缀的空格告诉scanf() 跳过第一个杂散字符并仅使用之后输入的字符。

【讨论】:

  • 感谢您的修复!现在我已经修复了这个问题和我的退出错误,它工作得很好。
【解决方案2】:

主要问题是:

用户通过首先输入字符,然后按“返回”键来输入字符。

该键(换行符)仍在下一个循环顶部的缓冲区中,因此读取的内容也是如此。

该换行符是“空白”定义的一部分。

要消耗空白,像这样写scanf:

scanf (" %c", &currentOption);

注意到格式字符串中的前导空格了吗?格式字符串中的空格会导致在输入中的该点消耗空格。

此外,应始终检查 scanf() 和函数系列的返回值,以确保输入/转换操作成功。

【讨论】:

  • 感谢您的帮助!这是我的问题。还注意到我的退出功能有一个错误。希望这种类型的错误不会成为问题,因为我对语法有了更好的理解。
【解决方案3】:

我不认为你的 switch 语句有什么问题,而是你获取的地方有什么问题

char option

在我看来你正在做类似的事情

scanf("%c", &option);
processOption(option);

在一个循环中。当 processOption() 返回时,scanf 会在您按 Enter 时立即获取放入流中的换行符。 \n,当然,不是您的有效选项之一。因此,将您的 scanf 调用更改为类似

scanf(" %c", &option);

这会导致 scanf 跳过所有前导空格,包括换行符。这对于 scanf("%d", int) 不是必需的,因为空格显然对数值无效,但可能对字符有效。

【讨论】:

    【解决方案4】:

    是的,即使在 JAVA 扫描仪中,如果您扫描 int、double 之类的数字类型,它会一直读取直到遇到可选符号,然后继续读取直到遇到数字,然后继续读取数字,对于浮点数/双精度数小数点,直到读取其他内容,然后将其放回缓冲区中(总是有 1 的空间,请参见 man ungetc() )。因此换行符在缓冲区中等待下一次扫描输入。这是计算机按照您的要求进行操作的经典案例。您可以在格式中放置文字换行符 '\n' 以使 scanf 吃掉它,或添加某种虚拟读取,或将一行读入字符串/字符串/字符 [] 并使用 sscanf()/Scanner 进行扫描/>> !

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多