Reputation: 11
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
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
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