2014-10-09 89 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);

那是不是要去工作...