While() read by line in file . CSV

Asked

Viewed 439 times

0

Good morning,

I have the following structures:

typedef struct celCidade *apontadorCidade;
typedef struct celEstado *apontadorEstado;

typedef struct{

    char nome[100];
    int populacao;
    int beneficiarios;
    int qtdCidades;
    float idh;
    apontadorEstado proxEstado;
    apontadorCidade Arv;

}celEstado;

typedef struct{

     char nomeCidade[100];
     char nomeEstado[100];
     int populacao;
     int beneficiarios;
     float idhm;
     apontadorCidade esq;
     apontadorCidade dir;

 }celCidade;

Each field of this structure has its data contained in a file. csv, where each city should be associated with its due state, then the screening should be done while reading the data with its due if’s and Else’s and because it is a file with a considerable amount of data, I would like to read through a while(), because I find it more practical, where the stopping condition would be when there is no more data to be read.

So far I’m at square one.

void carregaArquivo(FILE *arquivo){

    arquivo = fopen("data.csv", "r");

    if(arquivo != NULL){
        printf("Arquivo lido com sucesso!\n");
    }else{
        printf("Erro ao carregar o arquivo!\n");
    }


} 

Here’s the problem: I have no idea how to do this reading, I’ve read about fscanf(), fgets() and other ways I can use to read this data, but I would like to know:

  1. What is the best function to read lines of a CSV file
  2. How to identify the order of fields in the program
  3. What would be the stopping condition of the while()?

Thank you in advance!

  • You can read a file. txt?

  • No, it’s the same thing in csv?

  • 2

    Same thing, but it has several ways to read. I recommend searching for fscanf or fread functions to read the file. The while stop condition can check if you found the end of the while file (fscanf()!=EOF) it continues reading. You have to see what you need to do, to get an idea of how it looks best to perform this reading

  • 1

    "How to identify the order of the fields in the program": you need to know what you are reading, usually this means knowing which fields and in what order they will be in the file being read. " What would be the stop condition of while()": test by EOF at each reading.

  • Thanks for the tips, I will seek to know more about EOF and updated the question anything

  • 1

    best function to read per line is "fgets"; then has the analysis of the fields of a csv line; this task may not be trivial, depending on the accepted formats (for example, may have fields delimited by quotation marks ?" etc); if for professional use (and not as a college exercise) probably the most suitable is to look for some ready lib for that task (google "csv c library")

  • thanks for the zentrunix tip!

Show 2 more comments

2 answers

2


Starting with your questions:

What is the best function to read lines from a CSV file

Each case is a case and always depends on the structure your data has, validations that have to be applied, among other factors.

How to identify the order of fields in the program

As a general rule you know which file you are reading and which structure and order of fields exists in it. With this information the reading can be very direct, with fscanf for example (as I will illustrate later), but if you do not know then complicates drastically.

When you don’t know, you have to read line by line with fgets and tokenize the entrance through the ; with the strtok for example, and try to apply a reading of each type in the token until hit one that works. Or read all fields as strings that is also not ideal.

What would be the stopping condition of the while()?

It depends on the type of reading you have. With fscanf the stopping condition is based on the amount of elements read or even using EOF which corresponds to the end of the file.

Use fgets the stop is usually given by the return of NULL of function.

Reading with fscanf

In my view this is the most direct way to read, but implies that you know the exact structure of the file. Imagine you have a csv with 3 integers per line. In that case you would only need the following code to read the file to the end:

int valor1, valor2, valor3;

while(fscanf(arquivo_csv, "%d;%d;%d", &valor1, &valor2, &valor3) == 3){
    //fazer coisas com os 3 campos
}

In the example above the fscanf already includes the ; separating each field and its respective %d for each whole. The == 3 will keep the while to be executed as long as it is possible to read 3 elements. Equally valid would be while(fscanf(...) != EOF){.

This solution will work perfectly even if you have fields that are of the type char or double(adjusting the parameters in the fscanf), but the problem starts when you need to read strings. String reading with %s read only one word and so if you are reading a full name, the %s will just pick up the first name, not reading the line correctly. But even in this case you can get around the problem by changing the reading of %s for %[^;] which means: read until you catch the next ;.

The previous example reading now 1 string and 2 integers would look like this:

char valor1[50];
int valor2, valor3;

while(fscanf(arquivo_csv, "%[^;];%d;%d", valor1, &valor2, &valor3) == 3){
    //fazer coisas com os 3 campos
}

For your example just need to adjust the required fields to the types you have, being that pointers can never be read and stored directly in the file. Instead you need to keep a valid reference to the element, such as a id or nome unique, and construct the pointer based on that reference.

After all, this reading with fscanf it is easier to break if the file is badly formatted.

  • Thank you so much for the answer! as soon as I get home I will test!

1

From their structures I presume you want to create a list linked with nodes "states", each pointing to a tree with nodes "cities".

To implement the complete program I would need to know a little how your file is formatted. I also need to know what kind of tree you want to create for the cities of a state.

Your question refers to how to read a file line by line and separate its fields. The key functions for this task are "fgets()" and "Strtok()". The following program reads lines in the "input" file and lists the fields, which are separated by "DELIMITER".

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

#define MAX_LINHA 1024
#define DELIMITADOR ","

int main(int argc, char *argv[])
{   
    // abre arquivo
    FILE* fp = fopen("input", "r");
    if (fp == NULL) 
    {
        printf("Falha ao abrir o arquivo");
        return(1);
    }

    // separa linhas
    char linha[MAX_LINHA];
    char *campo;
    while (fgets(linha, MAX_LINHA, fp) != NULL) 
    {
        printf("Linha: %s", linha);

        // separa tokens
        printf("Campos:\n");
        campo = strtok(linha, DELIMITADOR);
        while( campo != NULL ) 
        {
            printf( "--> %s\n", campo);
            campo = strtok(NULL, DELIMITADOR);
        }
    }

    fclose(fp);
    return(0);
}
  • 1

    Exactly that, we linked states and each with its city tree. Thank you very much for the answer, as soon as we get home I will test!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.