Im new to C. I have a problem in understanding a piece of code. What I don't understand are two things. The second argument of fgets is the maximum length of bytes can be stored in the buffer. Why if I type more letters in the terminal and hit enter still the string is printed back in full. I am assuming that if the length of the string inserted in the console is larger than the buffer will overflow and the printf will work because it stops on the termination of the string, but then what it is the point of setting a max limit as second argument to fgets?
#define buff_size 4
//3.71
void good_echo(){
char buf[buff_size];
while(1) {
char* p = fgets(buf, 8, stdin);
if(p == NULL) {
break;
}
printf("%s", p);
}
return;
}
CodePudding user response:
fgets will stop when it reads the enter key OR when the buffer is full.
If you say the buffer is 8 characters long, and you type abcdef<enter>
it will put in the buffer a
, b
, c
, d
, e
, f
, \n
and \0
(8 characters).
If you say the buffer is 8 characters long, and you type abcdefgh<enter>
, it will put in the buffer a
, b
, c
, d
, e
, f
, g
and \0
(8 characters). There is still h<enter>
left over, which will be read the next time you call fgets
(or gets
or getchar
or scanf
etc)
CodePudding user response:
The reason because you're still getting back what you write is that stdin
is buffered, that means when you read less characters than you actually wrote, considering you're in a while
loop and fgets
doesn't give any error(so you don't break in the if
statement) you do once more the fgets
and get the remaining chars.
CodePudding user response:
Why if I type more letters in the stdin still the string is printed back. I am assuming that if the length of the string inserted in the console is larger than the buffer will overflow and the printf will work because it stops on the termination of the string,
You get the full input echoed back by the program because the fgets()
and printf()
calls are inside a loop. Each fgets()
call will read and store as many characters as will fit in the buffer, up to and including a newline if one is in fact encountered before the available buffer space is exhausted. If there is more data than will fit in the buffer -- because you typed more characters than can fit at once, or because you typed ahead multiple lines at hyperspeed -- then whatever is not read by fgets()
remains in the stream, waiting to be read via some future call to an I/O function.
In your program, the printf()
echoes back the characters that were read and stored, and control then loops back to fgets()
. If there are more characters available to read, then it will read them, up to, again, the buffer capacity or a newline, whichever comes first. In this way, one long line may be consumed from the standard input and echoed to the standard output over multiple iterations of the loop.
but then what it is the point of setting a max limit as second argument to fgets?
It does exactly what it is advertized to do. On any call, fgets()
will write up to that many bytes into the provided buffer.
CodePudding user response:
I believe the confusion is related to the behavior of the terminal rather than the behavior of the program. When you type a single character into the terminal, it is displayed on the screen by the terminal driver. That behavior has nothing to do with your program. Eventually, the fgets
function will read some data from stdin, but that may happen many seconds or minutes (or hours, if you go on a long lunch) after you initially typed the key. Generally, the terminal driver will hold on to the data until you hit 'enter' (or 'return'), at which point a line of text will be sent to the program. It might be easier to see if you actually write some data and see what your program is doing. eg:
$ cat a.c
#include <signal.h>
#include <stdio.h>
#define buff_size 4
void
good_echo(void)
{
char buf[buff_size];
char *p;
while( (p = fgets(buf, sizeof buf, stdin)) != NULL ){
printf("good_echo read: %s\n", p);
}
}
int
main(int argc, char **argv)
{
good_echo();
return 0;
}
$ gcc a.c
$ ./a.out
this is some text that is typed
good_echo read: thi
good_echo read: s i
good_echo read: s s
good_echo read: ome
good_echo read: te
good_echo read: xt
good_echo read: tha
good_echo read: t i
good_echo read: s t
good_echo read: ype
good_echo read: d
In the above, you can see that each call to fgets
only consumes 3 bytes.