简体   繁体   English

为什么在尝试从文件中读取时 fscanf() 段错误?

[英]Why is fscanf() seg faulting while trying to read from a file?

I am using C in Visual Studio via a remote Linux server.我通过远程 Linux 服务器在 Visual Studio 中使用 C。 I want to read a file and store the contents in a array of structs.我想读取一个文件并将内容存储在一个结构数组中。 Every time I try to read a line using fscanf() it seg faults.每次我尝试使用fscanf()读取一行时,它都会出现错误。 Thanks in advance.提前致谢。

Format of the file I'm trying to read:我要读取的文件格式:

F150    5.4 28000 white
RAM1500 5.7 32000 orange
car     4.5 12000 green
truck   6.1 55000 black

Here's a simplified version my program as the other parts function fine:这是我的程序的简化版本,其他部分 function 很好:

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

struct data {
    char name[20];
    float floatNum;
    int intNum;
    char color[20];
} temp;

int scan(void) {
    int size = 0;
    FILE *data;
    data = fopen("./hw3.data", "r");
    while (1) {
        fscanf(data, "%s %f %d %s", temp.name, &temp.floatNum,
               &temp.intNum, temp.color);
        if (feof(data))
            break;
        size++;
    }
    return size;
}

void load(int size, struct data autos[]) {
    int i;
    FILE *data;
    data = fopen("./hw3.data", "r");
    for (i = 0; i < size; i++) {
        fscanf(data, "%s %f %d %s", autos[i].name, &autos[i].floatNum,
               &autos[i].intNum, autos[i].color);
    }
}

int main() {
    int size;
    struct data *autos;
    size = scan();
    autos = malloc(size * sizeof(struct data));
    load(size, autos);
    return 0;
}

There are multiple possible causes for problems:问题有多种可能的原因:

  • you do not test if fopen() succeeds: if the file cannot be opened, the FILE pointer data will be null, causing undefined behavior in fscanf() , possibly a seg fault.您不测试fopen()是否成功:如果文件无法打开,则FILE指针data将为 null,导致fscanf()出现未定义的行为,可能是段错误。

  • you do not test if malloc succeeds... again causing a seg fault if memory cannot be allocated.您不测试malloc是否成功...如果无法分配 memory 再次导致段错误。

  • you should close the FILE after reading你应该在阅读后关闭FILE

  • your test for feof() is incorrect: it might be true after successfully reading the last item, causing it to be ignored and you might never reach the end of file if one of the items cannot be read.您对feof()的测试不正确:成功读取最后一项后可能为真,导致它被忽略,如果其中一项无法读取,您可能永远不会到达文件末尾。 You should just test the return value of fscanf() : it returns the number of successful conversions, so 4 in your case.您应该只测试fscanf()的返回值:它返回成功转换的次数,因此在您的情况下为4

  • you should use %19s to avoid writing beyond the end of the targets arrays, another potential source of undefined behavior.您应该使用%19s来避免写入超出目标 arrays 的末尾,这是未定义行为的另一个潜在来源。

Here is a modified version:这是修改后的版本:

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

struct data {
    char name[20];
    float floatNum;
    int intNum;
    char color[20];
};

int scan(const char *filename) {
    struct data temp;
    int size = 0;
    FILE *data = fopen(filename, "r");
    if (data == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
        return -1;
    }
    while (fscanf(data, "%19s %f %d %19s",
                  temp.name, &temp.floatNum,
                  &temp.intNum, temp.color) == 4) {
        size++;
    }
    fclose(data);
    return size;
}

int load(const char *filename, int size, struct data autos[]) {
    int i;
    FILE *data = fopen(filename, "r");
    if (data == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
        return -1;
    }
    for (i = 0; i < size; i++) {
        if (fscanf(data, "%19s %f %d %19s",
                   autos[i].name, &autos[i].floatNum,
                   &autos[i].intNum, autos[i].color) != 4)
            break;
    }
    fclose(data);
    return i;
}

int main() {
    char filename[] = "./hw3.data";
    int size = scan(filename);
    if (size < 0)
        return 1;
    if (size > 0) {
        struct data *autos = malloc(size * sizeof(struct data));
        if (autos == NULL) {
            fprintf(stderr, "cannot allocate %zu bytes\n", size * sizeof(struct data));
            return 1;
        }
        int n = load(filename, size, autos);
        for (int i = 0; i < n; i++) {
            printf("%s %g %d %s\n", autos[i].name, autos[i].floatNum,
                   autos[i].intNum, autos[i].color);
        }
        free(autos);
    }
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM