C编程中的结构

Iam*_*ent -1 c struct

我正在尝试读取文件内容并将其存储到结构中,因为某些原因我不断收到分段错误.请帮助我,我也不了解valgrind.

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

typedef struct {
    int day;
    int month;
    int year;
    char text[401];
} journal;

int main(int argc, char** argv){
    int  i, numberEntries;
    FILE* fp = fopen(argv[1], "r");

    fscanf(fp,"%d", &numberEntries); /* reads value on first line of file for number of entries */
    printf("%d", numberEntries); /* check that it worked */
    journal *entryArray ;
    entryArray = (journal*)malloc(sizeof(journal));

    if(fp == NULL){
        perror("Error opening file");
    } else {

        for(i=0; i<4; i++){
            fscanf(fp,"%d/%d/%d", entryArray[i].day, entryArray[i].month, entryArray[i].year);
            fgets(entryArray[i].text, 400, fp);
            printf("%s", entryArray[i].text);
        }
    } 
    for(i=0; i<4; i++){
        printf("%d %d %d", entryArray[i].day, entryArray[i].month, entryArray[i].year);
        printf("%s", entryArray[i].text);
    }
    free(entryArray);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

更新的代码:仍然给出了分段错误.

typedef struct {
    int day;
    int month;
    int year;
    char text[401];
} journal;

int main(int argc, char** argv){
    int  i, numberEntries;
    FILE* fp = fopen(argv[1], "r");

    if(fp == NULL){
        perror("Error opening file");
    } else {
        fscanf(fp,"%d", &numberEntries); /* reads value on first line of file for number of entries */
        printf("%d", numberEntries); /* check that it worked */
        journal *entryArray ;
        entryArray = (journal*)malloc(numberEntries*sizeof(journal));
        for(i=0; i<4; i++){
            fscanf(fp,"%d/%d/%d", &entryArray[i].day, &entryArray[i].month, &entryArray[i].year);
            fgets(entryArray[i].text, 400, fp);
            printf("%s", entryArray[i].text);
        }
        for(i=0; i<4; i++){
            printf("%d/%d/%d", entryArray[i].day, entryArray[i].month, entryArray[i].year);
            printf("%s", entryArray[i].text);
        }
        free(entryArray);
    } 
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输入文件

4
12/04/2010
Interview went well I think, though was told to wear shoes.
18/04/2010
Doc advised me to concentrate on something... I forget.
03/05/2010
Was asked today if I was an art exhibit.
19/05/2010
Apparently mudcakes not made of mud, or angry wasps.
Run Code Online (Sandbox Code Playgroud)

AnT*_*AnT 5

至少有三个原因可能(并且将会)导致程序中的分段错误

  • 首先,您检查程序是否验证文件是否已成功打开.但是,您检查之前尝试从文件中读取数据

    fscanf(fp,"%d", &numberEntries);
    
    Run Code Online (Sandbox Code Playgroud)

    如果文件未成功打开,则fopen返回空指针.尝试通过空文件指针读取任何内容会导致未定义的行为,这可能很容易表现为分段错误.

  • 其次,entryArray总是只分配一个元素.然而,您正在尝试访问4个元素.这可能(并且将会)容易导致分段错误.

    顺便说一下,如果numberEntries从文件中读取然后完全忽略该值,那又有什么意义呢?

  • 第三,fscanf%d格式需要一个指针int作为对应的可变参数的参数.你已经提供了ints

    fscanf(fp,"%d/%d/%d", entryArray[i].day, entryArray[i].month, entryArray[i].year);
    
    Run Code Online (Sandbox Code Playgroud)

    这也会导致通常伴随分段错误的未定义行为.通过你的第一个判断fscanf,你知道如何使用%dfscanf.你第二次忘记了fscanf吗?

如果文件成功打开,则有99%的可能性是导致代码中出现分段错误的第三个问题.在第二个问题出现之前,这个问


最后,输入数据的格式与您硬编码到程序中的格式不匹配.由于您fgets之后立即使用fscanf,因此text数据必须与数据位于同一行day/month/year.同时,在输入文件中,text数据位于单独的行中.这肯定会破坏你的阅读代码.

在阅读日期之后和之前,您必须跳过行的其余部分和换行符fgets.一种方法是fgets在做实际之前执行"假"fgets

for(i=0; i<4; i++){
  fscanf(fp,"%d/%d/%d", &entryArray[i].day, &entryArray[i].month, &entryArray[i].year);
  fgets(entryArray[i].text, 400, fp); // <- fake `fgets`
  fgets(entryArray[i].text, 400, fp);
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以将尾随空格字符添加到fscanf格式中以强制fscanf使用所有尾随空格

for(i=0; i<4; i++){
  fscanf(fp,"%d/%d/%d ", &entryArray[i].day, &entryArray[i].month, &entryArray[i].year);
  fgets(entryArray[i].text, 400, fp);
}
Run Code Online (Sandbox Code Playgroud)

或者您可以使用更复杂的fscanf格式来要求它使用并忽略换行符之前的所有内容,然后是换行符本身

for (i = 0; i<4; i++){
  fscanf(fp, "%d/%d/%d%*[^\n]\n", &entryArray[i].day, &entryArray[i].month, &entryArray[i].year);
  fgets(entryArray[i].text, 400, fp);
}
Run Code Online (Sandbox Code Playgroud)

这些并不是最好的方法,但只要输入文件符合硬格式,它们就能正常工作.