2014-03-06 136 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

相关问题