我尝试打开文件时出现C分段错误

时间:2014-03-06 04:19:07

标签: c file-io segmentation-fault

我正在尝试将文件中的数据输入到结构中,但每当我尝试在“filename”变量中输入路径时,它会在终端中给出一个分段错误:

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

2 个答案:

答案 0 :(得分: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以返回falseEOF

答案 1 :(得分: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];
顺便说一句 - 把货币存放为花车并不是一个好主意