Search code examples
cscanf

Reading Numbers (integers and decimals) from file w/period as delimiter


Currently, I wanted to fetch the file with delimiter .. However, the using fscanf unable to differentiate decimals and integers.

Wanting to extract first two integers (separated by .) and the final decimals into tmp[]

Tried fscanf(file, "%d.", &tmp[j]); with %d, %d. and %f, neither had worked.


Result with %d: tmp[3]: {1.61149323e-43, 0, 0.409999996}

Result with %d.: tmp[3]: {1.61149323e-43, 5.7453237e-44, 24.3600006}

Result with %f: tmp[3]: {115.410004, 24.3600006, 113.489998}

%d and %d. [0] and [1] got gibberish, only %d. [3] got to be seems read right.
%f seems reading good, but it fused in the first two numbers into one decimals.

Do I had to use fgets() or fgetc()? or I can just change fscanf() format specifier to get it right?


Expected Result: (in debugger)

tmp[0]: 115
tmp[1]: 41
tmp[2]: 24.36

(file line 2 as input)
tmp[0]: 113
tmp[1]: 49
tmp[2]: 44

Source:

#include <stdio.h>
#include <stdlib.h>
int main() {
    FILE *file = fopen("data.txt", "r");
    float tmp[3] = {};
        for(int j = 0; j < 2; j++) {
            fscanf(file, "%d.", &tmp[j]);
        }
        fscanf(file, "%f", &tmp[2]);
} 

Data.txt

115.41.24.360
113.49.44
115.41.51.573

Solution

  • The %d conversion specification is for reading a decimal integer, and expects an int * argument. Similarly, the %i, %o, %u, %x and %X conversion specifications are also for integers.

    Using %f is not going to work; it will read the 'second integer' as the fraction part of the first floating-point value, and there's no way to stop it doing that (unless you can safely use %3f because there'll always be at most 3 digits — which is a dubious proposition).

    You'll need to use

    int i1, i2;
    if (fscanf(file, "%d.%d.%f", &i1, &i2, &tmp[2]) != 3)
    {
        …handle error…
    }
    tmp[0] = i1;
    tmp[1] = i2;
    

    This reads the integer values into int variables, then assigns the results to the float array elements. Note that you should always check the return value from fscanf() and friends. If it isn't what you expect, there's a problem (as long as your expectations are correct, which they will be once you've read the specification for fscanf() often enough — a couple of times a day for the first couple of days, once a day for the next week, once a week for the next month, and about once a month for the next year).