0

I am writing a program that is supposed to look through a file load it up and you are supposed to search for a name in the list using the command ./main (searchedname) after compilation. While compiling I get no errors. But when I try to search for a name I get a segfault immediately and the program terminates. Here is my code.

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

struct _data {
    char *name;
    long number;
};

int SCAN(FILE *(*stream)) {
    int lines = 0;
    *stream = fopen("hw5.data", "r");
    char c_temp[100];
    long l_temp;
    while(!feof(*stream)) {
        fscanf(*stream, "%s %ld", c_temp, &l_temp);
        lines++;
    }
    return lines;
}

struct _data *LOAD(FILE *stream, int size) {

    struct _data *temp;
    stream = fopen("hw5.data", "r");
    char c_temp[100];
    long l_temp;
    int i;

    rewind(stream);

    for(i = 0; i < size; i++) {
        fscanf(stream, "%s %ld", c_temp, &l_temp);
        temp[i].name = calloc(strlen(c_temp), sizeof(char));
        strcpy(temp[i].name, c_temp);
    }

    return temp;

}

void SEARCH(struct _data *Blackbox, char *name, int size) {
    int found = 0, i, entry;
    for(i = 0; i < size; i++) {
        if((strcmp(Blackbox[i].name, name)) == 0) {
            found = 1;
            entry = i;
        }
    }

    if(found == 1) {
        printf("The name you are looking for has been found at entry: %d\n", entry);
    } else {
        printf("Entry not found.\n");
    }
}

void FREE(struct _data *Blackbox, int size) {
    int i;
    for(i = 0; i < size; i++) {
        free(Blackbox[i].name);
    }
}

int main(int argv, char **argc) {

    struct _data *Blackbox;
    if(argv == 1)  {
        printf("*******************************************\n");
        printf("*You must include a name to search for.   *\n");
        printf("*******************************************\n");
    } else {
        FILE *(*data);
        int lines = SCAN(data);
        printf("%d", lines);
        Blackbox = LOAD(*data, lines);
        SEARCH(Blackbox, argc, lines);
    }
}

The file looks like this

foo 7894898,
bar 7895497
.
.
.
Kara
  • 6,115
  • 16
  • 50
  • 57
user1881401
  • 85
  • 3
  • 15
  • Why are you using uppercase for function names? that's not very common. – Iharob Al Asimi Mar 02 '15 at 20:03
  • In the assignment requirements that is how my professor named the functions so I did the same – user1881401 Mar 02 '15 at 20:04
  • 1
    Beyond failing to allocate space for our array, even after that is fixed it would be in your best interest to check that `fscanf(*stream, "%s %ld", c_temp, &l_temp)` actually *worked* rather than marching on like it always succeeds. And this is wrong: [while(!feof(*stream))](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong) – WhozCraig Mar 02 '15 at 20:05
  • @user1881401 `In the assignment requirements that is how my professor named the functions` Probably a Fortran or COBOL programmer... – PaulMcKenzie Mar 02 '15 at 20:07
  • The notation `int SCAN(FILE *(*stream))` is unusual. Quite apart from the capitalization of the function name (contrary to normal practice in C, though not formally wrong), the parentheses in the argument list are redundant — `int SCAN(FILE **stream)` is sufficient. – Jonathan Leffler Mar 02 '15 at 20:31

1 Answers1

1

The reason is that you are not allocating space for your array, but you have many other minor issues that would make your program have weird behavior.

  1. You don't check that the file opened, after every call to fopen() you need to make sure that the returned value is not NULL.

    FILE *stream = fopen(filename, "r");
    if (stream == NULL)
    /* do not try to read from stream */
    
  2. while(!feof(file)) is always wrong and you pass the wrong value to feof() anyway, to count the number of valid lines in the file, this should do it

    int countLines(const char *const filename)
    {
        int      lines;
        FILE    *stream;
        long int ignore;
    
        stream = fopen(filename, "r");
        if (stream == NULL)
            return 0;
        lines = 0;
        while(fscanf(*stream, "%*s%ld", &ignore) == 1)
            lines++;
        fclose(stream);
        return lines;
    }
    
  3. This

    FILE *(*data);
    Blackbox = LOAD(*data, lines);
    

    would also cause problems, because you are dereferencing data but it's not allocated.

  4. You didn't allocate space for the array of structs, and you allocated the wrong ammount to copy the string, in c you always need one character more than the value returned by strlen() , because you need space to store the '\0' terminator.

    The following function fixes boths issues, and also uses the fopen() function in the correct way, note that you don't need to pass the FILE * object to the function unless it was already opened before calling this function, and you should also call fclose()

    struct _data *load(const char *const filename, int size)
    {
        struct _data *temp;
        FILE         *stream;
        char          c_temp[100];
        long int      l_temp;
        int           i;
    
        stream = fopen(filename, "r")
        if (stream == NULL)
            return NULL;
        temp = malloc(size * sizeof(*temp));
        if (temp == NULL)
        {
            fclose(stream);
            return NULL;
        }
        i = 0;
        while ((fscanf(stream, "%99s%ld", c_temp, &l_temp) == 2) && (i < size))
        {
            size_t length;
    
            length       = strlen(c_temp);
            temp[i].name = malloc(1 + length);
            if (temp[i].name != NULL)
                memcpy(temp[i].name, 1 + length);
            temp[i].number = l_temp;
    
            i++;
        }
        fclose(stream);
        return temp;
    }
    

The rest of the program is almost ok, you should note what changes it will require to make it work with these fixes.

Community
  • 1
  • 1
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97