fscanf returns no data after program is closed and run again. (C)
21 replies, posted
Okay, I have finally gotten a program that has been troubling me for weeks to a stage where there is only one bug left. If I save a file, remove all data from RAM, and load that file back, it works perfectly, exactly as designed.
If, however, I close the program and re-run it, and try to load that previously saved file, no data is returned, despite the fact that the loading function seems to have executed normally.
Here are the relevant bits of code:
[code]
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct entry //Creates a structure for the phone book.
{
char FirstName[32];
char LastName[32];
char Number[16];
} ent;
void CreateEntry(ent*, int); //Create Entry prototype
void DeleteEntry(ent*, int); //Delete Entry prototype
void AlphaLast(ent*, int); //Alphabetize by Last Name prototype
void AlphaFirst(ent*, int); //Alphabetize by First Name prototype
void FindEntry(ent*, int);
void Clear(ent*,int);
void SaveBook(ent*,int);
void LoadBook(ent*,int);
int main()
{
int counter=0;
int displaycounter;
int savecounter;
int option;
int menu=1;
int rfriend;
char infilename[128];
ent *PhoneBook; //Creates the phone book
FILE *IOFile;
FILE *AppendFile;
char Rfilename[32];
char WFilename[32];
char testname[]="testname";
PhoneBook = (ent *) malloc(sizeof(ent)); //Dynamically allocates memory for the phone book
srand(time(NULL));
do //Menu loop
{
printf("Main Menu\n---------\n");
printf("1. Display Phone Book\n");
printf("2. Create Entry\n");
printf("3. Delete Entry\n");
printf("4. Find Entry\n");
printf("5. Alphabetize Phone Book by Last Name\n");
printf("6. Alphabetize Phone Book by Frist Name\n");
printf("7. Pick a Random Friend\n");
printf("8. Erase Phone Book\n");
printf("9. Save Phone Book\n");
printf("10. Open Phone Book\n");
printf("11. Exit\n");
scanf("%d", &option);
getchar();
switch(option)
{
...
case 9:
SaveBook(PhoneBook,counter);
break;
case 10:
LoadBook(PhoneBook,counter);
break;
}
...
void SaveBook(ent * PhoneBook, int counter)
{
FILE *IOFile;
int savecounter;
char outfilename[128];
printf("Enter a name for your phonebook.\n");
gets(outfilename);
IOFile=fopen(outfilename,"w");
if(!IOFile)
{
printf("What did you DO?");
}
for(savecounter=1;savecounter<=counter;savecounter++)
{
fprintf(IOFile,"%s %s %s\n",PhoneBook[savecounter].FirstName,PhoneBook[savecounter].LastName,PhoneBook[savecounter].Number);
}
fclose(IOFile);
printf("Phonebook saved as %s\n\n",outfilename);
}
void LoadBook(ent*PhoneBook, int counter)
{
FILE *IOFile;
char infilename[128];
Clear(PhoneBook, counter);
counter=0;
printf("Enter the name or location of the phonebook you wish to load.\n");
gets(infilename);
IOFile=fopen(infilename, "rw");
if(!IOFile)
{
printf("The file you have entered is invalid, or does not exist.");
}
while(!feof(IOFile))
{
counter++;
fscanf(IOFile,"%s %s %s",PhoneBook[counter].FirstName,PhoneBook[counter].LastName,PhoneBook[counter].Number);
}
counter--;
printf("Phonebook %s has been loaded.\n",infilename);
}
[/code]
I am not concerned with my inefficient programming practices, I'm well aware. All I need to figure out is why the program will not load a file when it is first run.
(For reference, the complete program:
[code]
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct entry //Creates a structure for the phone book.
{
char FirstName[32];
char LastName[32];
char Number[16];
} ent;
void CreateEntry(ent*, int); //Create Entry prototype
void DeleteEntry(ent*, int); //Delete Entry prototype
void AlphaLast(ent*, int); //Alphabetize by Last Name prototype
void AlphaFirst(ent*, int); //Alphabetize by First Name prototype
void FindEntry(ent*, int);
void Clear(ent*,int);
void SaveBook(ent*,int);
void LoadBook(ent*,int);
int main()
{
int counter=0;
int displaycounter;
int savecounter;
int option;
int menu=1;
int rfriend;
char infilename[128];
ent *PhoneBook; //Creates the phone book itself
FILE *IOFile;
FILE *AppendFile;
char Rfilename[32];
char WFilename[32];
char testname[]="testname";
char garbage[256];
PhoneBook = (ent *) malloc(sizeof(ent)); //Dynamically allocates memory for the phone book
srand(time(NULL));
do //Menu loop
{
printf("Main Menu\n---------\n");
printf("1. Display Phone Book\n");
printf("2. Create Entry\n");
printf("3. Delete Entry\n");
printf("4. Find Entry\n");
printf("5. Alphabetize Phone Book by Last Name\n");
printf("6. Alphabetize Phone Book by Frist Name\n");
printf("7. Pick a Random Friend\n");
printf("8. Erase Phone Book\n");
printf("9. Save Phone Book\n");
printf("10. Open Phone Book\n");
printf("11. Exit\n");
scanf("%d", &option);
getchar();
switch(option)
{
case 1:
for(displaycounter=1; displaycounter<=counter; displaycounter++) //Displays entries in phone book
{
if(strcmp(PhoneBook[displaycounter].FirstName,"Empty")!=0) //Ignores entries that are Empty
{
printf("\n%s %s\n%s\n\n\n", PhoneBook[displaycounter].FirstName, PhoneBook[displaycounter].LastName, PhoneBook[displaycounter].Number);
}
}
break;
case 2:
counter++;
PhoneBook = (ent *) realloc(PhoneBook, (counter+1) * sizeof(ent));
CreateEntry(PhoneBook, counter);
break;
case 3:
DeleteEntry(PhoneBook, counter);
break;
case 4:
FindEntry(PhoneBook, counter);
break;
case 5:
AlphaLast(PhoneBook, counter);
break;
case 6:
AlphaFirst(PhoneBook, counter);
break;
case 7:
if(counter>0)
{
printf("\nYou should call...\n\n");
rfriend=(rand()%counter)+1;
printf("%s %s\n%s\n\n",PhoneBook[rfriend].FirstName,PhoneBook[rfriend].LastName,PhoneBook[rfriend].Number);
}
else printf("\nYou have no friends! D:\n\n");
break;
case 8:
Clear(PhoneBook, counter);
break;
case 9:
SaveBook(PhoneBook,counter);
break;
case 10:
LoadBook(PhoneBook,counter);
break;
case 11:
printf("\n\nGoodbye.\n\n");
menu=0;
break;
default:
printf("Invalid Selection. Please enter a number 1-9.\n\n");
}
}while(menu==1);
system("Pause");
return 0;
}
void CreateEntry(ent * PhoneBook, int counter)
{
printf("Enter First Name: ");
scanf("%s", PhoneBook[counter].FirstName);
printf("Enter Last Name: ");
scanf("%s", PhoneBook[counter].LastName);
printf("Enter Phone Number: ");
scanf("%s", PhoneBook[counter].Number);
printf("\nEntry Complete.\n\n");
}
void DeleteEntry(ent * PhoneBook, int counter)
{
char FNSearch[32];
char LNSearch[32];
int searchcount;
printf("Enter First Name: ");
scanf("%s", FNSearch);
printf("Enter Last Name: ");
scanf("%s", LNSearch);
for(searchcount=1; searchcount<=counter; searchcount++) //Searches entries by first name
{
if((strcmp(FNSearch,PhoneBook[searchcount].FirstName)==0)&&(strcmp(LNSearch,PhoneBook[searchcount].LastName)==0))
{
strcpy(PhoneBook[searchcount].FirstName,"Empty");
strcpy(PhoneBook[searchcount].LastName,"Empty");
strcpy(PhoneBook[searchcount].Number,"Empty");
printf("Entry Deleted.\n");
}
}
}
void AlphaLast(ent*PhoneBook, int counter)
{
char FNSwitch[32];
char LNSwitch[32];
char NumSwitch[16];
int searchcount;
int alphaloop;
for(alphaloop=1;alphaloop<=counter;alphaloop++)
{
for(searchcount=1; searchcount<counter;searchcount++)
{
if(strcmp(PhoneBook[searchcount].LastName,PhoneBook[searchcount+1].LastName)==1)
{
strcpy(LNSwitch,PhoneBook[searchcount+1].LastName);
strcpy(FNSwitch,PhoneBook[searchcount+1].FirstName);
strcpy(NumSwitch,PhoneBook[searchcount+1].Number);
strcpy(PhoneBook[searchcount+1].LastName,PhoneBook[searchcount].LastName);
strcpy(PhoneBook[searchcount+1].FirstName,PhoneBook[searchcount].FirstName);
strcpy(PhoneBook[searchcount+1].Number,PhoneBook[searchcount].Number);
strcpy(PhoneBook[searchcount].LastName,LNSwitch);
strcpy(PhoneBook[searchcount].FirstName,FNSwitch);
strcpy(PhoneBook[searchcount].Number,NumSwitch);
}
}
}
}
void AlphaFirst(ent*PhoneBook, int counter)
{
char FNSwitch[32];
char LNSwitch[32];
char NumSwitch[16];
int searchcount;
int alphaloop;
for(alphaloop=1;alphaloop<=counter;alphaloop++)
{
for(searchcount=1; searchcount<counter;searchcount++)
{
if(strcmp(PhoneBook[searchcount].FirstName,PhoneBook[searchcount+1].FirstName)==1)
{
strcpy(LNSwitch,PhoneBook[searchcount+1].LastName);
strcpy(FNSwitch,PhoneBook[searchcount+1].FirstName);
strcpy(NumSwitch,PhoneBook[searchcount+1].Number);
strcpy(PhoneBook[searchcount+1].LastName,PhoneBook[searchcount].LastName);
strcpy(PhoneBook[searchcount+1].FirstName,PhoneBook[searchcount].FirstName);
strcpy(PhoneBook[searchcount+1].Number,PhoneBook[searchcount].Number);
strcpy(PhoneBook[searchcount].LastName,LNSwitch);
strcpy(PhoneBook[searchcount].FirstName,FNSwitch);
strcpy(PhoneBook[searchcount].Number,NumSwitch);
}
}
}
}
void FindEntry(ent * PhoneBook, int counter)
{
char FNSearch[32];
char LNSearch[32];
int searchcount;
printf("Enter First Name: ");
scanf("%s", FNSearch);
printf("Enter Last Name: ");
scanf("%s", LNSearch);
for(searchcount=1; searchcount<=counter; searchcount++) //Searches entries by first name
{
if((strcmp(FNSearch,PhoneBook[searchcount].FirstName)==0)&&(strcmp(LNSearch,PhoneBook[searchcount].LastName)==0))
{
printf("\n%s %s\n%s\n\n", PhoneBook[searchcount].FirstName,PhoneBook[searchcount].LastName,PhoneBook[searchcount].Number);
}
}
}
void Clear(ent*PhoneBook, int counter)
{
int count;
for(count=1;count<=counter;count++)
{
strcpy(PhoneBook[count].FirstName,"Empty");
strcpy(PhoneBook[count].LastName,"Empty");
strcpy(PhoneBook[count].Number,"Empty");
}
printf("Phonebook Cleared.\n\n");
}
void SaveBook(ent * PhoneBook, int counter)
{
FILE *IOFile;
int savecounter;
char outfilename[128];
printf("Enter a name for your phonebook.\n");
gets(outfilename);
IOFile=fopen(outfilename,"w");
if(!IOFile)
{
printf("What did you DO?");
}
for(savecounter=1;savecounter<=counter;savecounter++)
{
fprintf(IOFile,"%s %s %s\n",PhoneBook[savecounter].FirstName,PhoneBook[savecounter].LastName,PhoneBook[savecounter].Number);
}
fclose(IOFile);
printf("Phonebook saved as %s\n\n",outfilename);
}
void LoadBook(ent*PhoneBook, int counter)
{
FILE *IOFile;
char infilename[128];
Clear(PhoneBook, counter);
counter=0;
printf("Enter the name or location of the phonebook you wish to load.\n");
gets(infilename);
IOFile=fopen(infilename, "rw");
if(!IOFile)
{
printf("The file you have entered is invalid, or does not exist.");
}
while(!feof(IOFile))
{
counter++;
fscanf(IOFile,"%s %s %s",PhoneBook[counter].FirstName,PhoneBook[counter].LastName,PhoneBook[counter].Number);
}
counter--;
printf("Phonebook %s has been loaded.\n",infilename);
}
[/code]
)
[code]
IOFile=fopen(infilename, "rw");
[/code]
You don't need the w.
This is what [url="http://www.cplusplus.com/reference/clibrary/cstdio/fopen/"]cplusplus.com[/url] says about fopen():
[quote]
"w" Create an empty file for writing. If a file with the same name already exists its content is erased and the file is treated as a new empty file.
[/quote]
[QUOTE=PvtCupcakes;18159533][code]
IOFile=fopen(infilename, "rw");
[/code]
You don't need the w.
[/QUOTE]
I've tried it with just the r parameter, same result.
The problem is probably that not enough memory is allocated on PhoneBook.
Without running the program:
1) Use 'r' to open for reading, not writing too (you're zero-ing the file)
2) Your PhoneBook variable only has enough memory for *one* entry. You probably want to be allocating more memory (and resizing with realloc) while you load the phone book data into entry structures.
3) Remember that arrays begin at index 0, not 1
Hmm, I didn't notice that I'd need to add another reallocation at the load function, that does make sense.
However, even using just the r parameter for the file, and even with memory reallocation, nothing is loaded into the program if I execute the load function from the start of the program.
[code]
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct entry //Creates a structure for the phone book.
{
char FirstName[32];
char LastName[32];
char Number[16];
} ent;
void CreateEntry(ent*, int); //Create Entry prototype
void DeleteEntry(ent*, int); //Delete Entry prototype
void AlphaLast(ent*, int); //Alphabetize by Last Name prototype
void AlphaFirst(ent*, int); //Alphabetize by First Name prototype
void FindEntry(ent*, int);
void Clear(ent*,int);
void SaveBook(ent*,int);
void LoadBook(ent*,int);
int main()
{
int counter=0;
int displaycounter;
int savecounter;
int option;
int menu=1;
int rfriend;
char infilename[128];
ent *PhoneBook; //Creates the phone book itself
FILE *IOFile;
FILE *AppendFile;
char Rfilename[32];
char WFilename[32];
char testname[]="testname";
char garbage[256];
PhoneBook = (ent *) malloc(sizeof(ent)); //Dynamically allocates memory for the phone book
srand(time(NULL));
do //Menu loop
{
printf("Main Menu\n---------\n");
printf("1. Display Phone Book\n");
printf("2. Create Entry\n");
printf("3. Delete Entry\n");
printf("4. Find Entry\n");
printf("5. Alphabetize Phone Book by Last Name\n");
printf("6. Alphabetize Phone Book by Frist Name\n");
printf("7. Pick a Random Friend\n");
printf("8. Erase Phone Book\n");
printf("9. Save Phone Book\n");
printf("10. Open Phone Book\n");
printf("11. Exit\n");
scanf("%d", &option);
getchar();
switch(option)
{
case 1:
for(displaycounter=1; displaycounter<=counter; displaycounter++) //Displays entries in phone book
{
if(strcmp(PhoneBook[displaycounter].FirstName,"Empty")!=0) //Ignores entries that are Empty
{
printf("\n%s %s\n%s\n\n\n", PhoneBook[displaycounter].FirstName, PhoneBook[displaycounter].LastName, PhoneBook[displaycounter].Number);
}
}
break;
case 2:
counter++;
PhoneBook = (ent *) realloc(PhoneBook, (counter+1) * sizeof(ent));
CreateEntry(PhoneBook, counter);
break;
case 3:
DeleteEntry(PhoneBook, counter);
break;
case 4:
FindEntry(PhoneBook, counter);
break;
case 5:
AlphaLast(PhoneBook, counter);
break;
case 6:
AlphaFirst(PhoneBook, counter);
break;
case 7:
if(counter>0)
{
printf("\nYou should call...\n\n");
rfriend=(rand()%counter)+1;
printf("%s %s\n%s\n\n",PhoneBook[rfriend].FirstName,PhoneBook[rfriend].LastName,PhoneBook[rfriend].Number);
}
else printf("\nYou have no friends! D:\n\n");
break;
case 8:
Clear(PhoneBook, counter);
break;
case 9:
SaveBook(PhoneBook,counter);
break;
case 10:
LoadBook(PhoneBook,counter);
break;
case 11:
printf("\n\nGoodbye.\n\n");
menu=0;
break;
default:
printf("Invalid Selection. Please enter a number 1-9.\n\n");
}
}while(menu==1);
system("Pause");
return 0;
}
void CreateEntry(ent * PhoneBook, int counter)
{
printf("Enter First Name: ");
scanf("%s", PhoneBook[counter].FirstName);
printf("Enter Last Name: ");
scanf("%s", PhoneBook[counter].LastName);
printf("Enter Phone Number: ");
scanf("%s", PhoneBook[counter].Number);
printf("\nEntry Complete.\n\n");
}
void DeleteEntry(ent * PhoneBook, int counter)
{
char FNSearch[32];
char LNSearch[32];
int searchcount;
printf("Enter First Name: ");
scanf("%s", FNSearch);
printf("Enter Last Name: ");
scanf("%s", LNSearch);
for(searchcount=1; searchcount<=counter; searchcount++) //Searches entries by first name
{
if((strcmp(FNSearch,PhoneBook[searchcount].FirstName)==0)&&(strcmp(LNSearch,PhoneBook[searchcount].LastName)==0))
{
strcpy(PhoneBook[searchcount].FirstName,"Empty");
strcpy(PhoneBook[searchcount].LastName,"Empty");
strcpy(PhoneBook[searchcount].Number,"Empty");
printf("Entry Deleted.\n");
}
}
}
void AlphaLast(ent*PhoneBook, int counter)
{
char FNSwitch[32];
char LNSwitch[32];
char NumSwitch[16];
int searchcount;
int alphaloop;
for(alphaloop=1;alphaloop<=counter;alphaloop++)
{
for(searchcount=1; searchcount<counter;searchcount++)
{
if(strcmp(PhoneBook[searchcount].LastName,PhoneBook[searchcount+1].LastName)==1)
{
strcpy(LNSwitch,PhoneBook[searchcount+1].LastName);
strcpy(FNSwitch,PhoneBook[searchcount+1].FirstName);
strcpy(NumSwitch,PhoneBook[searchcount+1].Number);
strcpy(PhoneBook[searchcount+1].LastName,PhoneBook[searchcount].LastName);
strcpy(PhoneBook[searchcount+1].FirstName,PhoneBook[searchcount].FirstName);
strcpy(PhoneBook[searchcount+1].Number,PhoneBook[searchcount].Number);
strcpy(PhoneBook[searchcount].LastName,LNSwitch);
strcpy(PhoneBook[searchcount].FirstName,FNSwitch);
strcpy(PhoneBook[searchcount].Number,NumSwitch);
}
}
}
}
void AlphaFirst(ent*PhoneBook, int counter)
{
char FNSwitch[32];
char LNSwitch[32];
char NumSwitch[16];
int searchcount;
int alphaloop;
for(alphaloop=1;alphaloop<=counter;alphaloop++)
{
for(searchcount=1; searchcount<counter;searchcount++)
{
if(strcmp(PhoneBook[searchcount].FirstName,PhoneBook[searchcount+1].FirstName)==1)
{
strcpy(LNSwitch,PhoneBook[searchcount+1].LastName);
strcpy(FNSwitch,PhoneBook[searchcount+1].FirstName);
strcpy(NumSwitch,PhoneBook[searchcount+1].Number);
strcpy(PhoneBook[searchcount+1].LastName,PhoneBook[searchcount].LastName);
strcpy(PhoneBook[searchcount+1].FirstName,PhoneBook[searchcount].FirstName);
strcpy(PhoneBook[searchcount+1].Number,PhoneBook[searchcount].Number);
strcpy(PhoneBook[searchcount].LastName,LNSwitch);
strcpy(PhoneBook[searchcount].FirstName,FNSwitch);
strcpy(PhoneBook[searchcount].Number,NumSwitch);
}
}
}
}
void FindEntry(ent * PhoneBook, int counter)
{
char FNSearch[32];
char LNSearch[32];
int searchcount;
printf("Enter First Name: ");
scanf("%s", FNSearch);
printf("Enter Last Name: ");
scanf("%s", LNSearch);
for(searchcount=1; searchcount<=counter; searchcount++) //Searches entries by first name
{
if((strcmp(FNSearch,PhoneBook[searchcount].FirstName)==0)&&(strcmp(LNSearch,PhoneBook[searchcount].LastName)==0))
{
printf("\n%s %s\n%s\n\n", PhoneBook[searchcount].FirstName,PhoneBook[searchcount].LastName,PhoneBook[searchcount].Number);
}
}
}
void Clear(ent*PhoneBook, int counter)
{
int count;
for(count=1;count<=counter;count++)
{
strcpy(PhoneBook[count].FirstName,"Empty");
strcpy(PhoneBook[count].LastName,"Empty");
strcpy(PhoneBook[count].Number,"Empty");
}
printf("Phonebook Cleared.\n\n");
}
void SaveBook(ent * PhoneBook, int counter)
{
FILE *IOFile;
int savecounter;
char outfilename[128];
printf("Enter a name for your phonebook.\n");
gets(outfilename);
IOFile=fopen(outfilename,"w");
if(!IOFile)
{
printf("What did you DO?");
}
for(savecounter=1;savecounter<=counter;savecounter++)
{
fprintf(IOFile,"%s %s %s\n",PhoneBook[savecounter].FirstName,PhoneBook[savecounter].LastName,PhoneBook[savecounter].Number);
}
fclose(IOFile);
printf("Phonebook saved as %s\n\n",outfilename);
}
void LoadBook(ent*PhoneBook, int counter)
{
FILE *IOFile;
char infilename[128];
Clear(PhoneBook, counter);
counter=0;
printf("Enter the name or location of the phonebook you wish to load.\n");
gets(infilename);
IOFile=fopen(infilename, "r");
if(!IOFile)
{
printf("The file you have entered is invalid, or does not exist.");
}
while(!feof(IOFile))
{
counter++;
PhoneBook = (ent *) realloc(PhoneBook, (counter+1) * sizeof(ent));
fscanf(IOFile,"%s %s %s",PhoneBook[counter].FirstName,PhoneBook[counter].LastName,PhoneBook[counter].Number);
}
counter--;
printf("Phonebook %s has been loaded.\n",infilename);
}
[/code]
[quote]gets(infilename);[/quote]
Let's ask GCC what it thinks about gets().
[code]
BUGS
Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security. Use fgets() instead.
[/code]
[editline]02:38PM[/editline]
Are you even sure that you are opening the file correctly? Your load function doesn't fail gracefully, and it is likely that it even fails silently.
You see this line that you print out when fopen fails?
[code]printf("The file you have entered is invalid, or does not exist.");[/code]
You need a '\n' at the end of that line. Otherwise, it is quite likely that your terminal never prints out the line indicating the error. (This is because most terminals use canonical input processing. Character data is buffered internally and not returned by a read() syscall until a newline character is input into the buffer. This is to reduce the number of expensive syscalls to the kernel all the time)
Furthermore, the function doesn't do anything differently on an error condition. At least it shouldn't try to load the non-existent file. Assuming feof(IOFile) returns true when IOFile = NULL (it doesn't have to, this behavior is undefined!) then you are still underflowing counter.
And one more thing, you are never closing the file descriptor. [U]This is very bad[/U] and likely why you were having trouble loading data in a second time after closing the program.
[QUOTE=Cathbadh;18168190]Let's ask GCC what it thinks about gets().
[code]
BUGS
Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security. Use fgets() instead.
[/code]
[/QUOTE]
Using fgets to get the filename to be opened has its own issues. Using the following code:
[code]
void LoadBook(ent*PhoneBook, int counter)
{
FILE *IOFile;
char infilename[128];
Clear(PhoneBook, counter);
counter=0;
printf("Enter the name or location of the phonebook you wish to load.\n");
fgets(infilename,128,stdin);
printf("%s",infilename);
IOFile=fopen(infilename, "r");
if(!IOFile)
{
printf("The file you have entered is invalid, or does not exist.\n");
}
else
{
while(!feof(IOFile))
{
PhoneBook = (ent *) realloc(PhoneBook, (counter+1) * sizeof(ent));
counter++;
fscanf(IOFile,"%s %s %s",PhoneBook[counter].FirstName,PhoneBook[counter].LastName,PhoneBook[counter].Number);
}
counter--;
printf("Phonebook %s has been loaded.\n",infilename);
fclose(IOFile);
}
}
[/code]
...the string is captured correctly, and when it prints it displays exactly what I put in, but I always get "The file you have entered is invalid, or does not exist."
And using...
[code]
void SaveBook(ent * PhoneBook, int counter)
{
FILE *IOFile;
int savecounter;
char outfilename[128];
printf("Enter a name for your phonebook.\n");
fgets(outfilename,128,stdin);
IOFile=fopen(outfilename,"w");
if(!IOFile)
{
printf("What did you DO?");
}
else
{
for(savecounter=1;savecounter<=counter;savecounter++)
{
fprintf(IOFile,"%s %s %s\n",PhoneBook[savecounter].FirstName,PhoneBook[savecounter].LastName,PhoneBook[savecounter].Number);
}
fclose(IOFile);
printf("Phonebook saved as %s\n\n",outfilename);
}
}[/code]
...I also get "What did you DO?" when I enter the filename, followed by a crash.
[QUOTE=Cathbadh;18168190]
Are you even sure that you are opening the file correctly? Your load function doesn't fail gracefully, and it is likely that it even fails silently.
[/QUOTE]
I don't know of any other way to open the file than what's been coded there.
[QUOTE=Cathbadh;18168190]
You see this line that you print out when fopen fails?
[code]printf("The file you have entered is invalid, or does not exist.");[/code]
You need a '\n' at the end of that line. Otherwise, it is quite likely that your terminal never prints out the line indicating the error. (This is because most terminals use canonical input processing. Character data is buffered internally and not returned by a read() syscall until a newline character is input into the buffer. This is to reduce the number of expensive syscalls to the kernel all the time)
[/QUOTE]
I'll change that.
[QUOTE=Cathbadh;18168190]
Furthermore, the function doesn't do anything differently on an error condition. At least it shouldn't try to load the non-existent file. Assuming feof(IOFile) returns true when IOFile = NULL (it doesn't have to, this behavior is undefined!) then you are still underflowing counter.
[/QUOTE]
That too.
[QUOTE=Cathbadh;18168190]
And one more thing, you are never closing the file descriptor. [U]This is very bad[/U] and likely why you were having trouble loading data in a second time after closing the program.[/QUOTE]
I think using fclose was giving me some trouble with earlier versions of the code, now it doesn't seem to raise any hell. It's been changed as well.
At this stage the problems mentioned above with being inable to open the file for reading or writing are the issues I'm running into.
Then you are probably entering something stupid for the filename. Upon failing, you should always try to provide more information about why it failed. Instead of [code]printf("What did you DO?");[/code]
use [code]fprintf(stderr, "SaveBook: %s\n", strerror(errno));[/code]
and that should help give you more information about why fopen failed.
[QUOTE=Cathbadh;18172044]Then you are probably entering something stupid for the filename. [/quote]
Even if I understand what the program wants, what if an end user enters a stupid filename?
[QUOTE=Cathbadh;18172044]Upon failing, you should always try to provide more information about why it failed. Instead of [code]printf("What did you DO?");[/code]
use [code]fprintf(stderr, "SaveBook: %s\n", strerror(errno));[/code]
and that should help give you more information about why fopen failed.[/QUOTE]
The code
[code]void SaveBook(ent * PhoneBook, int counter)
{
FILE *IOFile;
int savecounter;
char outfilename[128];
printf("Enter a name for your phonebook.\n");
fgets(outfilename,128,stdin);
IOFile=fopen(outfilename,"w");
if(!IOFile)
{
fprintf(stderr, "SaveBook: %s\n", strerror(errno));
}
else
{
for(savecounter=1;savecounter<=counter;savecounter++)
{
fprintf(IOFile,"%s %s %s\n",PhoneBook[savecounter].FirstName,PhoneBook[savecounter].LastName,PhoneBook[savecounter].Number);
}
fclose(IOFile);
printf("Phonebook saved as %s\n\n",outfilename);
}
}
void LoadBook(ent*PhoneBook, int counter)
{
FILE *IOFile;
char infilename[128];
Clear(PhoneBook, counter);
counter=0;
printf("Enter the name or location of the phonebook you wish to load.\n");
fgets(infilename,128,stdin);
printf("%s",infilename);
IOFile=fopen(infilename, "r");
if(!IOFile)
{
//printf("The file you have entered is invalid, or does not exist.\n");
fprintf(stderr, "LoadBook: %s\n", strerror(errno));
}
else
{
while(!feof(IOFile))
{
PhoneBook = (ent *) realloc(PhoneBook, (counter+1) * sizeof(ent));
counter++;
fscanf(IOFile,"%s %s %s",PhoneBook[counter].FirstName,PhoneBook[counter].LastName,PhoneBook[counter].Number);
}
counter--;
printf("Phonebook %s has been loaded.\n",infilename);
fclose(IOFile);
}
}[/code]
Returns the error Invalid Argument on both counts after entering a filename.
Oh, and I hope I am stating the obvious here but, actually *open your phonebook.txt data file in a text editor*.
Does it have any data at all? Is it in the expected format?
[QUOTE=streeter;18173232]Oh, and I hope I am stating the obvious here but, actually *open your phonebook.txt data file in a text editor*.
Does it have any data at all? Is it in the expected format?[/QUOTE]
Yes, files have been saving as designed for several iterations now.
[QUOTE=FZE;18172394]Even if I understand what the program wants, what if an end user enters a stupid filename?
The code
[code]void SaveBook(ent * PhoneBook, int counter)
{
FILE *IOFile;
int savecounter;
char outfilename[128];
printf("Enter a name for your phonebook.\n");
fgets(outfilename,128,stdin);
IOFile=fopen(outfilename,"w");
if(!IOFile)
{
fprintf(stderr, "SaveBook: %s\n", strerror(errno));
}
else
{
for(savecounter=1;savecounter<=counter;savecounter++)
{
fprintf(IOFile,"%s %s %s\n",PhoneBook[savecounter].FirstName,PhoneBook[savecounter].LastName,PhoneBook[savecounter].Number);
}
fclose(IOFile);
printf("Phonebook saved as %s\n\n",outfilename);
}
}
void LoadBook(ent*PhoneBook, int counter)
{
FILE *IOFile;
char infilename[128];
Clear(PhoneBook, counter);
counter=0;
printf("Enter the name or location of the phonebook you wish to load.\n");
fgets(infilename,128,stdin);
printf("%s",infilename);
IOFile=fopen(infilename, "r");
if(!IOFile)
{
//printf("The file you have entered is invalid, or does not exist.\n");
fprintf(stderr, "LoadBook: %s\n", strerror(errno));
}
else
{
while(!feof(IOFile))
{
PhoneBook = (ent *) realloc(PhoneBook, (counter+1) * sizeof(ent));
counter++;
fscanf(IOFile,"%s %s %s",PhoneBook[counter].FirstName,PhoneBook[counter].LastName,PhoneBook[counter].Number);
}
counter--;
printf("Phonebook %s has been loaded.\n",infilename);
fclose(IOFile);
}
}[/code]
Returns the error Invalid Argument on both counts after entering a filename.[/QUOTE]
Is that output from the program to the console when it runs, or is that a compile-time error?
In the case that this is a run-time error output you are listing, then it means errno was set to EINVAL, which would specifically mean that the 'mode' string is an invalid argument. But this doesn't make any sense because "w" is a completely legit argument for mode. Are you ever using anything other than libc for this? You aren't redefining fopen, are you? [I]Does the kernel's libc and the static library match?[/I]
[QUOTE=Cathbadh;18180341]Is that output from the program to the console when it runs, or is that a compile-time error?[/quote]
It's the output from the line you suggested I input.
Transcript from the running program:
[code]
...
9. Save Phone Book
10. Open Phone Book
11. Exit
9
Enter a name for your phonebook.
phonebook.txt
SaveBook: Invalid argument
Main Menu
...
[/code]
[QUOTE=Cathbadh;18180341]
In the case that this is a run-time error output you are listing, then it means errno was set to EINVAL, which would specifically mean that the 'mode' string is an invalid argument. But this doesn't make any sense because "w" is a completely legit argument for mode. Are you ever using anything other than libc for this? You aren't redefining fopen, are you? [I]Does the kernel's libc and the static library match?[/I][/QUOTE]
I wouldn't even know how to go about redefining fopen, I haven't touched any library files, and none are used other than the three #included at the beginning of the program.
Then I have no idea what is happening. What sort of environment are you running this on? fopen [I]specifically[/I] fails under that code whenever the mode argument is bad.
The class uses Dev C/C++. Not my choice, but I haven't found another IDE in which I can just compile source code into an EXE as quickly.
You could use CodeLite or Code::Blocks, both are able to run from a USB-Stick.
I will give those a shot.
This is the current state of the Load function, I've given up on modifying the input, this will work for the purpose of getting a grade.
[code]
ent* LoadBook(ent*PhoneBook, int counter)
{
FILE *IOFile;
int loadloop;
char infilename[128];
Clear(PhoneBook, counter);
counter=0;
char stringone[32];
char stringtwo[32];
char stringthree[32];
int variable=10;
printf("Enter the name or location of the phonebook you wish to load.\n");
gets(infilename);
IOFile=fopen(infilename, "r");
if(!IOFile)
{
printf("The file you have entered is invalid, or does not exist.\n");
fprintf(stderr, "LoadBook: %s\n", strerror(errno));
}
else
{
while(!feof(IOFile))
{
/*if(PhoneBook==NULL)
{
printf("PhoneBook is Null.");
}*/
PhoneBook = (ent *) realloc(PhoneBook, (counter+1) * sizeof(ent));
counter++;
fscanf(IOFile,"%s %s %s",PhoneBook[counter-1].FirstName,PhoneBook[counter-1].LastName,PhoneBook[counter-1].Number);
}
counter--;
printf("Phonebook %s has been loaded.\n",infilename);
fclose(IOFile);
}
return PhoneBook;
}[/code]
This works fine, and accomplishes what I was trying to do. Now the problem is in displaying the phonebook from the main menu.
[code]
case 1:
for(displaycounter=0; displaycounter<=counter; displaycounter++) //Displays entries in phone book
{
if(strcmp(PhoneBook[displaycounter].FirstName,"Empty")!=0) //Ignores entries that are Empty
{
printf("\n%s %s\n%s\n\n\n", PhoneBook[displaycounter].FirstName, PhoneBook[displaycounter].LastName, PhoneBook[displaycounter].Number);
}
}
break;[/code]
This also works fine. The problem is that within the LoadBook function, counter becomes a local variable, so when it's done loading data, the value of counter hasn't changed in the main function.
How can I return the value of counter to the main function once loading is finished? I'm already returning PhoneBook into ent *PhoneBook, how can I make use of the second variable passed to the function?
You could pass counter as a pointer.
You know, I thought the same thing.
Then I sat here and passed it as a pointer, and it gave me errors.
So then I passed it as a reference. And it gave me errors.
Then I copied and pasted the code into a new file, and it ran flawlessly.
Then I copied the flawlessly working reference-passing code into my main file, and it gave me syntax errors in places there were none before, despite everything but the code that I had just copied in being commented out.
counter is now a global variable, and this program gets to fuck off forever.
[QUOTE=FZE;18203446]You know, I thought the same thing.
Then I sat here and passed it as a pointer, and it gave me errors.
So then I passed it as a reference. And it gave me errors.
Then I copied and pasted the code into a new file, and it ran flawlessly.
Then I copied the flawlessly working reference-passing code into my main file, and it gave me syntax errors in places there were none before, despite everything but the code that I had just copied in being commented out.
counter is now a global variable, and this program gets to fuck off forever.[/QUOTE]
There is no such thing as references in C.
Maybe you forgot to dereference the pointer?
Sorry, you need to Log In to post a reply to this thread.