joofil
joofil

Reputation: 13

Read file in columns in C

So, I have a file like this:

12345 name1 18 500.000000
12345 name2 18 500.000000

And I wanted to read the file and each column go to a different variable. So I coded this:

void updateStruct() {
    char c;
    int lines, i;
    accounts account[accMAX];
    FILE *acc = fopen("acc.dat", "r+");
    if (acc == NULL)
        return;
    for (c = getc(acc); c != EOF; c = getc(acc))
        if (c == '\n')
            lines += 1;
    fscanf(acc, "%d %s %d %f", &account[0].number, account[0].name,
                               &account[0].age, &account[0].balance);
}

Somehow, the fscanf() doesn't attribute any value to the variables. What am I doing wrong?

Upvotes: 1

Views: 38

Answers (2)

chqrlie
chqrlie

Reputation: 145297

The for loop to compute the number of lines reads the whole file. fscanf() fails to convert anything and returns EOF.

You must rewind the position to the beginning of file with rewind(acc) or fseek(acc, 0L, SEEK_SET).

Note also that variable c must have type int for the EOF test to function correctly. Furthermore you should also count the last line that may or may not have a newline.

Here is a modified version:

accounts *updateStruct(int *countp) {
    int c, last, lines, i;
    FILE *acc = fopen("acc.dat", "r");
    if (acc == NULL)
        return NULL;
    last = EOF;
    while ((c = getc(acc)) != EOF) {
        if (c == '\n')
            lines += 1;
        last = c;
    }
    if (last != '\n') { // last line did not have a newline
        lines += 1;
    }
    rewind(acc);

    accounts *account = calloc(lines, sizeof(account));
    if (account == NULL) {
        fclose(acc);
        return NULL;
    }
    for (i = 0; i < count;) {
        if (fscanf(acc, "%d %s %d %f", &account[i].number, account[i].name,
                                       &account[i].age, &account[i].balance) != 4) {
            // invalid line: skip to the newline
            while ((c = getc(acc)) != EOF && c != '\n')
                continue;
            if (c == EOF)
                break;
        } else {
            i++;
        }
    }
    fclose(acc);
    *countp = i;
    return account;
}

Upvotes: 0

kaylum
kaylum

Reputation: 14044

The for loop leaves the file pointer at the end of the file. Call rewind to position the file pointer back at the start of the file before calling fscanf.

Upvotes: 1

Related Questions