fscanf inside a do-while not working - c

So, I'm having problem to read a file using a do-while loop:
#include <stdio.h>
int main(){
FILE* f = fopen("teste.txt", "r");
double i;
do{
fscanf(f, "%lf ", &i);
printf(" %.0lf", i);
} while (fscanf(f, "%lf", &i) != EOF);
return 0;
}
The file is ike that:
1 2 3 4 5
When i run the program, the output is:
1 3 5
Can anyone help me?

You are discarding the result of every second call to fscanf.
In the while condition you call fscanf and check for EOF but you do not use the value of i. Then the next statement is back up the top of the loop , doing another fscanf which reads the next value (and does not check for error).
Also, you have an infinite loop if the file contains any text which is not a valid double.
The loop should be:
while ( fscanf(f, "%lf", &i) == 1 )
{
printf(" %.0f", i);
}

It should be:
#include <stdio.h>
int main() {
FILE* f = fopen("teste.txt", "r");
double i;
fscanf(f, "%lf ", &i);
do {
printf(" %.0lf", i);
} while (fscanf(f, "%lf", &i) != EOF);
return 0;
}
after fscanf(f, "%lf ", &i);, f contains 1. Now after fscanf(f, "%lf", &i) != EOF, f contains 2. You are not printing that 2 and after next fscanf(f, "%lf ", &i);, f will contain 3. In short you are calling fscanf twice in every loop and printf only once.

Related

Reading Rows and Columns from File in C

