The_0bserver
The_0bserver

Reputation: 11

C segmentation fault when I try to open file

I'm trying to input data from a file into a struct but whenever i try to input the path in the "filename" variable it gives me a segmentation fault in terminal:

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

This is my code. Also I'm currently running osx 10.5.8 if that is relevant.

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

Upvotes: 0

Views: 4148

Answers (2)

AndyG
AndyG

Reputation: 41220

Your problem is here:

while(!feof(input_file))

you should read only at the end of the while loop. Try this:

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

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

You will also need to modify getrecord to exit if EOF is found.

Something like this (untested):

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;
    //...

You could also change getrecord to return true or false based on whether EOF was read.

Upvotes: 3

Ed Heal
Ed Heal

Reputation: 60037

After you are unable to open the file you do the check but need a return

i.e.

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

EDIT

The loop in getrecord should be

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

So you do not overrun the buffer.

Also the structure should be (as buffer could be 40 characters)

struct goods
{
   char name[40];

BTW - Not a good idea to store money as floats

Upvotes: 2

Related Questions