我尝试使用 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
最佳答案
2
-
包含标题。
-
如果 (missing)
tax()
函数返回一个包含少于x+1
个元素的数组,则循环for (int i = 1; i <= x; i++)
是未定义的行为,因为 C 中的数组的索引是从0
到 的x - 1
。 -
如果
tax()
函数分配一个数组,正如调用签名所建议的那样,那么您需要free()
该数组,否则就会发生内存泄漏。 -
始终检查 I/O 操作的返回值,否则
scanf()
您可能正在操作未初始化的变量。或者更糟的是,如果输入流已关闭 (EOF
),则最终会陷入无限繁忙循环。 -
我建议您使用
fgets()
获取一行输入,然后通过直接访问数组或使用sscanf()
而不是 来解析输入scanf()
。getchar()
由于 stdin 是行缓冲的,因此可以提供更好的用户体验,而丢弃不理解的内容可以使您的程序更加健壮(例如,尝试在初始提示符下输入“a2q\n”)。在这种情况下,
scanf("%d", &x);
将把 留\n
在输入缓冲区中,后续的scanf("%c", &pick);
将读取它并将其视为无效输入。您可以使用 跳过前导空格。如果您选择这种方式,也scanf(" %c", &pick);
请消除对 的调用。getchar()
-
(未固定)考虑使用
for(;;)
循环并使用goto
退出循环,使用if-else if ...
而不是开关,以便使用 break 退出循环,或者调用exit()
以避免在开关和循环条件中检查“q”。 -
(部分修复)
int x
(重命名为n
下文)大概用于分配数组中的元素数量。负数没有意义,因此请考虑unsigned
(又名)或来自类似 的unsigned int
合适类型。无论哪种情况,您都希望将其作为特殊情况处理,因为来自的返回值是实现定义的,并且可能为 NULL,因此您无法区分没有元素的数组和错误。inttypes.h
uint8_t
0
calloc(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也许指出是
\n
fromscanf("%d", &x);
导致了问题,因为 op 使用fromgetchar()
删除了您提到的调用?或者也许您假设 windows 是行终止符?\n
scanf()
\r\n
–
|
pick
。然后scanf("%d"...
读取您以交互方式输入的数字,但不读取\n
。在下一次迭代中,scanf("%c", &pick)
读取\n
,然后阻塞getchar
。只需停止使用scanf
。–
scanf(" %c", ...
(在 前有一个空格%c
)。但是,真的,不要再使用 了scanf
。–
tax()
可能出错的函数更新你的程序。C 中的数组从索引 0 开始,所以for(int i = 1; i <= x; i++)
看起来不对–
*(a + i)
=>a[i]
–
–
|