I am trying to read this input txt file with my C code:
4 3
1.4 4.6 1
1.6 6.65 1
7.8 1.45 0
7 -2 2
and separate them into rows and columns so that I can sort. I tried doing that but I kept getting weird numbers.
So I tried printing out the rows and columns after I read them from the file and the output was zero. I realized then that my code is not reading the numbers from my text file properly. I have tried different means to fix to no avail. Any help or pointers will be highly appreciated.
#include <stdio.h>
#include <string.h>
#include <stdbool.h> //for bool
int main(){
setvbuf(stdout, NULL,_IONBF, 0);
int c;
FILE *file;
FILE *infile;
char filename[99];
char choice;
int rows, columns;
//while(choice == 'y' || choice == 'Y'){
printf("%s", "Enter file name: ");
fgets(filename, 99, stdin);
char *p = strchr(filename, '\n'); // p will point to the newline in filename
if(p) *p = 0;
file = fopen(filename, "r");
if (file) {
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
else{
puts("FILE NOT FOUND");
}
//read rows and columns from file
printf("%s","\n");
fscanf(file, "%d", &rows);
fscanf(file, "%d", &columns);
printf("%d", rows);
printf("%d", columns);
}
Problem 1
int rows = 0;
int columns = 0;
float matrix[rows][columns];
float sumOfRows[rows];
is not right.
After that, the number of elements in matrix and sumOfRows is fixed. They won't change if you change the values of rows and columns later in your program.
You need to read the values of rows and columns first before you define matrix and sumOfRows.
Problem 2
fscanf(file, "%d", &matrix[rows][columns]);
printf("%f",matrix[rows][columns]);
are not right either. Given the defition of matrix, use of matrix[rows][columns] is not right. They access the array using out of bounds indices.
Remember that given an array of size N, the valid indices are 0 to N-1.
Here's one way to proceed to resolve your problems:
fscanf(file, "%d", &rows); // Use %d, not %f
fscanf(file, "%d", &columns); // Use %d, not %f
// Now define the arrays.
float matrix[rows][columns];
float sumOfRows[rows];
// Read the data of matrix
for (int i = 0; i < rows; ++i )
{
for (int j = 0; j < columns; ++j )
{
fscanf(file, "%f", &matrix[i][j]); // Use %f, not %d
}
}
Your problem (actually, two problems) are in the if (file) {... block. First, you use a loop to read all characters from the file. Because of that, at the end of the loop you are also at the end of the file. Any further calls to fscanf result in undefined behavior.
Second, if the file did not open, you print a message (to the wrong output) and still continue to the fscanf part, which definitely leads to undefined behavior.
Solution: Remove the while loop and fix the error handling code:
if(file) {
// Nothing!
} else {
perror(filename);
return 1; // or return EXIT_FAILURE;
}

fscanf only reading first field C

I'm doing an assignment where I have to create a grade report program. Everything was working, but the final section has me altering the code so it reads data from a file (student.dat) and uses that as data for the output.
Sample of student.dat (there are 100 lines similar to these in total).
Julius Hoffman,95,92,79,90,90
Dianne Conner,100,100,80,90,85
Mitchell Cooper,100,95,89,85,95
My issue is with the fscanf command as it is only reading the first name
Sample Output (the final program will have 100 lines total)
Please enter a filename: student.dat
Student Name W(30%) Q(15%) T(20%) P(15%) E(20%) TOTAL(100%) GRADE
Julius Hoffman 0 0 0 0 0 0.00 F
0 0 0 0 0 0.00 F
0 0 0 0 0 0.00 F
The function that handles the file reading is below.
int read(char filename[], char name[][MAX_NAME_SIZE], float w[], float q[], float t[],float p[],float e[]){
int i =0;
FILE *fp = NULL;
fp = fopen(filename, "r");
if (fp != NULL) {
for(i=0; i < MAX_CLASS_SIZE; i++){
fscanf(fp, "%[^,]%[^,]%[^,]%[^,]%[^,]%[^,]", name[i], w[i], q[i], t[i], p[i], e[i]);
}
fclose(fp);
} else {
printf("Failed to open file\n");
}
return 0;
}
And just in case, this is the function that handles presenting the report to the user
void display( char name[][MAX_NAME_SIZE], float w[], float q[], float t[], float p[], float e[], float total[], char grade[][MAX_LETTER_SIZE] ) {
int i = 0;
printf("Student Name W(30%) Q(15%) T(20%) P(15%) E(20%) TOTAL(100%) GRADE\n===================================================================================\n");
for(i = 0; i < MAX_CLASS_SIZE; i++){
printf("%-15s %-3.0f %-3.0f %-3.0f %-3.0f %-3.0f %-3.2f %-15s\n", name[i], w[i], q[i], t[i], p[i], e[i], total[i], grade[i]);
}
}
Any advice is appreciated.
Mis-match scanf() format specifier. Use "%f" with float *
Also save debug time. Simply read the line into a buffer and then scan it.
" %n" scans white-space and then save the index of the scan into n. So if n > 0, code knows the entire line scanned. if buf[n], the scan did not finish at the end of the line.
for(i=0; i < MAX_CLASS_SIZE; i++) {
char buf[200];
if (fgets(buf, sizeof buf, fp) == NULL) break;
int n = 0;
sscanf(buf, fp, " %[^,],%f ,%f ,%f ,%f ,%f %n",
name[i], &w[i], &q[i], &t[i], &p[i], &e[i], &n);
if (n > 0) break; // format error
if (buf[n]) break; // extra text
// Use name[i], w[i], q[i], t[i], p[i], e[i]
}
Your fscanf should look like this:
fscanf(fp, " %[^,],%d,%d,%d,%d,%d", name[i], &w[i], &q[i], &t[i], &p[i], &e[i]);
Notes:
%[^,] control format is only for reading characters until the comma. There is no reason why you use that control format for all your data (which include several int afterwards I suppose).
You should also check the return results of your fscanf, make sure that it returns the correct value, in this case you are reading 6 values from your text file at a time.

Reading combinations of string and integer from file in C

I am novice to C langugage, so please bear with me. I've tried to read a file which contains strings but output obtained is single character.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define CALLOC(num, type) ((char*)calloc (num, sizeof(char)))
#define FREE(addr) (free((void*) (addr)))
int i, count;
char *x, *y, *z;
int main (void)
{
FILE *stream;
if ( (stream = fopen ( "test.txt", "r" )) == NULL )
{ printf ("Cannot read the new file\n");
exit (1);
}
count = 3;
x=CALLOC(count, char);
y=CALLOC(count, char);
z=CALLOC(count, char);
for ( i=0; i<count; i++ )
{ fscanf (stream,"%c %c %c", &x[i], &y[i], &z[i]);
printf ("\n %d %c %c %c ", i, x[i], y[i], z[i]);
}
FREE(x);
FREE(y);
FREE(z);
fclose (stream);
}
Input test.txt file contains
1 ab 1
2 aa 5
1 cc 1
current output
0 1 a b
1 1 2
2 a a
Expected output
0 1 ab 1
1 2 aa 5
2 1 cc 1
I doubt whether I should use a character array but it seems not working and I feel reading a int using char is acceptable. Here I require the expected output, for this any method/suggestion is appreciated.
%c reads in only one char. So it's not going to read ab as a single char. Your lines in file and your formats don't correctly to read an entire line.
A simple approach is to use fgets() and print the entire line:
char line[256];
i = 0;
while(fgets(line, sizeof line, stream))
{
printf ("%d %s", i, line);
i++;
}
By the way, macros for calloc and free are unnecessary. They really don't make the code any easier to read than directly using those functions.
And the casts in them are also unnecessary.
The problem is you have the scan file. %c read a 8bit value. You scanned 3 char, but the file is contain 4 characters. If you don't use to be the value of the x, y, z I don't understand why use malloc.
Here a working source:
#include <stdio.h>
#include <stdlib.h>
int main() {
int count,i;
char w,x,y,z;
FILE *stream;
if((stream = fopen("test.txt","r")) == NULL) {
printf("Cannot read the new file\n");
return 1;
}
count = 3;
for(i=0;i<count;++i) {
fscanf(stream,"%c %c%c %c\n",&w,&x,&y,&z);
printf("%d %c %c%c %c\n",i,w,x,y,z);
}
return 0;
}
for ( i=0;i<count; i++ )
{
fscanf (stream,"%s %s %s", x, y, z);
printf ("\n %d %s %s %s ", i, x, y, z);
}
You can modify your loop to this.This loop will read file until end of file and you have to use %s as ab is a string not charater so it can't be stored in a char variable.

Using fscanf() in c to read multiple lines

So I am trying to figure out how to use fscanf to read multiple lines from an in file. The in file looks like this:
8
1 8
1 7
1 9
1 8
3 2
3 8
0 0
1 5
2 4
0 0
The first number I want to obtain is going to be the size of an array I will be creating so I will just set it to n(in this example that number being the 8 at the beginning).
The following digits will be as follows: the left most number will tell me what index in my array I will queue the right most number in a list I have created.
The zeros just indicate where I will be terminating.
The way I was attempting to do it thus far is:
fscanf(in, "%d", &n)
//have obtained n
arr[n];
while( fgets(line, MAX_LEN, in) != NULL){
fscanf(in, "%d %d", &x, &y);
//from here I place them in their corresponding arrays
}
Code:
int main()
{
int i, j, k;
scanf ("%d\n", &i);
printf ("%d\n", i);
while (i){
--i;
scanf ("%d %d\n", &j, &k);
printf ("%d %d\n", j, k);
}
}
Execution:
./a.out <input.txt
This is using file redirection. Also check about freopen. If u use this, you no need to worry about fscanf syntax. If you suppose to fscanf only, then there are lots of example in Google. Please refer it.
1) Using fgets() right after fscanf(in, "%d", &n) leaves the first line's '\n' in stdin and only read a short line. Suggest avoid mixing fgets() with fscanf().
2) After using fgets() to read the line (good idea), use sscanf() (or strtol()) to read the numbers, not fscanf()
if (fgets(line, MAX_LEN, in) == NULL) Hanlde_EOF();
if (sscanf(line, "%d", &n) != 1) Handle_BadInput();
arr[n];
while(fgets(line, MAX_LEN, in) != NULL){
if (sscanf(in, "%d %d", &x, &y) != 2) Handle_BadData();
...
}

