Home > Back-end >  C parsing data from files
C parsing data from files

Time:06-09

So I'm trying to parsing some data given in a text file into a C program. The text file consists of:

4 4
1 1 0 0
1 1 0 0
0 0 1 1
0 0 1 1

The first two numbers are the row and length needed for the 2D array to store the integers. So far my code is:

        file = fopen(argv[1], "r");
        if (file == NULL)
        {
            perror("File IO error\n");
        }
        else
        {
            while(fgets(line, sizeof(line), file) != NULL)
            {        
                
                if(sscanf(line, "%d %d %d %d", &a, &b, &c, &d) == 4)
                {
                    printf("%d %d %d %d\n", a, b, c, d);
                }
                else
                {
                    sscanf(line, "%d %d", &ROW, &COL);
                    printf("ROW: %d COL: %d\n", ROW, COL);
                }

My problem I'm having is that there are other text files that need to be inputted. They are not the same rows and colums as the above one. E.g:

15 15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 1 0 1 0 0 0 0 1 0
0 1 0 0 0 0 1 0 1 0 0 0 0 1 0
0 1 0 0 0 0 1 0 1 0 0 0 0 1 0
0 0 0 1 1 1 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 0 0 1 1 1 0 0 0
0 1 0 0 0 0 1 0 1 0 0 0 0 1 0
0 1 0 0 0 0 1 0 1 0 0 0 0 1 0
0 1 0 0 0 0 1 0 1 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

As my code is only for 4 integers each line, it wouldn't work on a larger or smaller file. How would I make it dynamic and parse according to the size. Thanks

CodePudding user response:

if your text file is formatted. you can use strtok and strtol

#include<stdio.h>
#include<string.h>
#include <stdlib.h>
int main() {
    char payload[] = {"1 2 3 4"};
    char *token = strtok(payload, " ");
    while (token) {
        int v = (int)strtol(token,NULL,10);
        printf("%d\n",v);
        token = strtok(NULL, " ");
    }
    return 0;
}

CodePudding user response:

You can just run scanf in loop like this:

int rows, cols;
if(fscanf(file, "%d %d", &rows, &cols) != 2) {
    // error
}

int num;
for(int i = 0; i<rows;   i) {
    for(int j = 0; j < (cols - 1);   j) {
        if(fscanf(file, "%d", &num) == 1) {
            printf("%d ", num);
        }
        else { /* error */ }
    }
    if(fscanf(file, "%d", &num) == 1) {
        printf("%d\n", num); // last col handled differently
    } 
    else { /* error */ }
}

If you want to receive whole row at one, you can just use int array (no need for string, like in your example)

int* row = malloc(sizeof(int) * cols); // allocate memory for array
for(int i = 0; i<rows;   i) {
    for(int j = 0; j < cols;   j) {
        if(fscanf(file, "%d", &row[j]) != 1) { /* error */}
    }
    // do what you want with your row
}
free(row); // release array memory

CodePudding user response:

In order to read files with different number of rows and columns, I suggest that you allocate memory dynamically after having read the first line containing the number of rows and columns.

Example:

#include <stdio.h>
#include <stdlib.h> // malloc/free

int main(int argc, char* argv[]) {
    if(argc != 2) return 1;

    FILE *file = fopen(argv[1], "r");
    if (file == NULL) {
        perror("fopen");
        return 1;
    }

    int ROW, COL;
    if(fscanf(file, "%d %d", &ROW, &COL) != 2 || ROW < 1 || COL < 1) {
        fprintf(stderr, "invalid file format\n");
        return 1;
    }

    // allocate the needed memory to store the data:
    int (*arr)[COL] = malloc(ROW * sizeof *arr);
    if(arr == NULL) {
        perror("malloc");
        return 1;
    }

    // read the data from file into your dynamically allocated array:
    for(int row = 0; row < ROW;   row) {
        for(int col = 0; col < COL;   col) {
            if(fscanf(file, " %d", &arr[row][col]) != 1) {
                fprintf(stderr, "invalid file format\n");
                fclose(file);
                free(arr);
                return 1;
            }
        }
    }
    fclose(file);

    // display the result:
    printf("ROW: %d COL: %d\n", ROW, COL);
    for(int row = 0; row < ROW;   row) {
        for(int col = 0; col < COL;   col) {
            printf("%d ", arr[row][col]);
        }
        putchar('\n');
    }

    free(arr); // release the memory allocated dynamically
}
  •  Tags:  
  • c
  • Related