在通过struct数组搜索名称时出现段错误

时间:2015-03-02 19:59:38

标签: c search struct segmentation-fault

我正在编写一个应该查看文件的程序加载它,你应该在编译后使用命令./main(searchingname)在列表中搜索一个名字。编译时我没有错误。但是当我尝试搜索名称时,我立即得到一个段错误,程序终止。这是我的代码。

#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);
    }
}

该文件看起来像这样

foo 7894898,
bar 7895497
.
.
.

1 个答案:

答案 0 :(得分:1)

原因是你没有为阵列分配空间,但是你还有很多其他小问题会让你的程序产生奇怪的行为。

  1. 在每次调用fopen()后,您都不会检查文件是否已打开,您需要确保返回的值不是NULL

    FILE *stream = fopen(filename, "r");
    if (stream == NULL)
    /* do not try to read from stream */
    
  2. while(!feof(file))总是错误的,无论如何都要将错误的值传递给feof(),以计算文件中有效行的数量,这应该这样做

    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. FILE *(*data);
    Blackbox = LOAD(*data, lines);
    

    也会导致问题,因为您正在取消引用data但未分配。

  4. 你没有为结构数组分配空间,并且你分配了错误的ammount来复制字符串,在c中你总是需要比strlen()返回的值多一个字符,因为你需要空间来存储'\0'终结符。

    以下函数修复了这两个问题,并且还以正确的方式使用fopen()函数,请注意您不需要将FILE *对象传递给函数,除非它之前已经打开过调用此函数,您还应该调用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;
    }
    
  5. 程序的其余部分几乎没问题,您应该注意使其适用于这些修复所需的更改。