Problems Reading File in C - comma delimiter

2

Help kindly.

I have the following file line structure:

99933311133,UM NOME QUALQUER,8485885855,UM ENDERECO QUALQUER,84 9992212,S,S

The default is: string-comma-string-comma-string-comma-string-comma ... That is, each field is separated by a comma.

To read, I intended to capture line by line with fgets, and then assign the value to each variable using fscanf, thus:

while (fgets(linha, TAM_BUFFER, arq)) { // lê cada linha do arquivo por vez, cada linha está na variável buffer
    fscanf(arq, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,]\n", cpf, nome, cnh, endereco, contato, ind_brasileiro, ind_estado_civil);

In fgets each line of the file is stored in the variable "line", like a gut.

In fscanf the variable arq is the variable with the file open in read mode.

This solution is not even close to what I need because the result is catastrophic:

Wouldanyonehaveanideaofwhattodotofixit?

WhatIwanttoappearonthescreenisatextlikethis:"CPF: 123456666, name: So-and-so, CNH number: 939393939393 ....".

    
asked by anonymous 07.11.2017 / 23:22

1 answer

2

You can use the strtok() function of the default library string.h to "break" the row in fields.

The following function is able to split the string src , using the delim delimiter and return it as an array of strings:

char ** strsplit( const char * src, const char * delim )
{
    char * pbuf = NULL;
    char * ptok = NULL;
    int count = 0;
    int srclen = 0;
    char ** pparr = NULL;

    srclen = strlen( src );

    pbuf = (char*) malloc( srclen + 1 );

    if( !pbuf )
        return NULL;

    strcpy( pbuf, src );

    ptok = strtok( pbuf, delim );

    while( ptok )
    {
        pparr = (char**) realloc( pparr, (count+1) * sizeof(char*) );
        *(pparr + count) = strdup(ptok);

        count++;
        ptok = strtok( NULL, delim );
    }

    pparr = (char**) realloc( pparr, (count+1) * sizeof(char*) );
    *(pparr + count) = NULL;

    free(pbuf);

    return pparr;
}

Then you can abstract the fields of your record into a data structure:

struct record_s
{
    char * cpf;
    char * nome;
    char * cnh;
    char * endereco;
    char * contato;
    char * ind_brasileiro;
    char * ind_estado_civil;
};

typedef struct record_s record_t;

Since the order of the fields of your record in the file is always the same, the following implementation is able to map the field with the member of the structure, converting the line read to a filled data structure:

record_t * parse_record( char * linha )
{
    char ** pp = NULL;
    record_t * cad = NULL;

    pp = strsplit( linha, "," );

    cad = (record_t*) calloc( 1, sizeof(record_t) );

    cad->cpf = strdup(pp[0]);
    cad->nome = strdup(pp[1]);
    cad->cnh = strdup(pp[2]);
    cad->endereco = strdup(pp[3]);
    cad->contato = strdup(pp[4]);
    cad->ind_brasileiro = strdup(pp[5]);
    cad->ind_estado_civil = strdup(pp[6]);

    strsplitfree( pp );

    return cad;
}

Putting it all Together:

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

#define LINE_MAX_LEN            (1024 * 2)   /* 2 KBytes */

struct record_s
{
    char * cpf;
    char * nome;
    char * cnh;
    char * endereco;
    char * contato;
    char * ind_brasileiro;
    char * ind_estado_civil;
};


typedef struct record_s record_t;


char ** strsplit( const char * src, const char * delim )
{
    char * pbuf = NULL;
    char * ptok = NULL;
    int count = 0;
    int srclen = 0;
    char ** pparr = NULL;

    srclen = strlen( src );

    pbuf = (char*) malloc( srclen + 1 );

    if( !pbuf )
        return NULL;

    strcpy( pbuf, src );

    ptok = strtok( pbuf, delim );

    while( ptok )
    {
        pparr = (char**) realloc( pparr, (count+1) * sizeof(char*) );
        *(pparr + count) = strdup(ptok);

        count++;
        ptok = strtok( NULL, delim );
    }

    pparr = (char**) realloc( pparr, (count+1) * sizeof(char*) );
    *(pparr + count) = NULL;

    free(pbuf);

    return pparr;
}


void strsplitfree( char ** strlist )
{
    int i = 0;

    while( strlist[i])
        free( strlist[i++] );

    free( strlist );
}


record_t * parse_record( char * linha )
{
    char ** pp = NULL;
    record_t * cad = NULL;

    pp = strsplit( linha, "," );

    cad = (record_t*) calloc( 1, sizeof(record_t) );

    cad->cpf = strdup(pp[0]);
    cad->nome = strdup(pp[1]);
    cad->cnh = strdup(pp[2]);
    cad->endereco = strdup(pp[3]);
    cad->contato = strdup(pp[4]);
    cad->ind_brasileiro = strdup(pp[5]);
    cad->ind_estado_civil = strdup(pp[6]);

    strsplitfree( pp );

    return cad;
}


void destroy_record( record_t * cad )
{
    free(cad->cpf);
    free(cad->nome);
    free(cad->cnh);
    free(cad->endereco);
    free(cad->contato);
    free(cad->ind_brasileiro);
    free(cad->ind_estado_civil);

    free(cad);
}


void show_record( record_t * cad )
{
    printf( "[ REGISTRO ]\n" );
    printf( "   CPF: %s\n", cad->cpf );
    printf( "   Nome: %s\n", cad->nome );
    printf( "   CNH: %s\n", cad->cnh );
    printf( "   Endereco: %s\n", cad->endereco );
    printf( "   Contato: %s\n", cad->contato );
    printf( "   Ind. Brasileiro: %s\n", cad->ind_brasileiro );
    printf( "   Estado Civil: %s\n", cad->ind_estado_civil );
    printf( "\n" );
}


int main( int argc, char * argv[] )
{
    char line[ LINE_MAX_LEN + 1 ];
    record_t * c = NULL;
    FILE * fp = NULL;

    fp = fopen( argv[1], "r" );

    while( fgets( line, LINE_MAX_LEN, fp ) )
    {
        c = parse_record( line );
        show_record( c );
        destroy_record( c );
    }

    fclose(fp);

    return 0;
}

Input.txt:

12312312300,JOSE SILVA,56548656,SAO PAULO,(11) 999991234,S,N
98798798700,MARIA SOUZA,32443234,RIO DE JANEIRO,21 978783434,S,S
88877766600,JOAO CARLOS,78645554,BRASILIA,61 945454532,N,N
99933311133,UM NOME QUALQUER,8485885855,UM ENDERECO QUALQUER,84 9992212,S,S

Testing:

$ ./teste entrada.txt
[ REGISTRO ]
   CPF: 12312312300
   Nome: JOSE SILVA
   CNH: 56548656
   Endereco: SAO PAULO
   Contato: (11) 999991234
   Ind. Brasileiro: S
   Estado Civil: N


[ REGISTRO ]
   CPF: 98798798700
   Nome: MARIA SOUZA
   CNH: 32443234
   Endereco: RIO DE JANEIRO
   Contato: 21 978783434
   Ind. Brasileiro: S
   Estado Civil: S


[ REGISTRO ]
   CPF: 88877766600
   Nome: JOAO CARLOS
   CNH: 78645554
   Endereco: BRASILIA
   Contato: 61 945454532
   Ind. Brasileiro: N
   Estado Civil: N


[ REGISTRO ]
   CPF: 99933311133
   Nome: UM NOME QUALQUER
   CNH: 8485885855
   Endereco: UM ENDERECO QUALQUER
   Contato: 84 9992212
   Ind. Brasileiro: S
   Estado Civil: S
    
08.11.2017 / 03:08