soxarered
soxarered

Reputation: 163

How to read in a text file of tab-separated integers in C?

I have a file of simply tab-separated integers (a .txt file) and I wish to read them in with just C, line by line. So, say each line has 5 integers. How can I accomplish this?

My first attempt was as follows. It was just to read in a single integer, but even that didn't work:

    FILE *fp;
    char blah[255];
    int *some_int;
fp = fopen("test.txt", "rt");
while (fgets(blah, 255, fp) != NULL)
{
    sscanf(blah, "%d", some_int);
    printf("%d\n", *some_int);
}

Upvotes: 3

Views: 7700

Answers (3)

Null Set
Null Set

Reputation: 5414

#include <stdio.h>
int main(){
    FILE *fp;
    int scanned = 0;
    int some_ints[5];
    fp = fopen("test.txt", "r");
    while ((scanned = fscanf(fp, "%d %d %d %d %d", some_ints, some_ints+1, some_ints+2, some_ints+3, some_ints+4)) !=  EOF) {
        if(scanned ==5){
            printf("%d %d %d %d %d\n", some_ints[0], some_ints[1], some_ints[2], some_ints[3], some_ints[4]);
        }
        else {
            printf("Whoops! Input format is incorrect!\n");
            break;
        }
    } 
}

Upvotes: 2

Chris Lutz
Chris Lutz

Reputation: 75399

Here's a way no one else suggested, that doesn't use fscanf so you can have sane error handling:

char buffer[BUFSIZE];
size_t size = 5;
int *data = malloc(size * sizeof *line);

if(line == NULL) error();

while(fgets(buffer, sizeof buffer, fp)
  {
    size_t i = 0;
    char *next = buffer;
    while(*next && *next != '\n')
      {
        data[i++] = strtol(next, &next, 0);
        // check for errors
      }
  }

Basically, instead of trying to use *scanf's "%d" to read characters, use the function it (probably) calls to do the conversion: strtol. Where *scanf goes through the string to match the format string but doesn't let you "save your place" in between function calls, strtol does, which is what you need to read an arbitrary number of integers.

I haven't written all your code for you - you have to do the hard error handling. Possible errors include:

  1. i == size, in which case you can try to make data bigger with realloc. Alternately, you could loop through the buffer and count how many numbers there are beforehand, then allocate that many so you don't need to reallocate later.
  2. fgets didn't read the entire line (check that the last character before '\0' is '\n'). In this case you'll probably want to refill the buffer and keep reading numbers. Be careful in this case - you'll likely need to go back and recalculate the last number - fgets might have cut it off. (This is one disadvantage to using fgets.)
  3. Erroneous input - handle however you like.

Upvotes: 3

JCooper
JCooper

Reputation: 6525

I'd do something like this:

int storedVals[MAX_STORED_VALS];
int bf;
int ii=0;

while (!feof(fp) && ii<MAX_STORED_VALS) {
  if (fscanf(fp," %d",&bf)) {
    storedVals[ii++]=bf;
  }
}

fscanf automatically does white space trimming. So as long as there's a space in your scan string, it'll get rid of zero or more \t (tabs) and \n (newlines) to find the next integer. Of course, this doesn't do much by way of error correction.

Upvotes: 1

Related Questions