I try to load the contents of a text file into a structure.
My idea looks like this:
I have two files, struct.h , main.c and a list.txt file .
in file struct.h :
struct analg {
char word[6];
char signature[6];
};
struct analg h[106];
FILE *fp;
In file main.c :
#include<stdio.h>
#include "struct.h"
void load() {
fp = fopen("list.txt", "r");
if(fp == NULL) {
printf("fail");
return 1;
}
else {
printf("file loaded!\n");
}
fclose(fp);
return;
}
void print() {
int i;
for(i=0; i<1000; i++) {
while(fgets(h[i].word, 6, fp)) {
printf("%s", h[i].word);
}
}
return;
}
int main () {
int choice;
do {
printf("choose L or P: ");
scanf("%s", &choice);
switch(choice) {
case 'l':
load();
printf("\n[l]oad - [p]rint\n");
break;
case 'p':
print();
printf("\n[l]oad - [p]rint\n");
break;
default:
break;
}
} while(choice!='q');
return;
}
In file list.txt :
throw
timer
tones
tower
trace
trade
tread
So I try to load the text file by pressing the "L" to the structure, and then when I press the 'p' will be displayed, but it is not!
In your code, I see there are 2 potential issues. The choice has to be a character to be switched based on l or p. You may have to add cases to handle the upper case also.
Another issue is that in load function, you are closing the file pointer. Hence, when you enter the print function fgets may not work as the fp is already closed.
To load your file into structure, the load has to be modified as
void load() {
fp = fopen("list.txt", "r");
if(fp == NULL) {
printf("fail");
return; // There was an error in original code as this was returning 1
}
do{
fgets(h[count++].word, 6, fp); // Count is a global variable - no. of elements read
}while(!feof(fp));
printf("file loaded!\n");
fclose(fp);
return;
}
The corresponding print function would become
void print(){
int i;
printf("Inside print\n");
for(i=0; i < count; i++) {
printf("%s", h[i].word);
}
return;
}
the main function would be,
int main (){
char choice;
do{
printf("choose L or P: ");
scanf("%c", &choice); //Only character is read and hence, %s is not required
switch(choice){
case 'l':
load();
printf("\n[l]oad - [p]rint\n");
break;
case 'p':
print();
printf("\n[l]oad - [p]rint\n");
break;
default:
case 'q':
break;
}
} while(choice !='q');
return 0;
}
One last point. In the scanf statement if scanf("%s", &choice); is employed, then a runtime check error is generated when main exits, with a message that stack is corrupted around the variable choice.
I'll comment up what your code is doing:
void load() {
fp = fopen("list.txt", "r"); // opens the file for reading
if(fp == NULL) {
printf("fail"); // if the file couldn't be opened, return an error
return 1; // (aside: a void function can't return an int)
}
else {
printf("file loaded!\n"); // tell the user that the file was opened
}
fclose(fp); // close the file, having read nothing from it
return;
}
At no point do you read anything from the file. What you have in memory will therefore have no relation to whatever you have on disk.
C has no built-in means for serialising and deserialising structs so what you need to do is define a formal grammar for your file on disk and write code that can parse that grammar into your structs.
Related
I can't get my delete record function to break out of the switch case or even give me an error when the record doesn't exist. Could someone please tell me why this is?
Any help is much appreciated!
I can't get my delete record function to break out of the switch case or even give me an error when the record doesn't exist. Could someone please tell me why this is?
Any help is much appreciated!
void delete_record();
void displayContent();
struct Update
{
char studentName[50];
char studentID [50];
char emailID[100];
char courseID[5];
char grade[50];
} update2;
int main ()
{
int num;
do
{
printf("1. Delete a record for the specific name\n");
printf("2. Display Content of File\n");
printf("6. Exit\n");
switch(num)
{
case 1:
printf("this is a test\n");
delete_record();
break;
//displayContent();
//printf("this is a test 2\n");
case 2:
printf("\n\nDiplaying Contents of File\n\n");
displayContent();
default:
printf("Give me a break!\n");
break;
}
scanf("%d", &num);
} while (num != 6);
return 0;
}
void delete_record()
{
FILE *fp;
FILE *fp_tmp;
fp = fopen ("BINARY_FILE.txt", "w");
char studentsID[20];
printf("enter studentID to delete:");
scanf("%s",studentsID);
printf("is this a test?\n");
while(fread(&update2,sizeof(update2),1,fp))
{
printf("this is another test\n");
if(strcmp(update2.studentID,studentsID) != 0)
{
//printf("testing\n");
fwrite(&update2,sizeof(update2),1,fp);
}
else
{
printf("No student with that student ID\n");
}
}
printf("more tests\n");
fclose(fp);
return;
}
void displayContent()
{
char c;
// Open file
FILE *fp;
fp = fopen ("BINARY_FILE.txt", "r");
if (fp == NULL)
{
printf("File Has No Content\n");
exit(0);
}
// Read contents from file
c = fgetc(fp);
while (c != EOF)
{
printf ("%c", c);
c = fgetc(fp);
}
fclose(fp);
//return 0;
}
When using scanf to read from the keyboard you must remember
that all characters that you enter are written to the in-buffer,
this means that if you type in
42ENTER
The ENTER will also be present in the in-buffer, so next time you call scanf ENTER will still be in the buffer and then scanf returns 0 since the format specificier "%d" doesn't match.
The easiest way to handle input from keyboard in C and to avoid the hassle of scanf in-buffer by using fgets() to read from the keyboard, then use sscanf() to cherry pick from the buffer:
// always check return value from all runtime functions when possible
char buffer[128];
if (fgets(buffer,sizeof(buffer), stdin) != NULL)
{
if (sscanf(buffer, "%d", &num) == 1)
{
}
else {...}
}
else {...}
Noob programmer here...so please bear with me. I'm trying to pass an existing text file into an array however once my main Menu loads the information that once existed in that file goes away, even if I don't make any changes. it is just not keeping the information. The Program is supposed to allow the user to either create a new file or update and/or load an existing file. Any ideas on how to fix this issue? Thank you all!
char fileName[20] = "";
void loadEmployee()
{
FILE* fPtr;
char singleLine[150];
if (strcmp(fileName, "") == 0)
{
printf("\nWhat's the name of the file? ");
scanf_s("%s", fileName, 20);
}
fopen_s(&fPtr, fileName, "r");
while (!feof(fPtr))
{
fgets(singleLine, 150, fPtr);
puts(singleLine);
}
fclose(fPtr);
}
void saveEmployee()
{
FILE* fPtr;
if (strcmp(fileName, "") == 0)
{
printf("\nWhat's the name of the file? ");
scanf_s("%s", fileName, 20);
}
fopen_s(&fPtr, fileName, "w");
for (int i = 0; i < numEmps; i++)
{
fprintf(fPtr, "%s %f %f\n", emps[i].emps.name,
emps[i].emps.rate, emps[i].emps.hours);
}
fclose(fPtr);
}
void loadMenu()
{
int i = 0;
printf("1. Load from a file \n");
printf("2. Keyboard \n");
scanf_s("%d", &choice);
switch (choice)
{
case 1: loadEmployee();
break;
default:
break;
}
do
{
printf("\nMAIN MENU\n");
printf("1.Add Employee\n");
printf("2.Edit Employee\n");
printf("3.Print Employee\n");
printf("4.Print ALL employees\n");
printf("5.Exit\n");
scanf_s("%d", &choice);
switch (choice)
{
case 1: NameInput();
break;
case 2: printf("Choose employee: \n");
for (int i = 0; i < numEmps; i++)
{
printf("%d. %s \n", i + 1,
emps[i].emps.name);
}
scanf_s("%d", &choice);
empUpdate(choice - 1);
break;
case 3: printf("Choose employee: \n\n");
for (int i = 0; i < numEmps; i++)
{
printf("%d) %s \n", i + 1,
emps[i].emps.name);
}
scanf_s("%d", &choice);
printf("%s \n", emps[choice -
1].emps.name);
printf("%.2f \n", emps[choice -
1].emps.hours);
printf("%.2f \n", emps[choice -
1].emps.rate);
break;
case 4: PayOutput();
break;
case 5: printf("Quitting program!");
saveEmployee();
return;
default: printf("Invalid choice try again \n\n");
break;
}
} while (choice != 5);
}
int main()
{
struct information empsi[20];
loadMenu();
}
Your function loadEmployee only writes to a char[] that is local to the function (which means it’s discarded at the end).
When the program exits, you « save » the employee by reopening your file in write mode, which clears it, and what follows probably doesn’t do much, so the file remains empty.
Try actually returning or storing the data from the file outside your function so it can be reused later.
As #hugo said, the program reads the file but doesn't store the contents. This means emps will be empty. When you quit you open the file for writing deleting its contents. Beause emps is empty, nothing is written.
This can be solved by reading similar to how you're writing. I don't know exactly what emps looks like, but something like this.
for( numEmps = 1; fgets(singleLine, 150, fPtr); numEmps++ ) {
// I'm assuming emps is preallocated.
struct Employee emp = emps[numEmps-1];
sscanf(singleLine, "%80s %f %f",
emp.emps.name,
&emp.emps.rate,
&emp.emps.hours
);
}
Notice rather than using feof I'm looking at the return value of fgets. As Edward Karak mentioned, when reading lines don't check for eof.
Other issues in the code...
You're not checking whether your files actually opened.
fopen_s(&fPtr, fileName, "r");
if( !fPtr ) {
perror(fileName);
exit(1);
}
The code uses a lot of global variables. This leads to hard to understand code as anything can change those globals at any time. Instead, take advantage of function arguments and return values. Then you can completely understand a function just by looking at it.
For example, loadEmployee should take the struct to populate and the filename to read from, then return how many it read. saveEmployee is similar.
int loadEmployee(struct Employee *emps, char *fileName) {
...
return numEmps;
}
void saveEmployee(struct Employee *emps, char *fileName) {
...
}
Neither should be in charge of asking the user for the filename. This should be handled by the caller. Functions should do one thing; it makes them simpler and more flexible.
We can move the logic to get the filename into a function. Rather than using a global, we use a static variable. This variable is still local to the function, but does not get reset. getFileName remembers the filename.
char *getFileName() {
static char fileName[80] = "";
if (strcmp(fileName, "") == 0)
{
printf("\nWhat's the name of the file? ");
scanf("%20s", fileName);
}
return fileName;
}
...
switch(choice) {
case 1:
numEmps = loadEmployee(emps, getFileName());
break;
...
case 5:
printf("Quitting program!");
saveEmployee(emps, getFileName());
return;
}
...
These are not the source of your problem, but they will help structure your code so it's easier to understand and debug.
It's my first time asking here, so I'm sorry in advance if my post is a bit messy. I'm a freshman and my finals is to make an atm program.
My program uses switch statements for the options: the first one asks the user for their info, (account number, account name, PIN, initial deposit), while the second one is for the actual transactions: Balance check, Deposit and Withdrawal. Before you could do any one of those options, of course I'll have to check if the info (in this case the account number and PIN) matches the ones in my file.
The file is in binary. My problem is that my code for reading the file works fine if i want to display the contents of my file (all the data entries that I populated the file with are shown), but when i want to use the contents of the file (searching inside the file for a match of the user inputted account number) it only reads the first line of the file, thus only the first data entry works, while the one's after that are not read.
My question is, what am i doing wrong in my code? its confusing because if I change my code to display the contents it shows everything, meaning it reads the whole file. but when i want to search the file using a conditional statement, only the first data entry gets read. Thank you very much for your time
tldr: can't use data in file for conditionals (verify the data inside the file, cuz my code doesn't read it whole apparently, except for the first entry)
but if i print the contents it reads it fully
my outputs
1.My data entries
data entries
2.Entering the Account no. of the 1st one (desired output)
desired output
3.Entering The account no. of the 2nd one (Problem part)
problem
my main code
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#include<process.h>
struct account
{
int no;
char name[100];
int pin;
float id;
};
main()
{
FILE *fptr;
fptr = fopen("accrec.dat","ab");
if (fptr == NULL)
{
printf("File does not exists \n");
return 0;
}
system("cls");
struct account accrec;
int i,tpin[4];
char step1,ch;
printf("\t\tWelcome to Banking System\n\t");
printf("\nA.Open an Account\n");
printf("\nB.Bank Transaction\n");
printf("\nC.exit\n");
scanf("%c",&step1);
switch (step1)
{
case 'A':
printf("Open a New Account\n");
printf("\nEnter the following information\n");
printf(" \n5-digit Account number:");
scanf("%d",&accrec.no);
getchar();
printf("\nAccount Name:");
scanf("%[^\n]s",&accrec.name);
printf("\n4-digit Account PIN:");
/*for(i=0;i<4;i++)
{
ch = getch();
tpin[4] = ch;
ch = '*' ;
printf("%c",ch);
}mask works but does not allow PIN saving */
scanf("%d",&accrec.pin);
printf("\nInitial deposit:");
scanf("%f",&accrec.id);
fwrite(&accrec,sizeof(struct account),1,fptr);
fclose(fptr);
break;
case 'B':
{
fptr = fopen("accrec.dat","rb");
int choice;
int accno = 0;
printf("Enter Your Account no.");
scanf("%d",&accno);
while (fread(&accrec,sizeof(account),1,fptr)!=NULL)
{
if(accno == accrec.no)
{
printf("\tWelcome to PUPQC Banking System\n");
printf("1.Balance Inquiry\n");
printf("2.Deposit\n");
printf("3.Withdrawal\n");
printf("4.quit\n");
scanf("%d",&choice);
}
else
{
printf("account doesn't exist\n");
exit(1);
}
fclose(fptr);
switch (choice)
{
case 1:
printf("BALANCE INQUIRY\n");
printf("Current Balance:");
fptr = fopen("accrec.dat","rb");
if (fptr == NULL)
{
printf("File Cant be read");
exit(1);
}
printf("Account No: %d\n",accrec.no);
while(fread(&accrec,sizeof(struct account),1,fptr)!=NULL);
{
printf("Initial Deposit is %0.2f\n",accrec.id);
}
printf("%d\n",&accrec.id);
break;
case 2:
float dv;
printf("DEPOSIT\n");
printf("Current Balance:");
fptr = fopen("accrec.dat","rb");
if (fptr == NULL)
{
printf("File Cant be read");
exit(1);
}
while(fread(&accrec,sizeof(struct account),1,fptr)!=NULL);
{
printf("%0.2f\n",accrec.id);
}
printf("Enter amount to deposit:\n");
printf("Deposit Value:");
scanf("%0.2f",&dv);
accrec.id = accrec.id + dv;
fwrite(&accrec,sizeof(struct account),1,fptr);
fclose(fptr);
break;
case 3:
float wv;
printf("WITHDRAWAL\n");
printf("Current Balance:");
fptr = fopen("accrec.dat","rb+");
if (fptr == NULL)
{
printf("File Cant be read");
exit(1);
}
while(fread(&accrec,sizeof(struct account),1,fptr)!=NULL);
{
printf("%0.2f\n",accrec.id);
}
printf("Enter amount to withdraw:\n");
printf("Withdrawal Value:");
scanf("%0.2f",wv);
accrec.id = accrec.id - wv;
fwrite(&accrec,sizeof(struct account),1,fptr);
fclose(fptr);
break;
case 4:
printf("thank you for your patronage \n");
return 0;
break;
default:
printf("error 404");
break;
}
}
}
break;
case 'C':
printf("Thank you! Have a good day");
return 0;
break;
case 'D':
fptr = fopen("accrec.dat","rb");
if (fptr == NULL)
{
printf("File Cant be read");
exit(1);
}
printf("Data From file\n");
while(fread(&accrec,sizeof(struct account),1,fptr)!=NULL)
printf("\n acc.no is %d\n acc.name is %s\n PIN %d\n Initial Deposit is %0.2f\n ",accrec.no,accrec.name,accrec.pin,accrec.id);
fclose(fptr);
getch();
break;
default:
printf("invalid input! please select form the options given\n");
}
}
my structure
struct account
{
int no;
char name[100];
int pin;
float id;
};
code for finding a match of account number in my file
(the part i'm having trouble with)
fptr = fopen("accrec.dat","rb");
int choice;
int accno = 0;
printf("Enter Your Account no.");
scanf("%d",&accno);
while (fread(&accrec,sizeof(account),1,fptr)!=NULL)
{
if (accno == accrec.no)
{
printf("\tWelcome to Banking System\n");
printf("1.Balance Inquiry\n");
printf("2.Deposit\n");
printf("3.Withdrawal\n");
printf("4.quit\n");
scanf("%d",&choice);
}
else
{
printf("account doesn't exist\n");
exit(1);
}
}
fclose(fptr);
The expected output is that my conditional statement works properly and reads my whole file for matches.
try to change the exit(1) to continue;, the exit(1) will make your program quit the while loop and exit the program immediately whenever accno != accrec.no.
in fact, you don't need the else statement inside the while loop, you should put it outside the while loop. for example:
scanf("%d",&accno);
boolean found = false;
while (fread(&accrec,sizeof(account),1,fptr)!=NULL)
{
if (accno == accrec.no)
{
found = true;
scanf("%d",&acpin);*/
printf("\tWelcome to Banking System\n");
printf("1.Balance Inquiry\n");
printf("2.Deposit\n");
printf("3.Withdrawal\n");
printf("4.quit\n");
scanf("%d",&choice);
}
}
if (!found) {
printf("account doesn't exist\n");
}
fclose(fptr);
I am writing a phone book program. I completed first function.
However, in second function (("" display() function "")) there is something wrong which is I couldn't find.
In display() function, I'm taking another name which is searched by user and comparing it with names into file to show that person's knowledge (Just one person) on the screen. But it doesn't work. How can I solve this problem?
#include <stdio.h>
#include <stdlib.h> // "stdlib" library contains of exit() and malloc function
#include <Windows.h> // "Windows" library contains of Sleep() function which waits the system as you want
#include <string.h> // "string" library contains of strcmp() function which compares string statements
struct personKnowledge
{
char number[16];
char name[16];
char surname[16];
char sName[16];
};
void newRecord(FILE *);
void display(FILE *);
void deletE();
void add();
void update();
FILE *ptrFILE;
int main()
{
int choice;
if ((ptrFILE = fopen("Phone Book.txt", "w+")) == NULL)
{
printf("The file couldn't open\n");
}
do
{
printf("\n\t\t --- Phone Book Program ---");
printf("\n\n\t\t 1) New record"); // The options are being presented to user
printf("\n\n\t\t 2) Display person knowledge");
printf("\n\n\t\t 3) Delete someone");
printf("\n\n\t\t 4) Add new person");
printf("\n\n\t\t 5) Update person knowledge");
printf("\n\n\t\t 6) Exit");
printf("\n\n\nEnter your choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
{
newRecord(ptrFILE);
break;
}
case 2:
{
display(ptrFILE);
break;
}
case 3:
{
break;
}
case 4:
{
break;
}
case 5:
{
break;
}
case 6:
{
printf("\nWorking has been completed.\n");
exit(EXIT_SUCCESS);
break;
}
default:
{
printf("\nWrong entry! The program has been terminated.\n");
}
}
} while (choice >= 1 && choice <= 6);
fclose(ptrFILE);
return 0;
}
void newRecord(FILE *ptrFILE)
{
static int counter = 0;
system("cls"); // Screen is being cleaned
struct personKnowledge *p; // p means person
p = (struct personKnowledge *)malloc(sizeof(struct personKnowledge)); // Memory is being allocated
fflush(stdin);
printf("\n\nDetermine person name: "); // User is entering the person's knowledge and they are being saved in file
gets(p->name);
printf("Determine %s's surname: ", p->name);
gets(p->surname);
printf("Determine %s's number: ", p->name);
gets(p->number);
if (counter == 0)
{
fprintf(ptrFILE, "Name\t\t\t\tSurname\t\t\t\tNumber\n");
fprintf(ptrFILE, "--------\t\t ----------------\t\t------------------------\n");
}
fprintf(ptrFILE, "\n%-33s%-33s%-38s\n", p->name, p->surname, p->number);
printf("Please wait, information is saving to file..\n");
Sleep(750);
printf("*-* Saving operation has been completed. *-*\n");
counter++;
free(p);
}
void display(FILE *ptrFILE)
{
if ((ptrFILE = fopen("Phone Book.txt", "r")) == NULL)
{
printf("The file couldn't open\n");
}
else
{
system("cls"); // Screen is being cleaned
struct personKnowledge *s; // s means searching
s = (struct personKnowledge *)malloc(sizeof(struct personKnowledge));
fseek(ptrFILE, 0L, SEEK_SET);
fflush(stdin);
printf("\n\nExpress name which you search: ");
gets(s->sName);
while (!feof(ptrFILE))
{
fscanf(ptrFILE, "\n%-33s%-33s%-38s\n", &s->name, &s->surname, &s->number);
if (strcmp(s->name, s->sName) == 0)
{
printf("*-* Person knowledge who is you search *-*\n");
Sleep(750);
printf("\n\nName: %s\nSurname: %s\nNumber: %s\n", s->name, s->surname, s->number);
}
}
free(s);
}
}
The MSVC documentation of fopen says about mode: "w" Opens an empty file for both reading and writing. If the file exists, its contents are destroyed.
Since the first file open in main is
if ((ptrFILE = fopen("Phone Book.txt", "w+")) == NULL)
you destroy anything you already have.
To read the content, use mode "r" to open the file, read the content, then close it.
To add new content, either re-open with mode "w" and write the whole content, or open in append mode "a" and just write the new records(s).
Or you can open in mode "r+" for reading and writing, but before writing you need to fseek the end of the file.
In int main() you opened file with "w+" mode so everything is discarded in file when it is called.
Also in function void display(FILE *ptrFILE) you have not closed the text file.And you have used feof() inside while loop which may create problem .
Please see following link why you should not use while(!feof())-Why is “while ( !feof (file) )” always wrong?
void display(FILE *ptrFILE)
{
fclose(ptrFILE);//!! flush out
if ((ptrFILE = fopen("Phone Book.txt", "r")) == NULL)
{
printf("The file couldn't open\n");
}
else
{
char buff[128];//!!for fgets
system("cls"); // Screen is being cleaned
struct personKnowledge *s; // s means searching
s = (struct personKnowledge *)malloc(sizeof(struct personKnowledge));
//fseek(ptrFILE, 0L, SEEK_SET);//!!no need
fflush(stdin);
printf("\n\nExpress name which you search: ");
gets(s->sName);
while (fgets(buff, sizeof buff, ptrFILE))//!!
{
sscanf(buff, "%15s%15s%15s\n", s->name, s->surname, s->number);//!!
I am slowly learning C, but not very well. I have been reading over the countless topics and questions on reading and writing, but I have yet to be able to find anything that makes this all click for me.
I was given the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
struct YouTubeVideo {
char video_name[1024]; // YouTube video name
int ranking; // Number of viewer hits
char url[1024]; // YouTube URL
};
struct YouTubeVideo Collection[MAX];
int tail = 0;
//-- Forward Declaration --//
void printall();
void insertion();
void branching(char option);
void menu();
int main()
{
char ch;
// TODO: Add code to load save data from file
printf("\n\nWelcome to CSE240: YouTube Classic Hits\n");
do {
menu();
fflush(stdin); // Flush the standard input buffer
ch = tolower(getchar()); // read a char, convert to lower case
branching(ch);
} while (ch != 'q');
return 0;
}
void menu()
{
printf("\nMenu Options\n");
printf("------------------------------------------------------\n");
printf("i: Insert a new favorite\n");
printf("p: Review your list\n");
printf("q: Save and quit\n");
printf("\n\nPlease enter a choice (i, p, or q) ---> ");
}
void branching(char option)
{
switch(option)
{
case 'i':
insertion();
break;
case 'p':
printall();
break;
case 'q':
// TODO: Add code to save data into a file
break;
default:
printf("\nError: Invalid Input. Please try again...");
break;
}
}
void insertion()
{
if(tail < MAX)
{
printf("\nWhat is the name of the video? (No spaces characters allowed)\n");
scanf("%s", Collection[tail].video_name);
printf("\nHow many viewer hits does this video have?\n");
scanf("%d", &Collection[tail].ranking);
printf("\nPlease enter the URL: ");
scanf("%s", &Collection[tail].url);
tail++;
}
else
{
printf("\nERROR: Your collection is full. Cannot add new entries.\n");
}
}
void printall()
{
int i;
printf("\nCollections: \n");
for(i = 0; i < tail; i++)
{
printf("\nVideo Name: %s", Collection[i].video_name);
printf("\nRanking (Hits): %d", Collection[i].ranking);
printf("\nURL: %s", Collection[i].url);
printf("\n");
}
}
I am suppose to write the code that will store the collection into a file and the likewise right the code that will load the file and read from it.
Thanks to a fairly helpful TA I was able to formulate the following code for each
void store()
{
FILE * fileName;
fileName = fopen ( "Ranking.dbm" , "wb" );
fwrite ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
fclose (fileName);
}
and
void read()
{
FILE *fileName;
fileName = fopen("ranking.dbm", "rb");
if (fileName != NULL){
fread ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
}
else {
printf("ERROR");
}
}
I believe these each to function but the real problem is I don't think I quite understand how and I believe that since I dont even know how they function, I dont know how to use them in the code.
I added both methods to the given code and came up with this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 100
struct YouTubeVideo {
char video_name[1024]; // YouTube video name
int ranking; // Number of viewer hits
char url[1024]; // YouTube URL
};
struct YouTubeVideo Collection[MAX];
int tail = 0;
//-- Forward Declaration --//
void printall();
void insertion();
void branching(char option);
void menu();
void store();
void read();
int main()
{
char ch;
read();
printf("\n\nWelcome to CSE240: YouTube Classic Hits\n");
do {
menu();
fpurge(stdin); // Flush the standard input buffer
ch = tolower(getchar()); // read a char, convert to lower case
branching(ch);
} while (ch != 'q');
return 0;
}
void menu()
{
printf("\nMenu Options\n");
printf("------------------------------------------------------\n");
printf("i: Insert a new favorite\n");
printf("p: Review your list\n");
printf("q: Save and quit\n");
printf("\n\nPlease enter a choice (i, p, or q) ---> ");
}
void branching(char option)
{
switch(option)
{
case 'i':
insertion();
break;
case 'p':
printall();
break;
case 'q':
store();
break;
default:
printf("\nError: Invalid Input. Please try again...");
break;
}
}
void insertion()
{
if(tail < MAX)
{
printf("\nWhat is the name of the video? (No spaces characters allowed)\n");
scanf("%s", Collection[tail].video_name);
printf("\nHow many viewer hits does this video have?\n");
scanf("%d", &Collection[tail].ranking);
printf("\nPlease enter the URL: ");
scanf("%s", &Collection[tail].url);
tail++;
}
else
{
printf("\nERROR: Your collection is full. Cannot add new entries.\n");
}
}
void printall()
{
int i;
printf("\nCollections: \n");
for(i = 0; i < tail; i++)
{
printf("\nVideo Name: %s", Collection[i].video_name);
printf("\nRanking (Hits): %d", Collection[i].ranking);
printf("\nURL: %s", Collection[i].url);
printf("\n");
}
}
void store()
{
FILE * fileName;
fileName = fopen ( "Ranking.dbm" , "wb" );
if (fileName != NULL)
{
fwrite ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
fclose (fileName);
}
else {
perror("Following error occurred(): ");
}
}
void read()
{
FILE *fileName;
fileName = fopen("Ranking.dbm", "rb");
if (fileName != NULL)
{
fread ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
fclose(fileName);
}
else {
perror("Following error occurred with fopen(): ");
}
}
Now I am sure anyone who has read this has probably already face palmed themselves cause they see the problem, but I do not. The code does not create the file to write to and likewise it has nothing to read from so I cant even begin to see what is wrong with that.
Now I am not looking for a given answer, but I would really like to know what it is I am doing incorrectly, what concepts I appear to not understand, and how I can go about fixing these. I have done a few hours of research on this already and I realize it is elementary, but I really would like a hand in learning. Its frustrating spending hours on a topic that the professor said should only take a couple of hours to complete at most.
You really should check the return value of fopen() against NULL - if there is a problem opening the file, it will return NULL and set errno. This is probably a permissions mistake, and by checking the return value and printing the error if one is set, you'll get more information on what went wrong.
Minor: Make sure to check the return values for things like fopen, fread, fwrite etc. more often.
Mild: You've got a potential typo in the filename (some operating systems have case-sensitive file names)
Severe: read() doesn't set up a value for tail... :)
I believe you may have a problem with the read function, which does not call fclose on the file handle (by the way, calling it fileName is a little misleading).
Because you leave the file open, it's entirely likely that you won't be able to overwrite it when you eventually call store. You haven't output any error messages if the file cannot be opened in that function, so it's quite easy to slip under the radar... At least until you wonder why your file date doesn't change.
Otherwise the code looks okay. All it does is dump the entire contents of your array out of memory and read it back in again. What you'll probably want to do is also write out the value of tail, since it is keeping track of how many elements you are keeping. So with minimal code changes, do this:
fwrite ( &tail, sizeof(int), 1, fileName);
fwrite ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
And of course the corresponding calls to fread in your read method.
fread ( &tail, sizeof(int), 1, fileName);
fread ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
To reiterate: don't forget to close your file!!!!
fclose(fileName);