You really should use getline
for this. You could use scanf
with something like:
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
int rv;
FILE *fp = stdin;
char *line = NULL;
while( (rv = fscanf(fp, "%m[^\n]", &line)) != EOF ){
if( rv == 0 ){
line = "";
}
puts(line);
fgetc(fp); /* Consume newline */
if( rv ){
free(line);
}
}
return 0;
}
But, don't. getline
is more widely available than %m
, and easier to understand. The %m
specifier is a non-standard extension that allocates space for the data, and the caller is responsible for freeing that data. getline
is a posix extension that does exactly what you're trying to do (allocates space for a buffer to read a full line of text.)
Also, note that the conversion specifier is just [
, not s, and the format string should not have the trailing s
.
To use getline
, you can do:
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
FILE *fp = stdin;
char *line = NULL;
size_t cap = 0;
while( getline(&line, &cap, fp) != -1 ){
fputs(line, stdout);
}
free(line);
return 0;
}
Note that when using getline
, the newline stays in the buffer, while the scanf
method does not add that character. Another advantage of getline
is that you only need to free the buffer once, and it will minimize the allocations.