0

I have this text file here:

6 
81.00 
1 
27 
2004 
8 
7.00 
1 
2 
2009 
14 
97.00 
4 
4 
2001 
10 
38.00 
5 
17 
2006 

and I am trying to read all of these values into an array. Here is the bit of code that I have come up with:

int a[20], i, m;
FILE *fn;
fn = fopen("test.txt", "r");
m = 0;
i = 0;
while(!feof(fn)){
    for(i = 0; i < 20 ;i+=1){
        fscanf(fn, "%d", &a[i]);
        printf("%d ", a[i]);
    }
    m += 1;
}

This code correctly reads the first value of the text file because it is an integer but then incorrectly reads the rest of the values and I am assuming it's because of the fact that the second value in the text file is a float. I'm not sure if this is possible in C but if it is, I'm pretty sure that reading the integer lines separately from the float lines would work. Any help is appreciated.

user7438591
  • 29
  • 1
  • 6

1 Answers1

2

Looking at your input file, you have an int, then double (or float) and 3-more int values before the input pattern repeats. You match your read to your input. Here if you read and int, a double, and 3-more int values in a loop, you can properly read the data in the file and you can store, or use, the int, double and int, int, int however you like.

The key is to match your read loop to your input.

There is nothing to say you can't loop reading one value at a time until EOF keeping a counter (e.g. with int n = 0;) and then use some whacky logic like

if (n) { 
    if (n == 1)      /* read double; n++ */ 
    else if (n == 4) /* read int; n = 0; */ 
) else               /* read int, n++ */`

But that would certainly be a weird way to approach the problem. Or you can just make use of the fact that numeric format specifiers for scanf will skip leading whitespace (newlines being whitespace) and just read all values in a single loop.

Here is a simple example of a less whacky way to do it. You can then choose whatever value you need in an array and fill the array accordingly, e.g.

#include <stdio.h>

int main (int argc, char **argv) {

    int id, mo, day, year;  /* 4-int values   */
    double val;             /* 1-double value */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    /* read an int, double, int, int, int, use as required */
    while (fscanf (fp, "%d %lf %d %d %d", &id, &val, &mo, &day, &year) == 5)
        printf (" %02d/%02d/%04d  %2d  %5.2f\n", mo, day, year, id, val);

    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    return 0;
}

note: generally a better approach is to use fgets and then sscanf to parse the values from a buffer (which allows independent validation of the read and parse). However, when intentionally eating line ends as whitespace, fscanf alone can provide an advantage (one of the only circumstances where that is true).

Example Input File

$ cat prodid.txt
6
81.00
1
27
2004
8
7.00
1
2
2009
14
97.00
4
4
2001
10
38.00
5
17
2006

Example Use/Output

The following is just an example of using the values read each trip through the loop:

$ ./bin/rdprod <prodid.txt
 01/27/2004   6  81.00
 01/02/2009   8   7.00
 04/04/2001  14  97.00
 05/17/2006  10  38.00

Look things over and let me know if you have any questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85