使用getchar(常见,容易理解)
int c;
while ((c = getchar()) != EOF && c != '\n'); /* <note the semicolon! */
if (c == EOF) {
if (feof(stdin)) {
/* Handle stdin EOF. */
}
else {
/* Handle stdin error. */
}
}
使用fgets(不太常见,不易理解)
char buf[8];
while (fgets(buf, sizeof buf, stdin) != NULL) {
size_t len = strlen(buf);
/*
* Exit the loop if either EOF was encountered before '\n', or
* if '\n' is detected.
*/
if (len + 1 != sizeof(buf) || memchr(buf, '\n', len))
break;
}
if (feof(stdin)) {
/* Handle stdin EOF. */
}
else {
/* Handle stdin error. */
}
使用带有scanf 的扫描集(可能不常见,易于理解)
/*
* Combining the scanset with assignment suppression (the '*' before the
* scanset) will return EOF on EOF/error and 0 if '\n' was read.
*/
if (scanf("%*[^\n]") == EOF) {
if (feof(stdin)) {
// Handle stdin EOF.
}
else {
// Handle stdin error.
}
}
getchar(); // Flush the '\n'.
使用getline(可能不常见,困难)
char *buf = NULL;
size_t bufsize = 0;
ssize_t len;
/* getline() will stop reading on '\n' or EOF. */
len = getline(&buf, &bufsize, stdin);
/* No bytes read and EOF encountered, or there was an error. */
if (len == -1) {
if (feof(stdin)) {
/* Handle stdin EOF. */
}
else if (ferror(stdin)) {
/* Handle stdin error. */
}
else {
/* Handle errno error, if desired. */
}
/*
* The value of "buf" is indeterminate here, so you likely
* just want to return from the function/program at this point
* rather than continuing and potentially freeing an invalid
* buffer.
*/
}
free(buf);
当然,所有这些方法都假定您希望以不同于 \n 的方式处理发生在 EOF/错误上的事情,甚至可能所有这三种情况都是不同的情况。例如,通过将上述 sn-ps 之一放入自包含函数中,如果读取了 \n,您可能会返回 0,或者在 EOF/error 上返回 EOF,甚至在 \n 上返回 0, EOF 在 EOF 上,1 在错误上。
注意事项:
-
getchar 和 fgets 方法是 100% 跨平台的。我更喜欢 getchar 方法,因为它很简单。
- scanset 方法的跨平台性较差,只是因为并非所有编译器都实现了扫描集(因此不符合 C99)。
-
getline 方法也不是很跨平台:它主要在 GNU/Linux 和其他一些 POSIX 操作系统上实现;这不包括此时的 Windows。一旦你有一些管理内存和使用指针的经验,你自己写一个并不难,但你最好使用前两种方法之一,因为编写getline的实现可能最终会使用@ 987654342@ 或 fgets 无论如何(fgetc(stdin) 和 getchar() 的行为应该相同)。