0

I've been trying to use scanf to get input from stdin but it truncates the string after seeing whitespace or after hitting return.

What I'm trying to get is a way to read keyboard input that stores in the buffer linebreaks as well as whitespace. And ending when ctrl-D is pressed.

Should I try using fgets? I figured that wouldn't be optimal either since fgets returns after reading in a \n

7
  • 1
    While readchar not equal to ctrl-d ... Commented Aug 31, 2013 at 18:27
  • If the input is from a terminal you won't see the control-D (it is translated to EOF by the terminal driver, unless in raw mode) Commented Aug 31, 2013 at 18:30
  • 1
    Reading from user is normally line based anyway, so using fgets is fine that way, it'll give you a line at a time. Alternative would be to read a char at a time, with getchar or something. In either case, if you want to read arbitrarily long input, you'll need to read it in parts and do your own buffer handling. Commented Aug 31, 2013 at 18:31
  • Use fgets() in a loop, and you'll probably need to allocate memory to hold the growing string. Commented Aug 31, 2013 at 18:36
  • fgets() gets cumbersome if the input happens to be binary (contains NUL characters) or if the linewidth is larger than the buffersize (2nd argument) Commented Aug 31, 2013 at 18:45

4 Answers 4

1

There is no ready-made function to read everyting from stdin, but creating your own is fortunately easy. Untested code snippet, with some explanation in comments, which can read arbitrarily large amount of chars from stdin:

size_t size = 0; // how many chars have actually been read size_t reserved = 10; // how much space is allocated char *buf = malloc(reserved); int ch; if (buf == NULL) exit(1); // out of memory // read one char at a time from stdin, until EOF. // let stdio to handle input buffering while ( (ch = getchar()) != EOF) { buf[size] = (char)ch; ++size; // make buffer larger if needed, must have room for '\0' below! // size is always doubled, // so reallocation is going to happen limited number of times if (size == reserved) { reserved *= 2; buf = realloc(buf, reserved); if (buf == NULL) exit(1); // out of memory } } // add terminating NUL character to end the string, // maybe useless with binary data but won't hurt there either buf[size] = 0; // now buf contains size chars, everything from stdin until eof, // optionally shrink the allocation to contain just input and '\0' buf = realloc(buf, size+1); 
Sign up to request clarification or add additional context in comments.

Comments

1

scanf() splits the input at whitespace boundaries, so it's not suitable in your case. Indeed fgets() is the better choice. What you need to do is keep reading after fgets() returns; each call will read a line of input. You can keep reading until fgets() returns NULL, which means that nothing more can be read.

You can also use fgetc() instead if you prefer getting input character by character. It will return EOF when nothing more can be read.

Comments

0

If you want to read all input, regardless of whether it is whitespace or not, try fread.

Comments

0

Read like this

char ch,line[20]; int i=0; //define a counter //read a character assign it to ch, //check whether the character is End of file or not and //also check counter value to avoid overflow. while((ch=getchar())!=EOF && i < 19 ) { line[i]=ch; i++; } line[i]='\0'; 

2 Comments

This isn't safe as there's no buffer overflow guard. You could add && i < 19 to the condition.
@NikosC yes i agreed.Edited my answer.thanks for pointing this.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.