Reputation: 11
I am writing a basic program that must read and write information from a text file into a structure. The function that dumps all struct information into a text file works, but trying to scan the same information back in from the file into an empty structure keeps resulting in an Access Violation Error.
#include <stdio.h>
#include <stdlib.h>
#define MAXENTRIES 100
struct entry{
unsigned int recordNum;
char *toolName;
unsigned int quantity;
double cost;
};
struct entry dataBase[MAXENTRIES];
int currentEntries = 0;
void initDataBase(void){
dataBase[0].recordNum = 3;
dataBase[0].toolName = "Electric Sander";
dataBase[0].quantity = 7;
dataBase[0].cost = 57.98;
// scanf("%d", &dataBase[0].recordNum);
dataBase[1].recordNum = 17;
dataBase[1].toolName = "Hammer";
dataBase[1].quantity = 76;
dataBase[1].cost = 11.99;
dataBase[2].recordNum = 24;
dataBase[2].toolName = "Jig Saw";
dataBase[2].quantity = 21;
dataBase[2].cost = 11.00;
dataBase[3].recordNum = 39;
dataBase[3].toolName = "Lawn Mower";
dataBase[3].quantity = 3;
dataBase[3].cost = 79.50;
dataBase[4].recordNum = 56;
dataBase[4].toolName = "Power Saw";
dataBase[4].quantity = 18;
dataBase[4].cost = 99.99;
dataBase[5].recordNum = 68;
dataBase[5].toolName = "Screwdriver";
dataBase[5].quantity = 106;
dataBase[5].cost = 6.99;
dataBase[6].recordNum = 77;
dataBase[6].toolName = "Sledge Hammer";
dataBase[6].quantity = 11;
dataBase[6].cost = 21.50;
dataBase[7].recordNum = 83;
dataBase[7].toolName = "Wrench";
dataBase[7].quantity = 34;
dataBase[7].cost = 7.50;
currentEntries = 8;
}
void printEntry(int i){
printf("\nRecordNum : %d", dataBase[i].recordNum);
printf("\nTool Name : %s", dataBase[i].toolName);
printf("\nQuantity : %d", dataBase[i].quantity);
printf("\nCost : %.2f\n\n", dataBase[i].cost);
}
void fprintDataBase(void){
FILE *dbPtr;
if((dbPtr = fopen("hardware.dat", "w")) == NULL){
puts("File could not be opened");
}
else{
for(int i = 0; i < currentEntries; i++){
fprintf(dbPtr, "%d %s %d %.2f\n", dataBase[i].recordNum, dataBase[i].toolName, dataBase[i].quantity, dataBase[i].cost);
}
printf("\nDatabase recorded!\n");
fclose(dbPtr);
}
}
void fscanDataBase(void){
FILE *dbPtr;
if((dbPtr = fopen("hardware.dat", "r")) == NULL){
puts("File could not be opened");
}
else{
currentEntries = 1;
// fscanf(dbPtr, "%d%29s%d%lf", &dataBase[0].recordNum, dataBase[0].toolName, &dataBase[0].quantity, &dataBase[0].cost);
fscanf(dbPtr, "%d", &dataBase[0].recordNum); //Access Violation Error HERE
while(!feof(dbPtr)){
fscanf(dbPtr, "%d%29s%d%lf", &dataBase[currentEntries].recordNum, dataBase[currentEntries].toolName, &dataBase[currentEntries].quantity, &dataBase[currentEntries].cost);
currentEntries++;
}
printf("\nDatabase scanned in!\n");
fclose(dbPtr);
}
}
int main()
{
// initDataBase();
// fprintDataBase();
fscanDataBase();
printEntry(0);
return 0;
}
Running this program gets this output:
Process returned -1073741819 (0xC0000005) execution time : 0.344 s
Press any key to continue.
Running initDataBase()
and then fprintDataBase()
correctly results in a file with everything I need, but commenting out those calls and calling fscanDataBase()
results in the aforementioned error.
Since this is an Access Violation error, my first thought is that this is an array issue, but I was able to access dataBase[0]
during initDataBase()
with no trouble. This also means that it can't be an issue of the struct falling out of scope (which it shouldn't anyway, being a global).
As shown in one of the commented lines, I was able to perform a scanf
into dataBase[0]
during initDataBase()
, so this shouldn't be an issue with my syntax.
All of this leads me to think this is a problem with how I'm using fscanf
, which is beyond my current level of understanding.
Upvotes: 1
Views: 37
Reputation: 14924
Your major issue is that there is no memory allocated for each entry.toolName
. Without changing the structure, the smallest change I could make is to scan into a temporary buffer, then duplicate the string. Of course this has memory-cleanup issues that need to be handled.
void fscanDataBase(void)
{
FILE *dbPtr;
if ((dbPtr = fopen("hardware.dat", "r")) == NULL)
{
puts("File could not be opened");
}
else
{
currentEntries = 0;
while(!feof(dbPtr))
{
char tempName[32];
fscanf(dbPtr, "%d %29s %d %lf", &dataBase[currentEntries].recordNum,
tempName,
&dataBase[currentEntries].quantity,
&dataBase[currentEntries].cost);
dataBase[currentEntries].toolName = strdup(tempName);
currentEntries++;
}
printf("\nDatabase scanned in!\n");
fclose(dbPtr);
}
}
But probably, you meant to allocate space in your struct entry
:
struct entry
{
unsigned int recordNum;
char toolName[32]; // <<-- HERE
unsigned int quantity;
double cost;
};
Be careful about overwriting the length of the string buffer here. You'll lose marks if you don't handle all sorts of issues (like the return value from fscanf()
).
You probably want to test your code with some rubbish input too. Your teacher/lecturer will.
Upvotes: 0