Skepller
Skepller

Reputation: 144

Segmentation fault (core dumped) when reading file

I'm doing a simple project to read a input.txt text file and show some basic statistics about it. The file is supposed to be about the entrance on a company building. That's how the file is:

1 ; Visitor ; 10 ; 19 ; 2
2 ; 1 ; Worker ; 8 ; 0
3 ; 2 ; Director ; 12 ; 19
4 ; 5 ; Worker ; 18 ; 22
5 ; Visitor ; 8 ; 0 ; 3

Format is = ID ; Companions(if employee) ; Type ; Entrance Time ; Exit Time ; Services(if Visitor)

I got the program to read the file correctly (i guess), it reads the first worker correctly, but when it gets to the second one it reads the ID and suddenly exits with Segmentation fault (core dumped).

example of error

I'd really appreciate if someone with more knowledge could help since i have no idea what's happening, and other questions with the same error didn't help.

Here's the code:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef enum { false, true } bool;

char * removeSpaces(char *line) {
    int counter = 0,i=0;

    while (line[i]!='\0'){
        if (line[i] == ' '){
            i++;
        } else{
            line[counter] = line[i];
            counter++;
            i++;
        }
    }
    return(line);
    line[counter] = '\0';
}

int main (int argc, char *argv[]){
    FILE * fp;
    char * line = NULL;
    char field[30];
    size_t len = 0;
    ssize_t read;
    bool flag = false;
    int i=0,j=0,k=0,counter=0; //variables to count on loops

    fp = fopen("input.txt", "r");
    if (fp == NULL)
        exit(EXIT_FAILURE);

    while ((read = getline(&line, &len, fp)) != -1) {
        printf("%s", line);
        if(strstr(line, "Worker") != NULL) { //determine the entrance type
            line = removeSpaces(line);

            printf("\nWORKER READ\n");
            i = 0;
            while(line[i] != ';'){ //Read ID
                field[i] = line[i]; //saves the content of the field (all between ';')
                i++;
            }
            field[i] = '\0';
            printf("\nID: ");
            for(i=0;field[i] != '\0';i++){
                printf("%c",field[i]);
            }
            //memset(field,0,strlen(field));
            i = 0; j = 0;
            while(flag != true){ //Read Companions
                if(line[i] == ';'){
                    flag = true; //keeps skipping the string till it finds the right field
                }
                if(flag == true){
                    j = i+1;
                    while(line[j] != ';'){
                        field[k] = line[j]; //saves the content of the field (all between ';')
                        j++; k++;
                    }
                }
                i++;
            }
            field[k] = '\0';
            printf("\nCOMPANIONS: ");
            for(i=0;field[i] != '\0';i++){
                printf("%c",field[i]); //prints what the number of companions read
            }
            //memset(field,0,strlen(field));
            i = 0; j = 0; k = 0; flag = false;
            while(flag != true){ //Read Type
                if(line[i] == ';'){
                    counter++;
                    if(counter == 2){
                        flag = true; //keeps skipping the string till it finds the right field
                    }
                }
                if(flag == true){
                    j = i+1;
                    while(line[j] != ';'){
                        field[k] = line[j]; //saves the content of the field (all between ';')
                        j++; k++;
                    }
                }
                i++;
            }
            field[k] = '\0';
            printf("\nTIPO: ");
            for(i=0;field[i] != '\0';i++){
                printf("%c",field[i]); /prints the type of entrance read
            }
            //memset(field,0,strlen(field));
            i = 0; j = 0; k = 0;  flag = false; counter = 0;
            while(flag != true){ //Read Entrance Time
                if(line[i] == ';'){
                    counter++;
                    if(counter == 3){
                        flag = true; //keeps skipping the string till it finds the right field
                    }
                }
                if(flag == true){
                    j = i+1;
                    while(line[j] != ';'){
                        field[k] = line[j]; //saves it
                        j++; k++;
                    }
                }
                i++;
            }
            field[k] = '\0';
            printf("\nENTRANCE: ");
            for(i=0;field[i] != '\0';i++){
                printf("%c",field[i]);
            }
            i = 0; j = 0; k = 0;  flag = false; counter = 0;
            while(flag != true){ //Read Exit Time
                if(line[i] == ';'){
                    counter++;
                    if(counter == 4){
                        flag = true;
                    }
                }
                if(flag == true){
                    j = i+1;
                    while(line[j] != ';'){
                        field[k] = line[j];
                        j++; k++;
                    }
                }
                i++;
            }
            field[k] = '\0';
            printf("\nSAIDA: ");
            for(i=0;field[i] != '\0';i++){
                printf("%c",field[i]);
            }
            printf("\n\n");

            i = 0; j = 0; k = 0;  flag = false;
            memset(field,0,strlen(field));
        } else if(strstr(line, "Director") != NULL){
            //TODO
        } else if(strstr(line, "Visitor") != NULL){
            //TODO
        }
    }

    return 0;
}

Upvotes: 1

Views: 943

Answers (2)

jwdonahue
jwdonahue

Reputation: 6669

While I recommend sscanf or fscanf over writing complicated parsing code, it's also good for your coding skills to learn how to write parsers. After adjusting your code to use fgets instead of getline so that I could get it to compile, I hit a fault in this loop:

while ( flag != true )
{ //Read Type
    if ( line[i] == ';' ) // <<<< Fault when i = 2488
    {
        counter++;
        if ( counter == 2 )
        {
            flag = true; //keeps skipping the string till it finds the right field
        }
    }
    if ( flag == true )
    {
        j = i + 1;
        while ( line[j] != ';' )
        {
            field[k] = line[j]; //saves the content of the field (all between ';')
            j++; k++;
        }
    }
    i++;
}

You're incrementing i without reference to the length of the actual line, so at some point you are accessing a memory address that you do not own.

You should enable all warnings when you compile your code. Your compiler should be warning you of some of your mistakes. One of the important ones you should be seeing is "Unreachable code..." at line 27 in your removeSpaces function:

return(line);
line[counter] = '\0'; // This never executed.

See http://pubs.opengroup.org/onlinepubs/009696699/functions/fgets.html

Upvotes: 1

user3121023
user3121023

Reputation: 8308

sscanf could be used to parse the values from line.

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

int main (int argc, char *argv[]){
    FILE * fp;
    char * line = NULL;
    char id[30];
    char companions[30];
    char type[30];
    char entrance[30];
    char depart[30];
    size_t len = 0;
    ssize_t read;

    fp = fopen("input.txt", "r");
    if (fp == NULL)
        exit(EXIT_FAILURE);

    while ((read = getline(&line, &len, fp)) != -1) {
        printf("%s", line);
        if(strstr(line, "Worker") != NULL) { //determine the entrance type
            printf("\nWORKER READ\n");
            if ( 5 == sscanf ( line, "%29s ; %29s ; %29s ; %29s ; %29s"
            , id, companions, type, entrance, depart)) {
                printf("\nID: %s", id);
                printf("\nCOMPANIONS: %s", companions);
                printf("\nTIPO: %s", type);
                printf("\nENTRANCE: %s", entrance);
                printf("\nSAIDA: %s", depart);
                printf("\n\n");
            }
            else {
                printf ( "problem parsing Worker\n");
            }

        } else if(strstr(line, "Director") != NULL){
            //TODO
        } else if(strstr(line, "Visitor") != NULL){
            //TODO
        }
    }

    return 0;
}

Upvotes: 0

Related Questions