This is how I've done it but I'm not sure this is the preferred idiom:
FILE *fp = fopen(argv[0], "r");
// handle fopen() returning NULL
while (!feof(fp)) {
char buffer[80]; // statically allocated, may replace this later with some more sophisticated approach
int num_chars = 0;
for (int ch = fgetc(fp); ch != EOF && ch != '\n'; ch = fgetc()) {
buffer[num_chars++] = ch;
}
// null-terminate the string
buffer[num_chars] = '\0';
printf("%s\n", buffer);
}
Is this okay, any suggestions to improve this?
Unless you're hoping to get a ultra-high efficient way to set the number of characters read, use
fgets()
.Replacing your example with a similar but different simple
fgets()
, you "lose" thenum_chars
variable.If you need to remove the last '\n'
If the strings are really humongous (like 42 Mega bytes worth), you may be better off reading character by character and keeping count with
num_chars
than usingfgets
first andstrlen
later.You're risking buffer overflow if the user inputs 80 characters or more.
I'm with ThiefMaster: you should use
fgets()
, instead. Read the input into a buffer that's larger than any legitimate input and then check that the last character is a newline.If you need every char in order to inspect it or modify or whatever else then use fgets. For everything else, use fgets.
Note that fgets will read until a new line or EOF is reached (or the buffer is full of course). New line character "\n" is also appended to the string if read from the file. Null character is also appended.
fgets returns :
No linesize-limit und strictly C89 (your code is only C99) like:
If you are not going to use
fgets()
(perhaps because you want to remove the newline, or you want to deal with"\r"
,"\n"
or"\r\n"
line endings, or you want to know how many characters were read), you can use this as a skeleton function:It recognizes only newline as the end of line; it drops the newline. It does not overflow the buffer; it does not discard excess characters, so if called upon to read a very long line, it will read the line in chunks; it returns the number of characters read. If you need to distinguish between overflow and a line that happens to be the length of the buffer - 1, then you probably need to preserve the newline - with consequential changes in the code:
There are endless minor variants on this, such as discarding any excess characters if the line has to be truncated. If you want to handle DOS, (old) Mac or Unix line endings, then borrow a leaf out of the CSV code from "The Practice of Programming" by Kernighan & Pike (an excellent book) and use:
Then you can use that in place of the
c != '\n'
test:The other alternative way of dealing with the whole process is using
fread()
andfwrite()
:In context, you'd open the file and check it for validity, then call: