Thread: Segmentation fault reading and parsing data from a text file

  1. #1
    Registered User
    Join Date
    May 2012
    Posts
    5

    Segmentation fault reading and parsing data from a text file

    Guys,

    I'm trying to read the content from a text file that goes is with this format:

    First Line: last account created
    Other Lines: Account number \t holdersName \t personalCode \t money

    Well, in order to do it, I got this structure where I want to insert the data so I can use for other functions of it:

    Code:
    typedef struct ContaFicheiro {
        unsigned int numero;
        char nomeUtilizador[19];
        char PIN[4];
        float saldo;
    } ContaFicheiro;
    And the function that reads from this file is this one:

    Code:
    void leAccounts() {
        
        FILE *fp;
        int i = 0;
        int k;
        char linha[80];
        
        unsigned int ultimaContaCriada = 0;
        char *item;
        
        if( (fp = fopen("accounts.txt", "r")) != NULL) {
            fscanf(fp, "%u\n", &ultimaContaCriada);
            
            //DEBUG
            printf("\nUltima conta criada: %u\n", ultimaContaCriada);
            
            while(fgets(linha, sizeof linha, fp) != NULL) {
                //DEBUG
                printf("\nLinha %d: %s\n", i, linha);             
    
                printf("Antes de fazer o tokenizer... \n");
    
                item = strtok(linha, "\t");
                contas[i].numero = atoi(item);
                printf("Finalizado o primeiro tokenizer.\n");    
            
                
                item = strtok(NULL, "\t");
                strcpy(contas[i].nomeUtilizador, item);
                item = strtok(NULL, "\t");
                strcpy(contas[i].nomeUtilizador, item);
                printf("Finalizado o segundo tokenizer.\n");
                
                item = strtok(NULL, "\t");
                strcpy(contas[i].PIN, item);
                printf("Finalizado o terceiro tokenizer.\n");
                
                item = strtok(NULL, "\t");
                contas[i].saldo = atoi(item);            
                printf("Finalizado ultimo tokenizer.\n");
    
                printf("\nConta %d: \nNumero: %u \t Nome: %s \t PIN: %s \t Saldo: %f \t \n", i, contas[i].numero,
                                                    contas[i].nomeUtilizador,
                                                    contas[i].PIN,
                                                    contas[i].saldo);
                
                i++;
            }
            
            //DEBUG            
            /*        
            for(k = 0; k < i; k++) {    
                printf("Numero: %u\tNome: %s\t PIN: %s\t Saldo: %f\n",     contas[k].numero, 
                                                 contas[k].nomeUtilizador, 
                                                 contas[k].PIN, 
                                            contas[k].saldo);
            }*/
    
        }
    The problem is that, when I run it it gives me the "Segmentation Fault" error and I think it's because of the strtok or strcpy function, but I don't have any idea on how to correct it.

    Can you help me with this?

    P.S.: Don't pay that much attention to the printfs in the middle of the while cycle, it was purely to understand if the program was getting there before the "segmentation fault" error...

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    item = strtok(NULL, "\t");
    strcpy(contas[i].nomeUtilizador, item);
    item = strtok(NULL, "\t");
    strcpy(contas[i].nomeUtilizador, item);
    printf("Finalizado o segundo tokenizer.\n");
    Why are you doing this twice?

    You've apparently got 4 fields, and 5 strtok() calls.

    You should ALWAYS check the return result of strtok() to make sure it isn't NULL before you use it.
    If it's NULL, and you try say strcpy, then you lose.

    > char PIN[4];
    Over here, PIN codes are 4 digits.
    So this would be a buffer overflow if you try to copy a string, say "1234" into this field.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2012
    Posts
    5
    Quote Originally Posted by Salem View Post
    item = strtok(NULL, "\t");
    strcpy(contas[i].nomeUtilizador, item);
    item = strtok(NULL, "\t");
    strcpy(contas[i].nomeUtilizador, item);
    printf("Finalizado o segundo tokenizer.\n");
    Why are you doing this twice?

    You've apparently got 4 fields, and 5 strtok() calls.
    I can explain that: in that part of the line of the file where the data is, the names can be composed by 2 names (like "John Mechanic", for instance). That's why I'm there trying to detect the blank space between the names and copying them to the same field in the structure.

    Quote Originally Posted by Salem View Post
    You should ALWAYS check the return result of strtok() to make sure it isn't NULL before you use it.
    If it's NULL, and you try say strcpy, then you lose.
    Thanks, I'll do that to avoid problems and if they exist, to detect them.

    Quote Originally Posted by Salem View Post
    > char PIN[4];
    Over here, PIN codes are 4 digits.
    So this would be a buffer overflow if you try to copy a string, say "1234" into this field.
    I believe the problem of the segmentation fault is actually here then. But then, if it is 4 digits - like it is here - I should declare it like char PIN[3] (so the array has 4 positions instead of 5), right ?

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > I can explain that: in that part of the line of the file where the data is, the names can be
    > composed by 2 names (like "John Mechanic", for instance)
    But if the fields are tab separated, it's still going to be a single token.

    And your logic for the number of chars in a PIN is completely wrong.
    You need at least [5] to store "1234" and a nul.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    May 2012
    Posts
    5
    Well, it's solved. The solution was exactly in the handling of the strtok's that you suggested and it was enough for me to detect where I did my mistake: because of the fact of having 4 fields and 5 strtoks. So, I deleted one of them and it's solved.

    Thank you very much for the help, I lost 2 hours today debugging this and searching for a solution.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading data from a text file
    By txmusic in forum C Programming
    Replies: 10
    Last Post: 02-25-2012, 10:13 PM
  2. Segmentation fault when reading very large text files
    By sapogo06 in forum C Programming
    Replies: 8
    Last Post: 12-07-2009, 03:19 PM
  3. Reading data from a text file
    By Dark_Phoenix in forum C++ Programming
    Replies: 8
    Last Post: 06-30-2008, 02:30 PM
  4. Reading in data from Text file
    By fortune2k in forum C Programming
    Replies: 214
    Last Post: 04-10-2008, 11:12 AM
  5. Parsing specific data from one text file to another..
    By chops11 in forum C Programming
    Replies: 2
    Last Post: 09-13-2005, 10:50 AM