我如何在不按 C 中的 enter 的情况下输入换行命令?
How do i put a newline command without pressing enter in C?
我在 Linux,使用 C99,我的问题是:我编写了一个基于整数的多选项。对于第一次迭代之后的每次迭代,输入比数组所需更多的整数将触发其他菜单选项,因为它们保留在缓冲区中。
我想避免 fflush(stdin)
函数,因为我读到它会导致未定义的行为,所以我尝试使用 while ((select = getchar()) != '\n')
,但在第一次迭代中,我需要按 Enter 键让菜单首先出现。我可以向缓冲区发送一个换行符来避免这个问题吗?
此外,我将 select
声明为 int
这是导致问题的代码部分:
for(;;) {
while ((select = getchar()) != '\n') { }
printf("\n\nWhat operation?\n1. Define array\n2. Delete element\n3. Add element\n4. Order array\n5. Randomize array\n6. Print array\n0. Exit\n");
scanf("%d", &select);
switch(select) {...}
在纯标准 C 中,您想要的可能是不可能的(当然定义不明确)并且不清楚。 C11 标准 n1570 does not know about terminals or keyboard (so about the enter key), but only about standard streams. See also 对与您的问题相近的问题的回答。
在实践中,如果你在某个 POSIX 系统上(我猜你在),终端有一个 line discipline managed by the kernel. However, the standard input might not be a terminal (with redirections or pipelines) and you could check if it is one by using isatty(3) 作为 isatty(STDIN_FILENO)
...
在这种情况下,我建议使用像 readline or ncurses 这样的库。
顺便说一句,您对 select
名称的使用令人困惑(因为 select(2) was an old system call, today superseded by poll(2))。
如果您受限于纯 C 标准函数,请仔细阅读 scanf, and use its return count. You certainly cannot (portably) put a newline (or any other characater) into some input stream like stdin
. But read carefully about ungetc 的文档。
我建议使用所有警告和调试信息进行编译(因此 gcc -Wall -Wextra -g
with GCC) and to learn to use the gdb
debugger 以了解程序的行为。
使用fgets 读取一行。使用 sscanf 解析行。解析整数和尾随非空白字符将允许检测整数后面的任何输入。
由于@chux 的评论
进行编辑以改进
#include <stdio.h>
int main ( void) {
char buffer[100] = "";
char extra = '[=10=]';
int scanned = 0;
int choice = 0;
do {
printf("\n\nWhat operation?\n1. Define array\n2. Delete element\n3. Add element\n4. Order array\n5. Randomize array\n6. Print array\n0. Exit\n");
if ( fgets ( buffer, sizeof buffer, stdin)) {
if ( 1 == ( scanned = sscanf ( buffer, "%d %c", &choice, &extra))) {// the space will consume whitespace and %c a non-whitespace character
printf ( "choice %d\n", choice);
if ( 0 > choice || choice > 6) {
scanned = 0;
}
}
if ( 1 != scanned) {
printf ( "\t\tenter a number 0 to 6\n");
}
}
else {
fprintf ( stderr, "problem fgets\n");
return 0;
}
} while ( 1 != scanned);
return 0;
}
我在 Linux,使用 C99,我的问题是:我编写了一个基于整数的多选项。对于第一次迭代之后的每次迭代,输入比数组所需更多的整数将触发其他菜单选项,因为它们保留在缓冲区中。
我想避免 fflush(stdin)
函数,因为我读到它会导致未定义的行为,所以我尝试使用 while ((select = getchar()) != '\n')
,但在第一次迭代中,我需要按 Enter 键让菜单首先出现。我可以向缓冲区发送一个换行符来避免这个问题吗?
此外,我将 select
声明为 int
这是导致问题的代码部分:
for(;;) {
while ((select = getchar()) != '\n') { }
printf("\n\nWhat operation?\n1. Define array\n2. Delete element\n3. Add element\n4. Order array\n5. Randomize array\n6. Print array\n0. Exit\n");
scanf("%d", &select);
switch(select) {...}
在纯标准 C 中,您想要的可能是不可能的(当然定义不明确)并且不清楚。 C11 标准 n1570 does not know about terminals or keyboard (so about the enter key), but only about standard streams. See also
在实践中,如果你在某个 POSIX 系统上(我猜你在),终端有一个 line discipline managed by the kernel. However, the standard input might not be a terminal (with redirections or pipelines) and you could check if it is one by using isatty(3) 作为 isatty(STDIN_FILENO)
...
在这种情况下,我建议使用像 readline or ncurses 这样的库。
顺便说一句,您对 select
名称的使用令人困惑(因为 select(2) was an old system call, today superseded by poll(2))。
如果您受限于纯 C 标准函数,请仔细阅读 scanf, and use its return count. You certainly cannot (portably) put a newline (or any other characater) into some input stream like stdin
. But read carefully about ungetc 的文档。
我建议使用所有警告和调试信息进行编译(因此 gcc -Wall -Wextra -g
with GCC) and to learn to use the gdb
debugger 以了解程序的行为。
使用fgets 读取一行。使用 sscanf 解析行。解析整数和尾随非空白字符将允许检测整数后面的任何输入。
由于@chux 的评论
#include <stdio.h>
int main ( void) {
char buffer[100] = "";
char extra = '[=10=]';
int scanned = 0;
int choice = 0;
do {
printf("\n\nWhat operation?\n1. Define array\n2. Delete element\n3. Add element\n4. Order array\n5. Randomize array\n6. Print array\n0. Exit\n");
if ( fgets ( buffer, sizeof buffer, stdin)) {
if ( 1 == ( scanned = sscanf ( buffer, "%d %c", &choice, &extra))) {// the space will consume whitespace and %c a non-whitespace character
printf ( "choice %d\n", choice);
if ( 0 > choice || choice > 6) {
scanned = 0;
}
}
if ( 1 != scanned) {
printf ( "\t\tenter a number 0 to 6\n");
}
}
else {
fprintf ( stderr, "problem fgets\n");
return 0;
}
} while ( 1 != scanned);
return 0;
}