Home > Back-end >  I am trying to read the formatted texts from files by using fscanf(), but it gives me a disgusting o
I am trying to read the formatted texts from files by using fscanf(), but it gives me a disgusting o

Time:01-02

Output is a bunch of zeros besided the printing of the name,code, salary and age, so where is the mistake, it keeps printing in an unformatted way

#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>

void main(void)
{
    //reading formatted text from a file.

    int code;
    char name[35];
    int age;
    float salary;

    FILE *pointer_;

    if ( (pointer_= fopen("Formated.txt","r"))==NULL)
        {
            printf("File is corrupted.");
        }

    while((fscanf(pointer_,"%d",&code))!=EOF)
        {
            fgets(name,35,pointer_);
            fscanf(pointer_,"%d", &age);
            fscanf(pointer_,"%f", &salary);
            printf("%-5d %-35s %-2d %-7.2f",code,name,age,salary);
        }

    fclose(pointer_);
}

CodePudding user response:

  1. Use constants NAME_LEN instead of hard-coding magic values, especially when you repeat that value 3 times.

  2. You need to check the return value of all your I/O operations otherwise you may be operating on uninitialized values. Any and all of these could encounter EOF of the stream. I used a couple of macros here to make the normal case more readable while still affecting the control in the error case.

  3. fgets() reads a line so the following fscanf() will fail if your input file Formated.txt [sic] doesn't contain a `\n' after the name field:

1 name
2 3.0
2 name2
3 4.0
  1. As you are reading the file it's not strictly required but it's a good idea fclose() the file before exit.

  2. It's a good practice to reduce variable scope as much as possible.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define CHECK_N(v, n, msg) {\
    int tmp = (v);\
    if(tmp == EOF) {\
        rv = EXIT_SUCCESS;\
        break;\
    }\
    if(tmp != n) {\
        printf("%s\n", msg);\
        break;\
    }\
}
#define CHECK_STR(s, msg) {\
    char *tmp = (s);\
    if(!tmp) {\
        if(feof(pointer_)) {\
            rv = EXIT_SUCCESS;\
            break;\
        }\
        printf("%s", msg);\
        break;\
    }\
}
#define NAME_LEN 35
#define str(s) str2(s)
#define str2(s) #s

int main() {
    int rv = EXIT_FAILURE;
    FILE *pointer_ = fopen("Formated.txt","r");
    if(!pointer_) {
        printf("fopen failed");
        return rv;
    }
    for(;;) {
        int code;
        CHECK_N(fscanf(pointer_,"%d", &code), 1, "code");

        char name[NAME_LEN];
        CHECK_STR(fgets(name, sizeof(name), pointer_), "name");
        name[strcspn(name, "\n")] = '\0';

        int age;
        float salary;
        CHECK_N(fscanf(pointer_,"%d %f", &age, &salary), 2, "age and salary");

        printf("%-5d %-" str(NAME_LEN) "s %-2d %-7.2f\n", code, name, age, salary);
    }
    fclose(pointer_);
    return rv;
}

and example output with the above mentioned input. Note that I replaced the \n in name with `\0' to format it like this:

1      name                               2  3.00   
2      name2                              3  4.00   

CodePudding user response:

Leftover '\n'

fscanf(pointer_,"%d"... does not consume any '\n' that may follow the numeric text, thus the following fgets() reads that line remnant.

while((fscanf(pointer_,"%d",&code))!=EOF)
        {
            fgets(name,35,pointer_);  // May only reads a `\n`.

Lack of result checking

The return values of fgets(name,35,pointer_); fscanf(pointer_,"%d", &age); fscanf(pointer_,"%f", &salary); are not checked. Unless they are as expected, assuming a good read is folly.

Look for unexpected data after the desired input on each line.

Recommend to read only with fgets()

After successfully reading the lines of data, parse them and check for parsing success.

If still wanting to use fscanf()

Check the return values.

  • Related