简体   繁体   中英

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

I am a novice in C programming. Suppose I want to read multiple lines of string from stdin. How can I keep reading until a line only containing 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. 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 . The only use cases where scanf actually makes sense are in problems for which C is the wrong language. Time spent learning the foibles of scanf is not well spent, and it doesn't really teach you much about 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?

Keep track of when reading the beginning of the line. If a '\n' is read at the beginning, stop

getchar() approach:

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

#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.

But you said you were reading strings, so I'm assuming fgets is more appropriate.

There are primarily two considerations:

  1. maximum line length
  2. whether or not to handle Windows versus non-Windows line endings

Even if you are a beginner--and I won't go into #2 here--you should know you can defend against it. 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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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