简体   繁体   English

如何从 C 中的标准输入读取多行字符串?

[英]How to read multiple lines of string from stdin in C?

I am a novice in C programming.我是 C 编程的新手。 Suppose I want to read multiple lines of string from stdin.假设我想从标准输入读取多行字符串。 How can I keep reading until a line only containing EOL?我如何才能继续阅读直到仅包含 EOL 的行?

example of input输入示例

1+2\n
1+2+3\n
1+2+3+4\n
\n (stop at this line)

It seems that when I hit enter(EOL) directly, scanf won't execute until something other than just EOL has been entered.似乎当我直接按 enter(EOL) 时, scanf将不会执行,直到输入 EOL 以外的其他内容。 How can I solve that problem?我该如何解决这个问题?

I'll be really grateful if someone can help me with this.如果有人可以帮助我,我将不胜感激。 Thank you.谢谢你。

If you want to learn C, you should avoid scanf .如果你想学习 C,你应该避免scanf The only use cases where scanf actually makes sense are in problems for which C is the wrong language. scanf真正有意义的唯一用例是 C 是错误语言的问题。 Time spent learning the foibles of scanf is not well spent, and it doesn't really teach you much about C.花在学习 scanf 弱点上的时间并没有得到很好的利用,而且它并没有真正教给你很多关于 C 的知识。 For something like this, just read one character at a time and stop when you see two consecutive newlines.对于这样的事情,一次只读一个字符,当你看到两个连续的换行符时停止。 Something like:就像是:

#include <stdio.h>

int
main(void)
{
        char buf[1024];
        int c;

        char *s = buf;

        while( (c = fgetc(stdin)) != EOF && s < buf + sizeof buf - 1 ){
                if( c == '\n' && s > buf && s[-1] == '\n' ){
                        ungetc(c, stdin);
                        break;
                }
                *s++ = c;
        }
        *s = '\0';
        printf("string entered: %s", buf);
        return 0;
}

to read multiple lines of string from stdin.从标准输入读取多行字符串。 How can I keep reading until a line only containing EOL?我如何才能继续阅读直到仅包含 EOL 的行?

Keep track of when reading the beginning of the line.跟踪读取行首的时间。 If a '\n' is read at the beginning, stop如果在开头读取了'\n' ,则停止

getchar() approach: getchar()方法:

bool beginning = true;
int ch;
while ((ch = getchar()) != EOF) {
  if (beginning) {
    if (ch == '\n') break;
  }
  // Do what ever you want with `ch` 
  beginning = ch == '\n';  
}

fgets() approach - needs more code to handle lines longer than N fgets()方法 - 需要更多代码来处理比 N 更长的行

#define N 1024
char buf[N+1];
while (fgets(buf, sizeof buf, stdin) && buf[0] != '\n') {
  ; // Do something with buf
}

If you need to read one character at a time then you can with either getchar or fgetc depending upon whether or not you're reading from stdin or some other stream.如果您需要一次读取一个字符,则可以使用getcharfgetc ,具体取决于您是从标准输入还是其他stdin读取。

But you said you were reading strings, so I'm assuming fgets is more appropriate.但是您说您正在阅读字符串,所以我假设fgets更合适。

There are primarily two considerations:主要有两个考虑:

  1. maximum line length最大线长
  2. whether or not to handle Windows versus non-Windows line endings是否处理 Windows 与非 Windows 行尾

Even if you are a beginner--and I won't go into #2 here--you should know you can defend against it.即使你是初学者——我不会把 go 放到这里的#2——你应该知道你可以防御它。 I will at least say that if you compile on one platform and read from stdin from a redirected file from another platform, then you might have to write a defense.我至少会说,如果您在一个平台上编译并从另一个平台的重定向文件中读取标准输入,那么您可能必须编写防御。

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main (int argc, char *argv[]) {
    char buf[32];  // relatively small buf makes testing easier
    int lineContinuation = 0;
    // If no characters are read, then fgets returns NULL.
    while (fgets(buf, sizeof(buf), stdin) != NULL) {
       int l = strlen(buf); // No newline in buf if line len + newline exceeds sizeof(buf)
       if (buf[l-1] == '\n') {
          if (l == 1 && !lineContinuation) {
             break; // errno should indicate no error.
          }
          printf("send line ending (len=%d) to the parser\n", l);
          lineContinuation = 0;
       } else {
          lineContinuation = 1;
          printf("send line part (len=%d) to the parser\n", l);
       }
    }
    printf("check errno (%d) if you must handle unexpected end of input use cases\n", errno);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM