Home > other >  How to read from a file and parse it
How to read from a file and parse it

Time:04-22

I have a file .txt containing some values formatted like this:

0,30,25,10

Now, i open up the file and store it into an array char imposta_tratt[300];

FILE *fp;
fp=fopen("/home/pi/Documents/imposta_trattamento.txt","r");  
if (fp==0) return;                                        
fread(imposta_tratt,sizeof(imposta_tratt),1,fp);         
fclose(fp); 

Now i expect to have the array filled with my data. I have the values separated by a , so i go on and parse it:

 const char delim[2] = ",";
 int t=0;
 char *token = strtok(imposta_tratt, delim);
    while (token!=NULL){
    
        strcpy(tratt[t],token);
        token = strtok(NULL, delim);
        tratt[t]=token;
        t  ;
    }

Here, referring to whats in the file .txt, i expect to have tratt[0]=0; tratt[1]=30; tratt[2]=25; and so on, but seems like i am missing something since it's not like this.

All i want is to have the values of the txt file stored in single variables. Can someone help?

CodePudding user response:

With fread you need to null terminate the read array of characters so you can then pass it to the parser function, you can use the return value of fread to do this.

The second argument of fread is the size in bytes of each element to be read, which is 1 given that is the size of a character, whereas the third argument is the number of elements, we can set this one to the size of the destination buffer.

ssize_t size = fread(imposta_tratt, 1, sizeof(imposta_tratt) - 1, fp);

if(size > 0)
    imposta_tratt[size] = 0;

For the parsing:

char tratt[size][30];

const char delim[2] = ",";
int t = 0;

char *token = strtok(imposta_tratt, delim);

while (token != NULL) {

if(strlen(token) < 30)
  strcpy(tratt[t], token);  

token = strtok(NULL, delim);
t  ;

Be sure to not lose t which will be handy to iterate over the tratt array.

Live sample

Note that the parsed values are still strings, if you want to convert them into int you can use strtol to do it.

CodePudding user response:

Suppose "in.txt" has contents

0,30,25,10

The below program uses fscanf to read the integers into the tratt array, one-by-one. As we read integers using fscanf, we make sure it's return value is as expected. If not, we close the file and exit. In the event that the return value of fscanf is not as expected, the program also prints which type of error occurred. Currently, if any error occurs, the program stops. However, you can make the program behave differently depending on the error that occurred if you like.

As output, the program prints all of the integers read into the tratt array. The output is

0
30
25
10

Now this program assumes we know the number of elements we want to read into tratt. If we do not, we could allow for dynamically allocating more memory should the array need more elements or perhaps "in.txt" could contain a data structure, say, at the beginning/end of the file that records information about the file, such as the number of numbers in the file and the data type (a binary file would be best suited for this). These are just a couple of the possibilities.

A better approach might be to read characters in one-by-one (say, using getc) and use strtol to convert a sequence of character digits to a long int (I would have taken an approach similar to this).

Nevertheless, this approach is more succinct and should suffice.

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

#define FILE_NAME "in.txt"
#define MAX_LEN 4

int main(void) {

    int i, tratt[MAX_LEN];
    FILE *fp = fopen(FILE_NAME, "r");      /* open file for reading */

    /* if cannot open file */
    if (fp == NULL) {

        printf("Cannot open %s\n", FILE_NAME);
        exit(EXIT_FAILURE);

    }

    /* read integer, checking return value of scanf as expected */
    if (fscanf(fp, "%d", &tratt[0]) != 1) {
        if (ferror(fp))
            printf("fscanf: read error\n");
        else if (feof(fp))
            printf("fscanf: end of file\n");
        else
            printf("fscanf: matching failure\n");

        fclose(fp);
        exit(EXIT_FAILURE);
    }

    for (i = 1; i < MAX_LEN; i  )
        /* read comma plus integer, checking return value of scanf */
        if (fscanf(fp, ",%d", &tratt[i]) != 1) {
            if (ferror(fp))
                printf("fscanf: read error\n");
            else if (feof(fp))
                printf("fscanf: end of file\n");
            else
                printf("fscanf: matching failure\n");

            fclose(fp);
            exit(EXIT_FAILURE);

        }
    fclose(fp);    /* close file */

    /* print integers stored in tratt */
    for (i = 0; i < MAX_LEN; i  )
        printf("%d\n", tratt[i]);

    return 0;

}
  • Related