2014-03-06 174 views
0

我試圖從一個文件中將數據輸入到一個結構中,但是每當我嘗試在「文件名」變量中輸入路徑時,它都會給出終端中的段錯誤:當我嘗試打開文件時發生C段錯誤

 
Goods Re-Order File program 
Enter database file 
/stock.txt 
Segmentation fault 

這是我的代碼。此外,我目前正在運行osx 10.5.8,如果這是相關的。

#include <stdio.h> 
#include <ctype.h> 
#include <string.h> 

struct goods 
{ 
    char name[20]; 
    float price; 
    int quantity; 
    int reorder; 
}; 
FILE *input_file; 
void processfile(void); 
void getrecord(struct goods *recptr); 
void printrecord(struct goods record); 
int main(void) 
{ 
    char filename[40]; 
    printf("Goods Re-Order File program\n"); 
    printf("Enter database file\n"); 
    scanf("%s",filename); 
    //strcpy(filename,"/stock.txt"); 
    //gets(filename); 

    input_file=fopen(filename,"r"); 
    if(!input_file) 
    { 
     printf("Could not open file!\n"); 
    } 
    processfile(); 
    fclose(input_file); 
    return 0; 
} 
void processfile(void) 
{ 
    struct goods record; 
    while(!feof(input_file)) 
    { 
     getrecord(&record); 
     if(record.quantity<=record.reorder) 
     { 
      printrecord(record); 
     } 
    } 
} 

void getrecord(struct goods *recptr) 
{ 
    int loop=0,number,toolow; 
    char buffer[40],ch; 
    float cost; 
    ch=fgetc(input_file); 
    while (ch!='\n') 
    { 
     buffer[loop++]=ch; 
     ch=fgetc(input_file); 
    } 
    buffer[loop]=0; 
    strcpy(recptr->name,buffer); 
    fscanf(input_file,"%f",&cost); 
    recptr->price=cost; 
    fscanf(input_file,"%d",&number); 
    recptr->quantity=number; 
    fscanf(input_file,"%d",&toolow); 
    recptr->reorder=toolow; 
} 
void printrecord(struct goods record) 
{ 
    printf("\nProduct name\t%s\n",record.name); 
    printf("Product price \t%f\n",record.price); 
    printf("Product quantity \t%d\n",record.quantity); 
    printf("Product reorder level \t%d\n",record.reorder); 
} 
+1

您是否正在輸入超過39個字符?另外,如果'if(!input_file)'測試失敗,你實際上不會退出程序,否則你繼續調用'processfile()',如果'input_file'爲NULL,可能會出現段錯誤。 –

+0

在商品中,名稱爲20個字符,getrecord保留40個字符,但您的循環從不檢查這些界限。 –

+1

'while(!feof(input_file))'如果你在while循環中讀取文件的最後一個元素,你會怎麼想?你將不會讀取文件的結尾,然後當另一個不存在的時候,你會嘗試讀另一個'if(record.quantity <= record.reorder)' – AndyG

回答

2

後,您將無法打開你做檢查的文件,但需要返回

if(!input_file) 
{ 
    printf("Could not open file!\n"); 
    return -1; 
} 

編輯

getrecord循環應該是

while (ch!='\n' && ch != EOF && loop < 39) 
{ 
    buffer[loop++]=ch; 
    ch=fgetc(input_file); 
} 

所以你不要超出緩衝區。

而且結構應(如緩衝可能是40個字符)

struct goods 
{ 
    char name[40]; 

順便說一句 - 不保存賺錢的好主意,因爲漂浮

+0

剛開始時,由於某種原因,給了我一個編譯錯誤,現在它不。猜猜我沒注意:)謝謝。儘管如此,仍然給我一個分割錯誤。 –

+0

起初我編譯的代碼[未做名[40],它實際上吐出來的東西那麼它給了我一個分段錯誤: 輸入數據庫文件 /stock.txt 3roduct名\t Greaters冰淇淋 產品價格\t 2.562500 產品數量\t -1609231168 產品訂貨點水平\t -1609229604 分段故障 現在我所做的名稱數組是40號,當我嘗試打開「/stock.txt」它什麼都不做。 –

+0

@ The_0bserver - 最好的辦法是使用調試器 –

3

你的問題是在這裏:

while(!feof(input_file)) 

您應該只在while循環結束時讀取。試試這個:

struct goods record; 
getrecord(&record); 
while(!feof(input_file)) 
{ 

    if(record.quantity<=record.reorder) 
    { 
     printrecord(record); 
    } 
    getrecord(&record); 
} 

您還需要修改getrecord如果EOF發現退出。

像這樣(未經):

void getrecord(struct goods *recptr) 
{ 
    int loop=0,number,toolow; 
    char buffer[BUFFER_SIZE]; 
    int ch; 
    float cost; 
    ch=fgetc(input_file); 
    if (ch == EOF) //if last element already read, will be EOF 
     return; 
    while (ch!='\n' && ch != EOF && loop < BUFFER_SIZE) //BUFFER_SIZE 
    { 
     buffer[loop++]=(char)ch; 
     ch=fgetc(input_file); 
    } 
    if (ch == EOF) //check for unexpected EOF 
     return; 
    //... 

你也可以改變getrecord返回true或基於EOF是否被讀取false

+1

您還應該檢查緩衝區溢出循環。 –

+0

通過將結構的名稱變量設置爲大小40來做到這一點。 –

+0

@JohnnyMopp:添加了檢查。如果緩衝區已滿,該函數將退出,但不能保證換行符是最後一個讀取的字符,因此OP可能會或可能不想對此進行說明。 – AndyG

相關問題