我尝试使用 do while 循环来制作菜单并调用某个函数。但是当我重新输入字符变量“pick”时,它什么也没有返回。

int main() {
    char pick;
    int x;
    int *a;
    do {
        printf("Menu of task\n");
        printf("a.Generate an array:\n");
        printf("b.Sort a given array of names to increasing alphabet\n");
        printf("q.Quit\n");
        scanf("%c", &pick);
        getchar();

        switch (pick) {
            case 'a':
                printf("Input N:\n");
                scanf("%d", &x);
                a = tax(x);
               for (int i = 1; i <= x; i++)
                    printf("%d ", *(a + i)); 
               printf("\n");

                break;
            case 'b':
                printf("Nah:\n");
                break;
            case 'q':
                printf("Out!");

                break;
            default:
                printf("Wrong syntax\n");
                break;


        }
    }
        while (pick != 'q');

}

我不知道代码是否错误,或者其他地方是否错误,因为当我删除所有 scanf 时,它正常运行

6

  • 假设循环的第一次迭代将“a”读入pick。然后scanf("%d"...读取您以交互方式输入的数字,但不读取\n。在下一次迭代中,scanf("%c", &pick)读取\n,然后阻塞getchar。只需停止使用scanf


    – 

  • 或者写成scanf(" %c", ...(在 前有一个空格%c)。但是,真的,不要再使用 了scanf


    – 

  • 另外,用tax()可能出错的函数更新你的程序。C 中的数组从索引 0 开始,所以for(int i = 1; i <= x; i++)看起来不对


    – 


  • 1
    注意:*(a + i)=>a[i]


    – 

  • 1
    @Yunnosch 不用担心,这还不是一个很好的答案,在我删除答案之前,任何投反对票的人都会得到一个,直到它变得更好。


    – 


最佳答案
2

  1. 包含标题。

  2. 如果 (missing)tax()函数返回一个包含少于x+1个元素的数组,则循环for (int i = 1; i <= x; i++)是未定义的行为,因为 C 中的数组的索引是从0到 的x - 1

  3. 如果tax()函数分配一个数组,正如调用签名所建议的那样,那么您需要free()该数组,否则就会发生内存泄漏。

  4. 始终检查 I/O 操作的返回值,否则scanf()您可能正在操作未初始化的变量。或者更糟的是,如果输入流已关闭 ( EOF),则最终会陷入无限繁忙循环。

  5. 我建议您使用fgets()获取一行输入,然后通过直接访问数组或使用sscanf()而不是 来解析输入scanf()getchar()由于 stdin 是行缓冲的,因此可以提供更好的用户体验,而丢弃不理解的内容可以使您的程序更加健壮(例如,尝试在初始提示符下输入“a2q\n”)。

    在这种情况下,scanf("%d", &x);将把 留\n在输入缓冲区中,后续的scanf("%c", &pick);将读取它并将其视为无效输入。您可以使用 跳过前导空格。如果您选择这种方式,也scanf(" %c", &pick);请消除对 的调用。getchar()

  6. (未固定)考虑使用for(;;)循环并使用goto退出循环,使用if-else if ...而不是开关,以便使用 break 退出循环,或者调用exit()以避免在开关和循环条件中检查“q”。

  7. (部分修复)int x(重命名为n下文)大概用于分配数组中的元素数量。负数没有意义,因此请考虑unsigned(又名)或来自类似 的unsigned int合适类型。无论哪种情况,您都希望将其作为特殊情况处理,因为来自的返回值是实现定义的,并且可能为 NULL,因此您无法区分没有元素的数组和错误。inttypes.huint8_t0calloc(0, ...)

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

#define MAX_LINE 32

int *tax(int n) {
    if(n <= 0) return NULL;
    return calloc(n, sizeof(int));
}

int main(void) {
    char line[MAX_LINE];
    int n;
    int *a;
    do {
        printf(
            "Menu of task\n"
            "a. Generate an array:\n"
            "b. Sort a given array of names to increasing alphabet\n"
            "q. Quit\n"
        );
        if(!fgets(line, MAX_LINE, stdin))
            break;
        switch(*line) {
            case 'a':
                printf("Input N:\n");
                if(!fgets(line, MAX_LINE, stdin)) {
                    *line = 'q';
                    break;
                }
                int rv = sscanf(line, "%d", &n);
                if(rv != 1) {
                    printf("Invalid N\n");
                    continue;
                }

                a = tax(n);
                if(!a) {
                    printf("tax() failed\n");
                    *line = 'q';
                    break;
                }
                for (int i = 0; i < n; i++)
                    printf("%d ", a[i]);
                printf("\n");
                free(a);
                break;
            case 'b':
                printf("Nah:\n");
                break;
            case 'q':
                printf("Out!\n");
                break;
            default:
                printf("Wrong syntax\n");
                break;
        }
    }
    while (*line != 'q');
}

示例运行:

Menu of task
a. Generate an array:
b. Sort a given array of names to increasing alphabet
q. Quit
a
Input N:
a
Invalid N
Menu of task
a. Generate an array:
b. Sort a given array of names to increasing alphabet
q. Quit
a
Input N:
4
0 0 0 0 
Menu of task
a. Generate an array:
b. Sort a given array of names to increasing alphabet
q. Quit
b
Nah:
Menu of task
a. Generate an array:
b. Sort a given array of names to increasing alphabet
q. Quit
q
Out!

0

只需在 scanf() 函数中添加一个前导空格,您的问题就解决了。

scanf(" %c", &pick);

问题:

  • 当您不添加前导空格时,c 编译器将把\n(ASCII 值 10)作为输入。

  • 您可以通过打印 switch 语句末尾的值来检查这一点

      printf("The value: %d", pick); // will print 10
    
  • 当您添加前导空格时,编译器会跳过任何空格字符(包括换行符)。

1

  • 2
    也许指出是\nfromscanf("%d", &x);导致了问题,因为 op 使用fromgetchar()删除了您提到的调用?或者也许您假设 windows 是行终止符?\nscanf()\r\n


    –