I have a question about the fgets()
char *fgets(char *str, int strsize, FILE *stream);
fgets()' document says:
On success, the function returns the same str parameter. If the End-of-File is encountered and no characters have been read, the contents of str remain unchanged and a null pointer is returned.
If an error occurs, a null pointer is returned.
How do you differentiate between above two situations - fgets reaching EOF(END OF FILE) & error whilst reading file?
Also, when an error occurs whilst fgets reads file, does fgets keep track of whatever has been read up to that point in the str?
How do you check if fgets immediately reaches EOF?
Referring your 1st question:
How do you differentiate between above two situations - fgets reaching EOF(END OF FILE) & error whilst reading file?
If fgets() returned NULL, call ferror() for the file pointer which just before had been used with the fgets() call, which returned NULL. If ferror() returns a non zero value, then fgets() failed, else it had reached the end-of-the file.
Example:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define LINE_LEN_MAX (42)
int main(int argc, char ** argv)
{
if (1 >= argc)
{
errno = EINVAL;
perror("main() failed");
exit(EXIT_FAILURE);
}
{
FILE * fp = fopen(argv[1], "r");
if (NULL == fp)
{
perror("fopen() failed");
exit(EXIT_FAILURE);
}
for (char line[LINE_LEN_MAX];
NULL != fgets(line, LINE_LEN_MAX, fp);)
{
printf("%s", line);
}
if (0 != ferror(fp))
{
perror("fgets() failed");
exit(EXIT_FAILURE);
}
fclose(fp);
}
return EXIT_SUCCESS;
}
The other to question can be answered straight forward from the docs:
Question 3:
How do you check if fgets immediately reaches EOF?
Answer:
If end-of-file is encountered and no characters have been read into the array, the contents of the array remain unchanged and a null pointer is returned.
Question 2:
when an error occurs whilst fgets reads file, does fgets keep track of whatever has been read up to that point in the str?
Answer:
If a read error occurs during the operation, the array contents are indeterminate and a null pointer is returned.
Related
I am trying to get a sample (shell script) program on how to write to a file:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv){
char buff[1024];
size_t len, idx;
ssize_t wcnt;
for (;;){
if (fgets(buff,sizeof(buff),stdin) == NULL)
return 0;
idx = 0;
len = strlen(buff);
do {
wcnt = write(1,buff + idx, len - idx);
if (wcnt == -1){ /* error */
perror("write");
return 1;
}
idx += wcnt;
} while (idx < len);
}
}
So my problem is this: Let's say I want to write a file of 20000 bytes so every time I can only write (at most) 1024 (buffer size).
Let's say that in my first attempt everything is going perfect and fgets() reads 1024 bytes and in my first do while I write 1024 bytes.
Then, since we wrote "len" bytes we exit the do-while loop.
So now what?? The buffer is full from our previous reading. It seems to me that for some reason it is implied that fgets() will now continue reading from the point it reached in in-file the last time. (buf[1024] here).
How come, fgets() knows where it stopped reading in the in-file?
I checked the man page :
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored in the buffer. A terminating null byte (aq\0aq) is stored after the last character in the buffer.
fgets() return s on success, and NULL on error or when the end of file occurs while no characters have been read.*
So from that, I get that it returns a pointer to the first element of buf, which is always buf[0],
that's why I am confused.
When using aFILE stream, it contains information about the position in the file (among other things). fgets and other functions like freador fwrite merely utilize this information and updates it when an operation is performed.
So, whenever fgets reads from the stream, the stream will be updated to maintain the position, so that the next operation starts off where the previous ended.
I want to have a c program read a text file line by line then print out those lines to the terminal.
My code
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* line;
FILE *ifp;
ifp = fopen("BBE.txt", "r");
if (ifp == NULL)
{
printf("Error opening file!\n");
exit(1);
}
while (fscanf(ifp, "%s", line) == 1)
{
printf("%s\n", line);
}
fclose(ifp);
return 0;
}
The program when i try to run it does not print out anything to the terminal. This tells me that the while loop is not working but i am not to sure as to why.
Your loop is not working, because fscanf does not return just 1 on success.
According to the man page of fscanf, the return value has the following meaning:
RETURN VALUE
On success, these functions return the number of input items
successfully matched and assigned; this can be fewer than provided for, or even zero, in the event of an early matching failure.
The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set to indicate the error.
Additionally as already stated in another answer: You write to memory that is NOT YOUR memory:
char* line;
is just a the declaration of a pointer to a char. What you need is a contiguous array of char to write to.
You either can allocate this on the stack by declaring it:
char line[1000]; // Allocate a char array of the size of 1000.
or on the heap;
char* line = malloc(1000*sizeof(char)); // Allocate 1000 chars on the heap
here you have to free the memory afterwards
free(line);
You used *line without initialising it -> undefined behavior.
To fix that, you can use a char array instead:
char line[1000] = "";
what is the correct way to read a text file until EOF using fgets in C? Now I have this (simplified):
char line[100 + 1];
while (fgets(line, sizeof(line), tsin) != NULL) { // tsin is FILE* input
... //doing stuff with line
}
Specifically I'm wondering if there should be something else as the while-condition? Does the parsing from the text-file to "line" have to be carried out in the while-condition?
According to the reference
On success, the function returns str.
If the end-of-file is encountered while attempting to read a character, the eof indicator is
set (feof). If this happens before any characters could be read, the
pointer returned is a null pointer (and the contents of str remain
unchanged). If a read error occurs, the error indicator (ferror) is
set and a null pointer is also returned (but the contents pointed by
str may have changed).
So checking the returned value whether it is NULL is enough. Also the parsing goes into the while-body.
What you have done is 100% OK, but you can also simply rely on the return of fgets as the test itself, e.g.
char line[100 + 1] = ""; /* initialize all to 0 ('\0') */
while (fgets(line, sizeof(line), tsin)) { /* tsin is FILE* input */
/* ... doing stuff with line */
}
Why? fgets will return a pointer to line on success, or NULL on failure (for whatever reason). A valid pointer will test true and, of course, NULL will test false.
(note: you must insure that line is a character array declared in scope to use sizeof line as the length. If line is simply a pointer to an array, then you are only reading sizeof (char *) characters)
i had the same problem and i solved it in this way
while (fgets(line, sizeof(line), tsin) != 0) { //get an int value
... //doing stuff with line
}
I've tried to read whole file with fgets, and when I use it in while loop, it never ends.
When I use fscanf everything works fine.
while((fscanf(f,"%s",ime)) != EOF)
{
fputs(ime,p);
fputc('\n',p);
}
But this doesn't work, how to fix it? I get infinite loop
while((fgets(ime,100,f)) != EOF)
{
fputs(ime,p);
fputc('\n',p);
}
What should I put instead != EOF so loop ends when it is end of text in file?
Is it really this hard to read the documentation?
char *fgets(char *str, int n, FILE *stream)
On success, the function returns the same str parameter. If the End-of-File is encountered and no characters have been read, the contents of str remain unchanged and a null pointer is returned.
If an error occurs, a null pointer is returned.
while((fgets(ime,100,f)) != NULL)
Change to
while((fgets(ime,100,f)) != NULL)
According to man page
char *fgets(char *s, int size, FILE *stream);
fgets() return s on success, and NULL on error or when end
of file occurs while no characters have been read.
I have just recently started working with I/O in C. Here is my question - I have a file, from which I read my input. Then I use fgets() to get strings in a buffer which I utilise in some way. Now, what happens if the input is too short for the buffer i.e. if the first read by fgets() reaches EOF. Should fgets() return NULL(as I have read in fgets() documentation)? It seems that it doesn't and I get my input properly. Besides even my feof(input) does not say that we have reached EOF. Here is my code snippet.
char buf[BUFSIZ];
FILE *input,
*output;
input = fopen(argv[--argc], "r");
output = fopen(argv[--argc], "w");
/**
* If either of the input or output were unable to be opened
* we exit
*/
if (input == NULL) {
fprintf(stdout, "Failed to open file - %s.\n", argv[argc + 1]);
exit(EXIT_FAILURE);
}
if (output == NULL) {
fprintf(stdout, "Failed to open file - %s.\n", argv[argc + 0]);
exit(EXIT_FAILURE);
}
if (fgets(buf, sizeof(buf), input) != NULL) {
....
}
/**
* After the fgets() condition exits it is because, either -
* 1) The EOF was reached.
* 2) There is a read error.
*/
if (feof(input)) {
fprintf(stdout, "Reached EOF.\n");
}
else if (ferror(input)) {
fprintf(stdout, "Error while reading the file.\n");
}
The documentation for fgets() does not say what you think it does:
From my manpage
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading
stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored
after the last character in the buffer.
And later
gets() and fgets() return s on success, and NULL on error or when end of file occurs while no characters have been read.
I don't read that as saying an EOF will be treated as an error condition and return NULL. Indeed it says a NULL would only occur where EOF occurs when no characters have been read.
The POSIX standard (which defers to the less accessible C standard) is here: http://pubs.opengroup.org/onlinepubs/009695399/functions/fgets.html and states:
Upon successful completion, fgets() shall return s. If the stream is at end-of-file, the end-of-file indicator for the stream shall be set and fgets() shall return a null pointer. If a read error occurs, the error indicator for the stream shall be set, fgets() shall return a null pointer, and shall set errno to indicate the error.
This clearly indicates it's only going to return a NULL if it's actually at EOF when called, i.e. if any bytes are read, it won't return NULL.