2014-10-09 61 views
-1

我试图读取文件内容并将它们存储到结构中,出于某种原因,我一直在收到段错误。请帮助我,我也不太了解valgrind。C编程中的结构

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

更新后的代码仍然给出了段错误。

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

输入文件

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. 
+0

使用gdb来在你的代码段错误得到抵消。根据情况,segfault可能在任何地方出现。所以这样很难帮助你。 – 2014-10-09 04:06:54

回答

5

有可能(并且将)在你的程序导致段故障

  • 首先,你在你的程序有一个检查至少有三个理由验证文件是否已成功打开。然而,你正在试图从文件之前检查

    fscanf(fp,"%d", &numberEntries); 
    

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

  • 其次,您的entryArray始终只分配一个元素。然而你试图访问4个元素。这可能(也会)很容易导致分段错误。

    顺便说一句,如果从文件中读取numberEntries然后完全忽略该值,那么该怎么办?

  • 第三,fscanf%d格式需要指针int作为对应的可变参数的参数。您所提供的int!而非

    fscanf(fp,"%d/%d/%d", entryArray[i].day, entryArray[i].month, entryArray[i].year); 
    

    这也将导致不确定的行为通常伴随着一个分段故障。通过你的第一个fscanf判断,你知道如何使用%dfscanf。你忘了第二个fscanf吗?

如果文件已成功打开,那么有99%的可能性是导致代码中出现段错误的第三个问题。这个问题在第二个问题之前就会显现


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

你必须在阅读日期和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); 
} 

或者之前进行“假” fgets,你可以添加一个尾随空格字符到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); 
} 

或者您可以使用更复杂的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); 
} 

这些并不是最好的方法,但只要您的输入文件坚持硬格式,它们就会工作。

+0

嘿,我已经根据你的观点更新了代码,但由于某种原因,它显示循环entryArray的低位在终端中未声明,你知道为什么会发生这种情况吗?谢谢。 – IamTrent 2014-10-09 04:19:57

+0

@IamTrent:在块{{}}中声明的变量只存在于该块的末尾。它不在该块之外。你不能在'else {...}'块之外访问你的'entryArray'。这是应该的。既然你把几乎所有东西都放到了'else'分支中,那么就把其余的代码放在那里。 – AnT 2014-10-09 04:20:57

+0

好吧,我更新了代码,仍然得到segfaults,任何其他想法?谢谢。 – IamTrent 2014-10-09 04:26:36

2

您分配了一个杂志entryArray = (journal*)malloc(sizeof(journal));,但你把它当作一个阵列fgets(entryArray[i].text, 400, fp);

那是不是要去工作...