While doing filing im stuck here.The condition of the while loop is not working.The compiler says cannot convert int to FILE*.
while(pFile!=EOF);
Should i typecase the pFile to int?I tried that but it did not worked.Thanks in advance.
The complete code is:
int main()
{
char ch;
char name[20];
FILE *pFile;
int score;
pFile=fopen("database.txt","r");
if(pFile!=NULL)
{
while(pFile!=EOF);
{
fscanf(pFile,"%c",ch);
}
}
else
printf("Cant open the file.......");
fclose(pFile);
return 0;
}
First, you do not want to use while (!feof(pFile)) -- ever! Doing so will almost inevitably lead to an error where the last data you read from the file appears to be read twice. It's possible to make it work correctly, but only by adding another check in the middle of the loop to exit when EOF is reached -- in which case, the loop condition itself will never be used (i.e., the other check is the one that will actually do the job of exiting the loop).
What you normally do want to do is check for EOF as you read the data. Different functions indicate EOF in different ways. fgets signals failure (including EOF) by returning NULL. Most others (getc, fgetc, etc.) do return EOF, so you typically end up with something like this:
int ch; // Note, this should be int, NOT char
while (EOF != (ch=getc(pFile)))
process(ch);
or:
char buffer[MAX_LINE_SIZE];
while (fgets(buffer, sizeof(buffer), pFile))
process(buffer);
With scanf, checking for success is a little more complex -- it returns the number of successful conversions, so you want to make sure that matches what you expected. For example:
while (1 == fscanf(fPfile, "%d", &input_number))
process(input_number);
In this case I've used 1 because I specified 1 conversion in the format string. It's also possible, however, for conversion to fail for reasons other than EOF, so if this failes, you'll frequently want to check feof(pFile). If it returns false, do something like reading the remainder of the line, showing it to the user in a warning message, and then continuing to read the rest of the file.
It depends what pFile and EOF are defined as, but I will asssume that pFile is a *FILE, and EOF is from stdio.h. Then I guess you should do something like:
#include <stdlib.h>
#include <stdio.h>
#define FILENAME "file.txt"
int main(void) {
FILE *pFile;
int ch;
pFile = fopen(FILENAME,"r");
if (pFile) {
while ((ch = getc(pFile)) != EOF) {
printf("Read one character: %c\n", ch);
}
close(pFile);
return EXIT_SUCCESS;
} else {
printf("Unable to open file: '%s'\n", FILENAME);
return EXIT_FAILURE;
}
}
which yields
$ echo "abc" > file.txt
$ /tmp/fileread
Read one character: a
Read one character: b
Read one character: c
Read one character:
# last character being a linefeed
Assuming pFile is your file handle, this doesn't change as you read from the file. EOF is returned by e.g. fgetc(). See e.g. http://www.drpaulcarter.com/cs/common-c-errors.php#4.2 for common ways to solve this.
here is correct way:
c = getc(pFile);
while (c != EOF) {
/* Echo the file to stdout */
putchar(c);
c = getc(pFile);
}
if (feof(pFile))
puts("End of file was reached.");
else if (ferror(pFile))
puts("There was an error reading from the stream.");
else
/*NOTREACHED*/
puts("getc() failed in a non-conforming way.");
fclose(pFile);
pFile is a pointer to a file. EOF is usually defined as -1, a signed integer.
What you should do is fopen, make sure pFile != NULL, then call some function on the file handle until that function returns EOF. A pointer will (or rather, should) never be EOF. But a function acting on that pointer may return EOF.
I'm guessing you want to keep looping while you haven't hit end-of-file. In that case, you are looking for this:
while (!feof(pFile))
{
...
}
That said, this is still not quite correct. feof will only return true once it tries to read beyond the end of the file. This means feof can return false and yet there is no more data to read. You should really try your operation and only check for end of file if it fails:
char buffer[SIZE];
while (fgets(buffer, sizeof(buffer), pFile))
{
...
}
if (!feof(pFile))
{
// fgets failed for some reason *other* then end-of-file
}
Related
I am trying to write user input to a txt file using a while loop.
But for some reason that I don't know, the while loop doesn't stop by clicking 'enter'.
when I click 'enter', I see "while loop executed" so I know the while loop iterated again even though I wanted to stop the while loop.
How to do it in a right way?
P.S: I use Microsoft Visual Studio recommended by my professor.
#include <stdio.h>
#include <string.h>
void main()
{
//writing to file
char write[100];
char fileName[100];
printf("give a name for file: ");
gets_s(fileName,99);
strcat(fileName,".txt");
FILE* pF = fopen(fileName, "w");
printf("what needs to be written?\n: ");
while(gets_s(write,99) != NULL)
{
printf("whileloop executed\n");
fprintf(pF,"%s\n", write);
}
fclose(pF);
}
Per Microsoft's gets_s() documentation, gets_s() returns NULL on end-of-file and error conditions:
Return Value
Returns buffer if successful. A NULL pointer indicates an error or
end-of-file condition. Use ferror or feof to determine which one
has occurred.
Hitting the enter key does not close the input stream and cause an end-of-file condition. It just places a zero-length line terminated with a newline in the input stream.
To do that on Windows from a terminal, one usually has to enter the CTRL-Z key combination.
You need to do some handling there as gets_s() will return and empty string when enter is hit. You can write an extra function to handle that:
size_t my_gets(char *buf,size_t len)
{
size_t ret=0;
if(gets_s(buf,len))
ret = strlen(buf);
return ret;
}
Then change your loop to:
while(my_gets(write,99))
{
...
P.S.- You should avoid calling variables with the same name of system functions (i.e. write).
I am trying to write a simple C program that loads a text-file, prints the first line to screen, waits for the user to press enter and then prints the next line, and so on.
As only argument it accepts a text-file that is loaded as a stream "database". I use the getline()-function for this, according to this example. It compiles fine, successfully loads the text-file, but the program never enters the while-loop and then exits.
#include <stdio.h>
#include <stdlib.h>
FILE *database = NULL; // input file
int main(int argc, char *argv[])
{
/* assuming the user obeyed syntax and gave input-file as first argument*/
char *input = argv[1];
/* Initializing input/database file */
database = fopen(input, "r");
if(database == NULL)
{
fprintf(stderr, "Something went wrong with reading the database/input file. Does it exist?\n");
exit(EXIT_FAILURE);
}
printf("INFO: database file %s loaded.\n", input);
/* Crucial part printing line after line */
char *line = NULL;
size_t len = 0;
ssize_t read;
while((read = getline(&line, &len, database)) != -1)
{
printf("INFO: Retrieved line of length %zu :\n", read);
printf("%s \n", line);
char confirm; // wait for user keystroke to proceed
scanf("%c", &confirm);
// no need to do anything with "confirm"
}
/* tidy up */
free(line);
fclose(database);
exit(EXIT_SUCCESS);
}
I tried it with fgets() -- I can also post that code --, but same thing there: it never enters the while-loop.
It might be something very obvious; I am new to programming.
I use the gcc-compiler on Kali Linux.
Change your scanf with fgetline using stdin as your file parameter.
You should step through this in a debugger, to make sure your claim that it never enters the while loop is correct.
If it truly never enters the while loop, it is necessarily because getline() has returned -1. Either the file is truly empty, or you have an error reading the file.
man getline says:
On success, getline() and getdelim() return the number of
characters
read, including the delimiter character, but not including the termi‐
nating null byte ('\0'). This value can be used to handle embedded
null bytes in the line read.
Both functions return -1 on failure to read a line (including end-of-
file condition). In the event of an error, errno is set to indicate
the cause.
Therefore, you should enhance your code to check for stream errors and deal with errno -- you should do this even when your code works, because EOF is not the only reason for the function
to return -1.
int len = getline(&line, &len, database);
if(len == -1 && ferror(database)) {
perror("Error reading database");
}
You can write more detailed code to deal with errno in more explicit ways.
Unfortunately handling this thoroughly can make your code a bit more verbose -- welcome to C!
I'm testing out the basic functions to operate files with.
I try to first open/close a file to create it, and then open/close it again to append to it. Lastly, I print out what is in the file.
My code currently looks like the following:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE * file;
char mark;
/* WRITING: */
file= fopen("goodbye.c","w");
if(!file)
{ printf("Couldn't open file.\n");
exit(EXIT_FAILURE); }
printf("Enter data to write to .c file:");
while((mark= getchar())!=EOF)
{
putc(mark,file);
}
fclose(file);
/* APPENDING: */
file= fopen("goodbye.c","a");
if(!file)
{ printf("Couldn't open file.\n");
exit(EXIT_FAILURE); }
char add;
scanf("%c",add);
putc(add,file);
fclose(file);
/* READING: */
file= fopen("goodbye.c","r");
if(!file)
{ printf("Couldn't open file.\n");
exit(EXIT_FAILURE); }
while((mark= getc(file))!= EOF)
{
printf("%c",mark);
}
fclose(file);
}
With this, I'm not able to append to the file. When using getchar(), I type ctrl+d once finished writing in the first place. After this it goes on to printing out what I just wrote, not giving me the chance to append to the file. Does ctrl+d somehow interrupt with scanf?
And how to get the result that I was looking for?
Your code only allows you to append a single character to the file, which is a little stingy. It can also (at least in theory) lead to problems on some systems if the last line of the text file does not end with a newline, which it won't if you add something other than a newline. Maybe you need a loop to read multiple characters?
Also, since you don't stop the initial input until EOF, you need to clear the 'error' on stdin with clearerr(stdin) to allow further input to occur. This works correctly on Mac OS X 10.10.1 Yosemite; it should work the same on other Unix systems. I can't answer confidently for Windows-based code unless it is using something like Cygwin to simulate Unix, but I expect it would work in much the same way there, too, even with MSVC.
Incidentally, my compiler complains about a missing & in the call to scanf() at:
char add;
scanf("%c",add);
If your compiler doesn't complain, either turn up the warning level or get a better compiler.
This code works as I'd expect:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *file;
char mark;
/* WRITING: */
file = fopen("goodbye.c", "w");
if (!file)
{
printf("Couldn't open file.\n");
exit(EXIT_FAILURE);
}
printf("Enter data to write to .c file:");
while ((mark = getchar()) != EOF)
{
putc(mark, file);
}
fclose(file);
printf("EOF 1\n");
/* APPENDING: */
file = fopen("goodbye.c", "a");
if (!file)
{
printf("Couldn't open file.\n");
exit(EXIT_FAILURE);
}
clearerr(stdin);
char add;
while (scanf("%c", &add) == 1)
putc(add, file);
fclose(file);
printf("EOF 2\n");
/* READING: */
file = fopen("goodbye.c", "r");
if (!file)
{
printf("Couldn't open file.\n");
exit(EXIT_FAILURE);
}
while ((mark = getc(file)) != EOF)
{
printf("%c", mark);
}
fclose(file);
return 0;
}
The only substantive changes are adding a loop around the scanf() — though frankly it would be better to use getchar() again, like in the first input loop — fixing the call to scanf(), adding the two printf() statements that report when EOF is detected, and including clearerr(stdin); to allow input to continue.
Sample output
Code without clearerr(stdin):
Enter data to write to .c file:Happiness is a bug-free program.
Happiness is seldom attained.
EOF 1
EOF 2
Happiness is a bug-free program.
Happiness is seldom attained.
Code with clearerr(stdin):
Enter data to write to .c file:Happiness is a bug-free program.
Happiness is seldom attained.
EOF 1
But it helps when you add the clearerr(stdin) to this one.
EOF 2
Happiness is a bug-free program.
Happiness is seldom attained.
But it helps when you add the clearerr(stdin) to this one.
Does feof() checks for eof for the current position of filepointer or checks for the position next to current filepointer?
Thanks for your help !
Every FILE stream has an internal flag that indicates whether the caller has tried to read past the end of the file already. feof returns that flag. The flag does not indicate whether the current file position is as the end of the file, only whether a previous read has tried to read past the end of the file.
As an example, let's walk through what happens, when reading through a file containing two bytes.
f = fopen(filename, "r"); // file is opened
assert(!feof(f)); // eof flag is not set
c1 = getc(f); // read first byte, one byte remaining
assert(!feof(f)); // eof flag is not set
c2 = getc(f); // read second byte, no bytes remaining
assert(!feof(f)); // eof flag is not set
c3 = getc(f); // try to read past end of the file
assert(feof(f)); // now, eof flag is set
This is why the following is the wrong way to use eof when reading through a file:
f = fopen(filename, "r");
while (!feof(f)) {
c = getc(f);
putchar(c);
}
Because of the way feof works, the end-of-file flag is only set once getc
tries to read past the end of the file. getc will then return EOF, which is
not a character, and the loop construction causes putchar to try to write it
out, resulting in an error or garbage output.
Every C standard library input method returns an indication of success or
failure: getc returns the special value EOF if it tried to read past the
end of the file, or if there was an error while reading. The special value is
the same for end-of-file and error, and this is where the proper way to use
feof comes in: you can use it to distinguish between end-of-file and error
situations.
f = fopen(filename, "r");
c = getc(f);
if (c == EOF) {
if (feof(f))
printf("it was end-of-file\n");
else
printf("it was error\n");
}
There is another internal flag for FILE objects for error situations:
ferror. It is often clearer to test for errors instead of "not end of file".
An idiomatic way to read through a file in C is like this:
f = fopen(filename, "r");
while ((c = getc(f)) != EOF) {
putchar(c);
}
if (ferror(f)) {
perror(filename):
exit(EXIT_FAILURE);
}
fclose(f);
(Some error checking has been elided from examples here, for brevity.)
The feof function is fairly rarely useful.
You can get a better understanding of how feof works, by knowing how it's implemented. Here is a simplified version of how the 7th Edition Unix stdio library implements feof. Modern libraries are very similar, adding code offering thread-safety, increased efficiency, and a cleaner implementation.
extern struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
char _flag;
char _file;
} _iob[_NFILE];
#define _IOEOF 020
#define feof(p) (((p)->_flag&_IOEOF)!=0)
#define getc(p) (--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p))
int
_filbuf(FILE *iop)
{
iop->_ptr = iop->_base;
iop->_cnt = read(fileno(iop), iop->_ptr, BUFSIZ);
if (iop->_cnt == 0) {
iop->_flag |= _IOEOF;
return(EOF);
}
return(*iop->_ptr++ & 0377);
}
The stdio library maintains with each file a structure containing an internal buffer pointed by _base. The current character in the buffer is pointed by _ptr and the number of characters available is contained in _cnt. The getc macro, which is the base for a lot of higher-level functionality, like scanf, tries to return a character from the buffer. If the buffer is empty, it will call _filbuf to fill it. _filbuf in turn will call read. If read returns 0, which means that no more data is available, _filbuf will set the _IOEOF flag, which feof checks each time you call it to return true.
As you can understand from the above, feof will return true the first time you try to read a character past the end of the file (or a library function tries in your behalf). This has subtle implications on the behavior of various functions. Consider a file containing a single character: the digit 1. After you read that character with getc, feof will return false, because the _IOEOF flag is unset; nobody has yet tried to read past the end of the file. Calling getc again will result in a call to read, the setting of the _IOEOF flag, and this will cause feof to return true. However, after reading the number from the same file using fscanf("%d", &n), feof will immediately return true, because fscanf will have tried to read additional digits of the integer.
I don't know exactly why a file pointer reads an extra line from a file, specifically the last line, here is the code:
FILE *fp ;
fp = fopen ("mac_ip.txt", "r") ;
int mac;
char *ip = (char *) malloc(15);
while(!feof(fp)){
fscanf(fp,"%i",&mac);
fscanf(fp,"%s",ip);
printf("MAC: %i\n",mac);
printf("IP: %s\n",ip);
}
and the file has exactly 20 lines, but the line 20, is printed twice.
Which is the error?
Thanks in advance.
Because after reading the last two values, you still haven't hit EOF. So the loop goes on. In the next pass of the loop, fscanf actually does not read the last line for the second time like it appears, the fscanfs fail, but the printfs print out the values from the previous pass of the loop.
feof does not "know" it's at the end of file until you try to read some more. Since fscanf tells you how many items it got, you can use this simple trick:
for(;;){
if (fscanf(fp,"%i%s", &mac, ip) != 2) break;
printf("MAC: %i\n",mac);
printf("IP: %s\n",ip);
}
After you have done the two reads on the twentieth line, you have got to the end of the file but the system doesn't know this. feof will only trigger when you try to get past the end of the file, not when you are exactly on it ...
Also, you may have a line-end (CR or CR-LF) on the 20th line which it will only get past with another attempted read.
The solution is to read the line in one go (there is a specific C command for this) and then parse that to get your data. If the whole-line read fails, then you've got to the end.
Your code resembles to the following example
#include <stdio.h>
int main(void)
{
char buffer[256];
FILE * myfile;
myfile = fopen("some.txt","r");
while (!feof(myfile))
{
fgets(buffer,256,myfile);
printf("%s",buffer);
}
fclose(myfile);
return 0;
}
from
http://www.friedspace.com/feof.html
You better test for fscanf return value before printing result. I bet that in the last iteration of your loop, fscanf calls fail and you print the last returned results.
FILE *fp ;
int mac;
char ip[15];
fp = fopen ("mac_ip.txt", "r") ;
if (!fp) return;
while(1){
if (fscanf(fp,"%i",&mac) < 1) break;
if (fscanf(fp,"%s",ip) < 1) break;
printf("MAC: %i\n",mac);
printf("IP: %s\n",ip);
}
fclose (fp);
fscanf() returns the number of assignments it mad (or -1 on eof). By using the return value, you don't need the eof() function. BTW I don't think you can read a MAC address into an int. Maybe you need to read that into a string, too ?
Explanation: feof() does not do what the OP expects. feof() should only be inspected after one of the file operations failed. In most cases you don't need feof().