I have this function to read numbers from txt files that are structured like so:
1 2 5
2 1 9
3 5 8
The function reads the values correctly into my values, but I want to check if the line I have read is the last in the file.
My last if statement in the below function attempts to do this by seeing if fscanf produces NULL but it doesn't work, the function always returns NULL even if it's not the last line.
void process(int lineNum, char *fullName)
{
int ii, num1, num2, num3;
FILE* f;
f = fopen(fullName, "r");
if(f==NULL)
{
printf("Error: could not open %S", fullName);
}
else
{
for (ii=0 (ii = 0; ii < (lineNum-1); ii++)
{
/*move through lines without scanning*/
fscanf(f, "%d %d %d", &num1, &num2, &num3);
}
if (fscanf(f, "%*d %*d %*d\n")==NULL)
{
printf("No more lines");
}
fclose(f);
}
}
Check this below code.Using this code u can see whether you have reached the end of file or not.It is not suggested to use fscanf to read the end of file.
/* feof example: byte counter */
#include <stdio.h>
int main ()
{
FILE * pFile;
int n = 0;
pFile = fopen ("myfile.txt","r");
if (pFile==NULL) perror ("Error opening file");
else
{
while (fgetc(pFile) != EOF) {
++n;
}
if (feof(pFile)) {
puts ("End-of-File reached.");
printf ("Total number of bytes read: %d\n", n);
}
else puts ("End-of-File was not reached.");
fclose (pFile);
}
return 0;
}
You can use feof() to check if you are reading past the end of the file.
From man page of fscanf:
RETURN VALUE
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in the
event of an early matching failure.
You if the last line that you are trying to read is not in the expected format, fscanf may not read anything and return 0 which is same as NULL.
Related
#include <stdio.h>
main() {
int n;
FILE *file;
printf("We are here to create a file!\n");
file = fopen("demo.txt", "w+");
if (file != NULL)
printf("Succesfully opened!");
printf("Enter number\n");
while (scanf("%d", &n)) {
fprintf(file, "%d", n);
}
fclose(file);
}
why fscanf() is not working here? Here scanf is working properly but fscanf() is not responding or working here. Can anyone explain what the problem is?
Your code has some problems:
the prototype for main without arguments is int main(void)
you do not exit the program if the file cannot be opened. You will have undefined behavior if fopen returns NULL because you later pass this null pointer to fprintf.
the loop iterates until scanf() returns 0. You should instead iterate while scanf() returns 1. scanf() will return EOF if it fails at end of file, causing an infinite loop.
you should probably output a separator after the number in fprintf() otherwise all numbers are going to be clumped together forming a long sequence of digits.
main() should return 0 or an error status
Here is a corrected version:
#include <stdio.h>
int main(void) {
int n;
FILE *file;
printf("We are here to create a file\n");
file = fopen("demo.txt", "w");
if (file != NULL) {
printf("Successfully opened\n");
} else {
printf("Cannot open demo.txt\n");
return 1;
}
printf("Enter numbers\n");
while (scanf("%d", &n) == 1) {
fprintf(file, "%d\n", n);
}
fclose(file);
return 0;
}
Regarding your question: why can't I use fscanf() instead of scanf()?
you can use fscanf() as long as you give it a stream pointer opened for reading: if you write while (fscanf(stdin, "%d", &n) == 1) the program will behave the same way.
if you want fscanf() to read from file, you need to perform a file positioning command between read and write operations, such as rewind() of fseek(). Yet fscanf() will fail if there is no number to read at the current position in the file and since you open file with "w+" mode, fopen() will be truncated it.
You could cause an infinite loop by writing a number to the file, rewinding it to the beginning and re-reading the same number, etc.
Here is some code for illustration:
#include <stdio.h>
int main(void) {
int n;
FILE *file;
printf("We are here to create a file\n");
file = fopen("demo.txt", "w+");
if (file != NULL) {
printf("Successfully opened\n");
} else {
printf("Cannot open demo.txt\n");
return 1;
}
printf("Enter a number: ");
if (scanf("%d", &n) == 1) {
fprintf(file, "%d\n", n);
rewind(file);
while (fscanf(file, "%d", &n) == 1) {
printf("read %d from the file\n", n);
if (n == 0)
break;
rewind(file);
fprintf(file, "%d\n", n >> 1);
rewind(file);
}
}
fclose(file);
return 0;
}
Interaction:
We are here to create a file
Successfully opened
Enter a number: 10
read 10 from the file
read 5 from the file
read 2 from the file
read 1 from the file
read 0 from the file
This question already has an answer here:
how to identify a field separator from scanf?
(1 answer)
Closed 4 years ago.
For example, I am trying to get the total age from a text file separated by semicolons with the format of Name;Age;Favorite Number
Jack;12;3
Red;21;15
Blue;14;6
I have tried doing something like this.
File *fp;
fp = fopen(in_file,"r");
int sum = 0, age = 0, fav_number = 0;
while (fscanf(fp,"%c %f %f", name, age, fav_number) != EOF) {
fscanf(fp, "%c %f %f", name, age, fav_number);
sum += age;
}
But since it is not separated with space by with semicolon, it wouldn't work. I am not sure how to change it. Any clue on how to do it?
There are few issues with your code. Firstly its recommended to check the return value of fopen() for e.g this
fp = fopen(in_file,"r");
should be
fp = fopen(in_file,"r");
if(fp == NULL) {
/* error handling #TODO */
}
Secondly, the fscanf() arguments are not correct, surely compiler produces the warnings but seems you ignored them. This
while(fscanf(fp,"%c %f %f", &name, &age, &fav_number) != EOF) { /* read the name from file & store into name i.e it should be &name if name is char variable */
fscanf(fp,"%c %f %f", &name, &age, &fav_number);
sum += age;
}
lastly if you want to read the lines separated by semicolon then use %[^;] or use strtok(). Or it's better to read whole line first using fgets() and then use strtok(). To know how strtok() works read the manual page strtok.
There are many issues in your code:
File should be FILE
you should test the return value of fopen()
the format string for fscanf() is incorrect: %c reads just one character, %f requires a pointer to float and you instead provide an int value...
you should compare the return value of fscanf() to the number of expected conversions (3 in your code), not EOF which is only returned at end of file if no conversions were performed.
you call fscanf() twice.
Since you are not interested in the Name and Favorite colour fields, you can just ignore them:
#include <stdio.h>
int main() {
char in_file[] = "test.csv";
FILE *fp;
fp = fopen(in_file, "r");
if (fp != NULL) {
double sum = 0, age = 0;
while (fscanf(fp," %*[^;];%lf;%*lf", &age) == 1) {
sum += age;
}
fclose(fp);
printf("total of ages: %g\n", sum);
}
return 0;
}
Note however that it would be more reliable to read the input file one line at a time and parse it with sscanf():
#include <stdio.h>
int main() {
char buf[256];
char in_file[] = "test.csv";
double sum = 0, age = 0;
FILE *fp;
fp = fopen(in_file, "r");
if (fp == NULL) {
fprintf(stderr, "cannot open input file %s\n", in_file);
exit(1);
}
while (fgets(buf, sizeof buf, fp)) {
if (sscanf(buf,"%*[^;];%lf;%*lf", &age) == 1) {
sum += age;
} else {
fprintf(stderr, "invalid data: %s\n", buf);
fclose(fp);
exit(1);
}
}
fclose(fp);
printf("total of ages: %g\n", sum);
return 0;
}
#include <stdio.h>
int main() {
FILE *fp1, *fp2, *fp3;
int n, i, num, flag = 0;
/* open files to write even, odd seperately */
fp1 = fopen("data.txt", "r");
fp2 = fopen("even.txt", "w");
fp3 = fopen("odd.txt", "w");
fprintf(fp2, "Even Numbers:\n");
fprintf(fp3, "Odd Numbers:\n");
/* print even, odd and prime numbers in separate files */
while (!feof(fp1)) {
fscanf(fp1, "%d", &num);
if (num % 2 == 0) {
fprintf(fp2, "%d ", num);
} else {
if (num > 1) {
for (i = 2; i < num; i++) {
if (num % i == 0) {
flag = 1;
break;
}
}
}
fprintf(fp3, "%d ", num);
flag = 0;
}
}
fprintf(fp2, "\n");
fprintf(fp3, "\n");
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}
I want to use EOF instead of feof. I have tried !EOF = fp1 but it doesn't work and gives an error. I just want to replace feof with EOF. can anyone indicate what is the problem in my code?
fscanf returns EOF when the end-of-file is reached:
man fscanf
#include <stdio.h>
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
[...]
The scanf() function reads input from the standard input stream stdin, fscanf() reads input from the stream pointer stream, and
sscanf() reads its input from the character string pointed to by str.
[...]
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.
A solution would be to read save the return value of fscanf in a int
variable and check it agains 0 and EOF, like this:
If you want to keep using fscanf:
int ret;
while((ret = fscanf(fp1, "%d, &num)) != EOF)
{
if(ret == 0)
{
// fscanf failed to convert the input
// let it consume a charatcer and try again.
getc(fp1);
continue;
}
if(num % 2 == 0)
...
}
edit
Avoid using feof to control looping on a file like this while(!feof(fp), see Why is “while ( !feof (file) )” always wrong? for more
information about that.
edit 2
This was my original idea, but as Jonathan Leffler pointed out in the comments:
Jonathan Leffler wrote:
Your first solution demands a single number per line, which the code in the question does not
He's right, I didn't see that.
me from the past
One option would be to read the input line by line using fgets and then use
sscanf to parse the line:
char buffer[1024];
while(fgets(buffer, sizeof buffer, fp1))
{
if(sscanf(buffer, "%d", &num) != 1)
{
fprintf(stderr, "Could not read an integer, ignoring line\n");
continue;
}
if (num % 2 == 0)
...
}
Your condition for the while loop should be the fscanf() statement itself. EOF is always an integer. See the manual page for fscanf():
Return Value
The fscanf() function returns the number of fields that it successfully converted and assigned. The return value does not include fields that the fscanf() function read but did not assign.
The return value is EOF if an input failure occurs before any conversion, or the number of input items assigned if successful.
And, like everyone else I will refer you to Why is while ( !feof (file) ) always wrong?. This is essential reading on Stack Overflow for new C programmers.
#include <stdio.h>
int main(void) {
FILE *fp1, *fp2, *fp3;
int n, i, num, flag = 0, ret;
/* fopen files */
while ((ret = fscanf(fp1, "%d", &num)) != EOF) {
if (ret == 0) {
getc(fp1);
continue;
}
if (num % 2 == 0) {
fprintf(fp2, "%d ", num);
}
/* rest of the loop here */
}
/* fclose files */
}
If fscanf() fails to read a character, but does not return EOF, it can often solve things to getc(), to advance the buffer by one character. This method also works when using getchar() to advance stdin, after getting user input from scanf().
I need to read in a file that contains text, and then a double for that text. It is simply to get the mean and standard deviation for the set of numbers, so the text that comes before is irrelevant. For example, my input file looks a little like:
preface 7.0000
chapter_1 9.0000
chapter_2 12.0000
chapter_3 10.0000
etc..
In this case, it is finding the mean and std dev for the chapters of a book. I have the section of code below, but I'm not quite sure how to "ignore" the text, and only grab the doubles. At the moment this code prints out zeros and only exits the loop when it exceeds the array limit, which I set as a constant to 20 at the beginning of the program.
FILE *ifp;
char *mode = "r";
ifp = fopen("table.txt", mode);
double values[array_limit];
int i;
double sample;
if (ifp==NULL)
{
printf("cannot read file \n");
}
else
{
i = 0;
do
{
fscanf(ifp, "%lf", &sample);
if (!feof(ifp))
{
values[i] = sample;
printf("%.4lf \n", values[i]);
i++;
if (i>=array_limit) //prevents program from trying read past array size limit//
{
printf("No more space\n");
break;
}
}
else
{
printf("read complete\n");
printf("lines = %d\n", i);
}
}while (!feof(ifp));
fclose(ifp);
}
I think you could use fscanf(ifp, "%*[^ ] %lf", &sample) for reading from your file. The * says to ignore that particular match, the [] specifices a list of characters to match and the ^ indicates to match all characters except those in [].
Or possibly (a bit simpler) fscanf(ifp, "%*s %lf", &sample).
You have two major problems -- you're using feof which is pretty much always wrong, and you're not checking the return value of fscanf, which it what tells you whether you got a value or not (or whether you got to the eof).
So what you want is something like
while ((found = fscanf(ifp, "%lf", &values[i])) != EOF) { /* loop until eof */
if (found) {
/* got a value, so count it */
if (++i >= ARRAY_LIMIT) {
printf("no more space\n");
break;
}
} else {
/* something other than a value on input, so skip over it */
fscanf(ifp, "%*c%*[^-+.0-9]");
}
}
When reading in from a file, it's often best to use fgets to read one line at a time, then extract the parts you are interested in using sscanf:
#include <stdlib.h>
#include <stdio.h>
#define ARRAY_LIMIT 10
#define LINE_LENGTH 128
int main()
{
double values[ARRAY_LIMIT];
int i, count = 0;
double sample;
FILE *ifp = fopen("table.txt", "r");
if (ifp==NULL)
{
printf("cannot read file \n");
return 1;
}
char buff[LINE_LENGTH];
while (fgets(buff, LINE_LENGTH, ifp) != NULL)
{
if (sscanf(buff, "%*s %lf", &sample) != 1) break;
values[count++] = sample;
if (count == ARRAY_LIMIT) {
printf("No more space\n");
break;
}
}
fclose(ifp);
for (i = 0; i < count; ++i) {
printf("%d: %f\n", i, values[i]);
}
return 0;
}
fgets returns NULL if it encounters the end of the file, or if a read error has occurred. Otherwise, it reads one line of the file into the character buffer buff.
The asterisk %*s in the sscanf means that the first part of the line is discarded. The second part is written to the variable sample. I am checking the return value of sscanf, which indicates how many values have been read successfully.
The loop breaks when the end of the file is reached or the count reaches the size of the array.
The thing is that im trying to read some integers to know the levels of the game I have already passed through, then I want to put the integer of the current level to one if t is not already. It creates the file but doesn't write anything. Anyone know why? Now, it does it the first time when creating it with printf but when reading it gives status access violation.
void SaveGame(void)
{
FILE *pFile = fopen("SavedData.txt","rb");
int MyArray[8] = {0};
if(pFile)
{
fscanf(pFile, "%d %d %d %d %d %d %d %d" , MyArray[0], MyArray[1], MyArray[2], MyArray[3], MyArray[4], MyArray[5], MyArray[6], MyArray[7]);
fclose(pFile);
}
if(MyArray[Current] == 0)
MyArray[Current] = 1;
pFile = fopen("SavedData.txt", "wb");
if(pFile)
{
fprintf(pFile, "%d %d %d %d %d %d %d %d" , MyArray[0], MyArray[1], MyArray[2], MyArray[3], MyArray[4], MyArray[5], MyArray[6], MyArray[7]);
fclose(pFile);
}
}
You can do what you want something like this (untested) :
#define SAVE_FILE "SavedData.txt"
#define NUMS_SIZE 8
void SaveGame() {
FILE *f;
f = fopen(SAVE_FILE, "r");
if (!f) {
fprintf(stderr, "Error: Can't open save file for reading.\n");
exit(-1);
}
int nums[NUMS_SIZE] = {0};
int n, i = 0;
while (fscanf(f, "%d", &n) == 1) {
if (i >= NUMS_SIZE) break;
nums[i++] = n;
}
fclose(f);
f = fopen(SAVE_FILE, "w");
if (!f) {
fprintf(stderr, "Error: Can't open save file for writing.\n");
exit(-1);
}
int j = 0;
if (i > 0) fprintf("%d", nums[0]);
for (j = 1; j < i; ++j)
fprintf(" %d", nums[j]);
fclose(f);
}
That's not how you read a file.
For starters if it is a text file, open with mode "r", not "rb".
When you do a read operation you should check to see whether the read operation suceeded or failed. You don't do feof instead. There is a lot of code out there that does feof and most of it is wrong. Be wary when copying off internet code samples.
Also, it's a great idea to read the documentation for any standard function you use. You may learn things about the function that you didn't know. For example, fscanf returns how many items were successfully read.
So in your reading loop, either check that fscanf returns 8 (or loop 8 times as ooga suggested, checking for 1 each time). Don't check feof during the loop.
Once the read fails, THEN you have the option to do feof to find out why the read failed, if you care to know. It could have fail because you hit the end of file (feof), or because of a device error (ferror), or because the file had words in it instead of numbers.
When you do the writing part, make sure you only write numbers which were successfully read.