How to read dataset from text file to a 2D matrix

376 Views Asked by At

I have a dataset of form

0.547,0.797,2.860,1.398,Sharp-Right-Turn

0.541,0.786,2.373,1.919,Sharp-Right-Turn

0.549,0.784,2.370,1.930,Sharp-Right-Turn

0.983,0.780,2.373,1.701,Move-Forward

0.984,0.780,2.372,1.700,Move-Forward

0.983,0.780,2.378,1.602,Move-Forward

0.983,0.780,2.381,1.701,Move-Forward

.
.


ROWS=5456, COL 5

Its easy in MATLAB to load the text file into a data matrix. But am struggling in C. I tried this code

int main()
{
    struct node {
        float at1;
        float at2;
        float at3;
        float at4;
        char at5[30];
    } record[ROW][COL];

    FILE *file;
    int i, j;

    memset(record, 0, sizeof(record)); 
    file = fopen("sensor.txt", "r");

    if (file == NULL) {
        printf("File does not exist!");
    } else {
        for (i = 0; i < ROW; ++i) {
            for (j = 0; j < COL; ++j) {
                fscanf(file, "%f,%f,%f,%f,%s", &record[i][j].at1, &record[i][j].at2, &record[i][j].at3, &record[i][j].at4, &record[i][j].at5);
            }   
        }   
    }   
    fclose(file);

    for (i = 0; i < ROW; ++i)
        for (j = 0; j < COL; ++j) {
            printf("%f\t%f\t%f\t%f\t%s\n", record[i][j].at1, record[i][j].at2, record[i][j].at3, record[i][j].at4, record[i][j].at5);
        }
    return 0;
}

I am getting infinite rows and 4 cols of 0.000000 only.

I want to save the first four columns in one matrix and last column as another column matrix. Could I do that?

I have to build a classifier which I easily did in MATLAB without using predefined functions but reading data in C is hampering my code.

I know this might be a repeated question, but I tried solutions in other threads, they are not working on my dataset.

1

There are 1 best solutions below

4
On BEST ANSWER

First of all you have defined a record holding all your fields, that together forms each row. This means that when you read you have all values for a row so the struct dimension should be the maximum record available that is a monodimensional array of structures record.

But you cannot allocate such an huge struct on the stack, it will overflow, it's better to allocate it in dynamic memory:

struct node {
    float at1;
    float at2;
    float at3;
    float at4;
    char at5[30];
} record;

struct node *record = malloc(sizeof(struct node) * MAXRECORDS);

Another error is in the scanf, the last field of the structure record is already a pointer to char, so you don't need to dereference it.

This is a working code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXRECORDS 10

int main(int argc, char *argv[])
{
    struct node {
        float at1;
        float at2;
        float at3;
        float at4;
        char at5[30];
    };

    struct node *record = malloc(sizeof(struct node) * MAXRECORDS);

    FILE *file;
    int nRecords = 0;

    memset(record, 0, sizeof(record));
    file = fopen("sensor.txt", "r");

    if (file == NULL)
    {
        printf("File does not exist!");
    }
    else
    {
        while (EOF != fscanf(file, "%f,%f,%f,%f,%s", &record[nRecords].at1, &record[nRecords].at2, 
                                &record[nRecords].at3, &record[nRecords].at4, record[nRecords].at5) && nRecords<MAXRECORDS)
        {
            nRecords++;
        }
    }

    fclose(file);

    for (int i = 0; i < nRecords; ++i)
    {
        printf("%f\t%f\t%f\t%f\t%s\n",
                record[i].at1, record[i].at2, 
                record[i].at3, record[i].at4, record[i].at5);
    }
    return 0;
}

In a 'real' application you want dimension the array to some large enough value, and when you reach the end of the allocated space you can reallocate it for other data. This allows you to read a file of how many entries you want without knowing their number before the reading.

P.S. I added the check for maximum number of record to read. But this remain a sample, many checks are still missing i.e. I don't check value returned by malloc.