C Read until end of file

I currently have code that reads 4 lines and I want to be able to change that until EOF or my MAX const int value. I can not get the !EOF to work right and was wondering how would I change my code to accomplish this?
Thanks in advance
#include <stdio.h>
struct record{
char name[2];
int arrival_time;
int job_length;
int job_priority;
};
const int MAX = 40;
int main(void)
{
struct record jobs[MAX];
int i = 0;
int j;
FILE *f = fopen("data.dat","rb");
while (fscanf(f, "%s %d %d %d", &jobs[i].name, &jobs[i].arrival_time,
&jobs[i].job_length, &jobs[i].job_priority) == 4 && i < MAX)
i++;
for (j = 0; j < i; j++)
printf("%s %d %d %d\n", jobs[j].name, jobs[j].arrival_time,
jobs[j].job_length, jobs[j].job_priority);
fclose(f);
return(0);
}
Something like
while (fscanf(f, " %s ", &etc) != EOF) {
}
Then use feof(f) to check if it was a fscanf error or actually EOF.
Your code seems to do what you want, except:
char name[2];
Names will probably be longer than 1 character.
FILE *f = fopen("data.dat","rb");
You seem to be reading text ("r") file, not binary ("rb").
&jobs[i].name should be jobs[i].name
You need to change the order of the tests in your while() loop - you must test i < MAX before calling fscanf(), or else you'll potentially call it one too many times (you should also be passing jobs[i].name without the & to fscanf):
while (i < MAX && fscanf(f, "%s %d %d %d", jobs[i].name, &jobs[i].arrival_time,
&jobs[i].job_length, &jobs[i].job_priority) == 4)
Personnaly, I would code like this:
for(i=0 ; i<MAX ; ++i) {
fscanf(f, "%s %d %d %d", &jobs[i].name, &jobs[i].arrival_time,
&jobs[i].job_length, &jobs[i].job_priority);
if(ferror(f) || feof(f)) break;
}
The key point is that, at the best of my knowledge, you cannot know that a file is come to end without trying to read it. That is the reason why I check feof() and ferror() after having read data.
At the end of the loop, the variable i contains the number of read data

Resources