How am I supposed to read long input using fgets()
, I don't quite get it.
I wrote this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char buffer[10];
char *input;
while (fgets(buffer,10,stdin)){
input = malloc(strlen(buffer)*sizeof(char));
strcpy(input,buffer);
}
printf("%s [%d]",input, (int)strlen(input));
free(input);
return 0;
}
For this problem, there is a format specifier %s by which we can read a string of unknown length and we don't need looping to read and print the string in the code. It results in less time taken for compiling the code by the compiler.
You should use "%5s" to ensure no buffer overflow.
The fgets() function stores the result in string and adds a null character (\0) to the end of the string. The string includes the new-line character, if read.
The C library function char *fgets(char *str, int n, FILE *stream) reads a line from the specified stream and stores it into the string pointed to by str. It stops when either (n-1) characters are read, the newline character is read, or the end-of-file is reached, whichever comes first.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char buffer[10];
char *input = 0;
size_t cur_len = 0;
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
size_t buf_len = strlen(buffer);
char *extra = realloc(input, buf_len + cur_len + 1);
if (extra == 0)
break;
input = extra;
strcpy(input + cur_len, buffer);
cur_len += buf_len;
}
printf("%s [%d]", input, (int)strlen(input));
free(input);
return 0;
}
This is about the minimal set of changes that will give you the complete line of input. This grows the space by up to 9 bytes at a time; that isn't the best way to do it, but there's extra bookkeeping involved doing it the better ways (doubling the space allocated, and keeping a record of how much is allocated vs how much is in use). Note that cur_len
record the length of the string in the space pointed to by input
excluding the terminal null. Also note that the use of extra
avoids a memory leak on failure to allocate.
The strcpy()
operation could be legitimately replaced by memmove(input + cur_len, buffer, buf_len + 1)
(and in this context, you could use memcpy()
instead of memmove()
, but it doesn't always work while memmove()
does always work, so it is more reliable to use memmove()
).
With length-doubling — the cur_max
variable records how much space is allocated, and cur_len
records how much space is in use.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char buffer[10];
char *input = 0;
size_t cur_len = 0;
size_t cur_max = 0;
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
size_t buf_len = strlen(buffer);
if (cur_len + buf_len + 1 > cur_max)
{
size_t new_len = cur_max * 2 + 1;
if (buf_len + 1 > new_len)
new_len = buf_len + 1;
char *extra = realloc(input, new_len);
if (extra == 0)
break;
input = extra;
cur_max = new_len;
}
strcpy(input + cur_len, buffer);
cur_len += buf_len;
}
printf("%s [%d]", input, (int)strlen(input));
free(input);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With