So my program basically asks for the assignment name/student name after clicking "1" from the student menu to submit an assignment. The function reads an arbitrary assignment from a text file I have in my debug folder, called "myassignment.txt". Then it creates a new file called "submission.txt" with the assignment name, student name and the assignment in it.
When I click "2" from the student menu to see the submitted assignment, it prints the assignment name and student name fine, but skips the first few characters from the first line of the actual assignment.
It skips more or less characters depending on how long the assignment name and student name are.
I can't figure out why it's doing this.
Here is my code for the data structure, menu, and functions used in the first two options of the menu:
#include "assignmentgrading3.h"
#define MAX_STUDENT_NAME_SIZE 50
#define MAX_ASSIGNMENT_NAME_SIZE 50
#define MAX_ASSIGNMENT_SIZE 1000
typedef struct{
char assignmentName[MAX_ASSIGNMENT_NAME_SIZE];
char studentName[MAX_STUDENT_NAME_SIZE];
char assignment[MAX_ASSIGNMENT_SIZE];
double score;
} Assignment;
void studentMenu(Assignment* assignmentStruct) {
int choice;
do {
printf("\nStudent Menu:\n");
printf("1. Submit an assignment\n");
printf("2. See the submitted assignment\n");
printf("3. See the graded assignment\n");
printf("4. Exit\n");
printf("Please enter a number from 1 - 4: ");
scanf("%d", &choice);
switch (choice) {
case 1:
submitAssignment(assignmentStruct, "myassignment.txt");
break;
case 2:
getAssignment(assignmentStruct);
displayAssignment(assignmentStruct);
break;
case 3:
getGradedAssignment(assignmentStruct);
displayGradedAssignment(assignmentStruct);
break;
case 4:
exit(0);
break;
}
} while (choice != 5);
}
void readRemainingLines(FILE* pFile, char* assignment){
long charsRead = 0;
while(fgets(assignment + charsRead, MAX_ASSIGNMENT_SIZE - charsRead, pFile)!= NULL)
{
charsRead = strlen(assignment);
if(charsRead >= MAX_ASSIGNMENT_SIZE - 1) //Credits: Carl Gelfand
break;
}
assignment[MAX_ASSIGNMENT_SIZE-1] = 0; //Just to make sure.
}
//Reads the file whose name is provided as string “fileName”,
//and creates a file named “submission.txt” as specified in the functional specification.
//It returns a 1 when it is successful, otherwise it returns a 0.
int submitAssignment(Assignment* assignmentStruct, char* fileName) {
FILE* pFile =0;
//char assignment[MAX_ASSIGNMENT_SIZE];
char* submissionFileName="submission.txt";
//Reading information from a user provided file : fileName
pFile = fopen(fileName,"r");
if(pFile==NULL){
printf("%s file did not open\n,",fileName);
exit(0);
}//EO if(pFile==NULL)
printf("Please enter the name of the assignment: ");
scanf(" %s", assignmentStruct->assignmentName);
printf("Please enter your (student) name: ");
scanf(" %s", assignmentStruct->studentName);
readRemainingLines(pFile, assignmentStruct->assignment);
fclose(pFile);
// Writing Information to "submission.txt"
pFile = fopen(submissionFileName, "w");
if(pFile == NULL) {
printf("%s file did not open\n,", submissionFileName);
exit(0);
} //EO if(pFile==NULL)
fprintf(pFile, "%s\n", assignmentStruct->assignmentName);
fprintf(pFile, "%s\n", assignmentStruct->studentName);
fprintf(pFile, "%s\n", assignmentStruct->assignment);
fclose(pFile);
return 1;
}
int getAssignment(Assignment* assignmentStruct) {
FILE* pFile = 0;
pFile = fopen("submission.txt","r");
if(pFile==NULL){
printf("file did not open\n,");
exit(0);
}
fscanf(pFile, "%[^\n]", assignmentStruct->assignmentName);
fscanf(pFile, "%[^\n]", assignmentStruct->studentName);
readRemainingLines(pFile, assignmentStruct->assignment);
return 1;
}
void displayAssignment(Assignment* assignmentStruct) {
char* middleOfAssignment = &(assignmentStruct->assignment[strlen(assignmentStruct->assignmentName) + strlen(assignmentStruct->studentName) + 2]);
print(assignmentStruct->assignmentName, assignmentStruct->studentName);
printf("%s \n", middleOfAssignment);
//printf("%s \n", assignment);
}
void print(char* assignmentName, char* studentName) {
printf("Assignment Name: %s \nStudent: %s\n", assignmentName, studentName);
}
displayAssignment is skipping over the first few characters of the assignment when it assigns middleOfAssignment. It's skipping the first strlen(assignmentStruct->assignmentName) + strlen(assignmentStruct->studentName) + 2 characters.
It should just print assignmentStruct->assignment, there's no need for middleOfAssignment. The only reason for that code would be if assignment contained a copy of the assignment name and student name at the beginning, but it doesn't.
void displayAssignment(Assignment* assignmentStruct) {
print(assignmentStruct->assignmentName, assignmentStruct->studentName);
printf("%s \n", assignmentStruct->assignment);
}
Related
I am working on code for s blood donation system. I'm currently struggling with the delete donor record function.
The delete record function is to delete the record of a donor with a given name. If there are two or more records with the same name in the file then the program asks for mobile number. While there may be more than one person with the same name, each person has a unique mobile number.
My problem is that when the same name is used for several records, the wrong record is deleted.
If there's only one record with that name, the program deletes the record in the manner that's required.
(The variable i is declared globally as int i)
Here's the delete function
void delete(struct blood *b,int n)
{
char name[50];
int phone;
int found=0;
int c=0;
FILE *fp = fopen("bloodrecord.txt", "r");
FILE *fp1 = fopen("temp.txt", "w");
printf("\nEnter Name: ");
scanf("%s", name);
printf("---------------------------------------------\n");
while(fread(&b[i],sizeof(struct blood),1,fp))
{
if(strcmpi(b[i].name,name)==0)
{
c=c+1;
printf("\nName: %s\n",b[i].name);
printf("Age: %d\n", b[i].age);
printf("Mobile no.: %d\n", b[i].phone);
printf("Blood group: %s\n", b[i].bg );
printf("Weight: %d\n", b[i].weight);
printf("Sex: %s\n",b[i].sex);
printf("Address: %s\n",b[i].add);
printf("\n");
if (c==1)
{
found=1;
}
else if(c>1)
{
printf("\nThere are more than one occurences of this name in the records\n");
printf("\nPlease enter the mobile number of the donor: ");
scanf("%d", &phone);
if (b[i].phone == phone)
{
found=1;
}
}
}
else
fwrite(&b[i],sizeof(struct blood),1,fp1);
}
fclose(fp);
fclose(fp1);
if (found==1)
{
fp1 = fopen("temp.txt", "r");
fp = fopen("bloodrecord.txt", "w");
while(fread(&b[i],sizeof(struct blood),1,fp1))
{
fwrite(&b[i],sizeof(struct blood),1,fp);
}
fclose(fp);
fclose(fp1);
}
else
{
printf("\n\aRECORD DOES NOT EXIST.\n");
}
printf("RECORD SUCCESSFULLY DELETED");
getchar();
getchar();
}
I suggest that to make the program simpler, you request both the donor's name and the donor's mobile number at the beginning.
Then you process the input file and look for both name and mobile number in a single pass.
I started with your code and made a few changes. See comments.
Please note that I have not tested this code nor compiled it. It should be essentially correct however there may be a compiler error if I made a syntax mistake.
I assume that the you are using the struct blood correctly in your code since you did not provide the code defining that struct.
I assume that an int is sufficiently large to hold the mobile number. Since the size of an int can vary and is determined by the compiler, it may or may not be large enough for a mobile number. See Range of values in C Int and Long 32 - 64 bits
One thing I do not understand is why you are using the b[i] syntax and where is the variable i defined? You could instead use a local variable in the delete() function.
I also have the delete() function returning a value indicating if it found a match or not. This may or may not be useful.
int delete()
{
struct blood b;
char name[50] = {0};
int phone;
int found = 0;
FILE *fp = fopen("bloodrecord.txt", "r");
FILE *fp1 = fopen("temp.txt", "w");
// Ask for the donor's mobile number along with their name
// at the beginning to make the search easier and be able to
// do this in a single pass.
printf("\nEnter Name of the donor: ");
scanf("%49s", name); // Oka's comments about scanf().
printf("\nPlease enter the mobile number of the donor: ");
scanf("%d", &phone);
printf("---------------------------------------------\n");
while(fread(&b, sizeof(struct blood), 1, fp))
{
// check both donor's name and donor's mobile number.
if(strcmpi(b.name, name) == 0 && b.phone == phone)
{
// print out the donor data and indicate we are deleting
// this donor record.
printf("Deleting donor record\n");
printf(" Name: %s\n", b.name);
printf(" Age: %d\n", b.age);
printf(" Mobile no.: %d\n", b.phone);
printf(" Blood group: %s\n", b.bg );
printf(" Weight: %d\n", b.weight);
printf(" Sex: %s\n", b.sex);
printf(" Address: %s\n", b.add);
printf("\n");
found = 1;
}
else {
// we are keeping this donor record so write it to the
// temp file.
fwrite(&b, sizeof(struct blood), 1, fp1);
}
}
fclose(fp);
fclose(fp1);
if (found == 1)
{
// file temp.txt has deleted donors so lets updated
// the original file, bloodrecord.txt, with the updated
// list of donors.
fp1 = fopen("temp.txt", "r");
fp = fopen("bloodrecord.txt", "w");
while(fread(&b, sizeof(struct blood), 1, fp1))
{
fwrite(&b, sizeof(struct blood), 1, fp);
}
fclose(fp);
fclose(fp1);
printf("RECORD SUCCESSFULLY DELETED");
}
else
{
printf("\n\aRECORD DOES NOT EXIST.\n");
}
getchar();
getchar();
return found; // indicate if we found a match or not.
}
I reused most of your code, and added a second pass to handle the actual delete (first pass searches for matching records).
void delete(struct blood *b,int n)
{
const int MOBILE_SIZE = 16;
char name[50];
int phone = 0;
int found=0;
int c=0;
FILE *fp = fopen("bloodrecord.txt", "r");
FILE *fp1 = fopen("temp.txt", "w");
printf("\nEnter Name: ");
scanf("%s", name);
printf("---------------------------------------------\n");
while(fread(&b[i],sizeof(struct blood),1,fp))
{
if(strcmpi(b[i].name,name)==0)
{
c=c+1;
printf("\nName: %s\n",b[i].name);
printf("Age: %d\n", b[i].age);
printf("Mobile no.: %d\n", b[i].phone);
printf("Blood group: %s\n", b[i].bg );
printf("Weight: %d\n", b[i].weight);
printf("Sex: %s\n",b[i].sex);
printf("Address: %s\n",b[i].add);
printf("\n");
found = 1;
}
}
/* Finished the first pass. Now, start again */
rewind(fp)
if (c > 1) {
printf("There are multiple records for the name %s\n", name);
printf("\nEnter Mobile Number: ");
scanf("%d", &phone);
}
while(fread(&b[i],sizeof(struct blood),1,fp))
{
if((c == 1 && strcmpi(b[i].name,name)==0)
|| (c > 1 && strcmpi(b[i].name,name) == 0 && b[i].mobile == mobile))
continue; /* skip this record */
}
else
fwrite(&b[i],sizeof(struct blood),1,fp1);
}
fclose(fp);
fclose(fp1);
if (found==1)
{
fp1 = fopen("temp.txt", "r");
fp = fopen("bloodrecord.txt", "w");
while(fread(&b[i],sizeof(struct blood),1,fp1))
{
fwrite(&b[i],sizeof(struct blood),1,fp);
}
fclose(fp);
fclose(fp1);
}
else
{
printf("\n\aRECORD DOES NOT EXIST.\n");
}
printf("RECORD SUCCESSFULLY DELETED");
getchar();
getchar();
}
I have tried several methods but none of them have worked.
I copied the txt file into the root file and it didn't open too. I have also tried to use the full path of the txt file. The same thing happened when I tried to use another IDE on another laptop.
Also the compiler isn't giving me any error.
Here is my code:
int main()
{
struct TreeNode *tmpDicNode;
struct LinkedList *tmpLinkedList;
FILE *infile;
infile = fopen("..//Synonyms.txt" ,"r");
char line[500];
while(fgets(line, 500, infile))
{
//if ( strlen(line)>0){
line[strlen(line) - 2] = '\0';
char * token = strtok(line, " -\n");
tmpDicNode = newTreeNode(token);
tmpLinkedList = newLinkedList();
while(token != NULL )
{
token = strtok(NULL, " , -\n");
if (token != NULL)
{
insertSynonym(tmpLinkedList, token);
}
}
tmpDicNode->synonyms = tmpLinkedList;
Root = insertWord(Root, tmpDicNode);
}
fclose(infile);
int ch = 0;
char userWord[30];
char userWord2[30];
while(ch!=8)
{
printf("\n=====================================\n");
printf("1. View The Dictionary.\n");
printf("2. test word existence.\n3. print synonyms of a word.\n");
printf("4. add a synonym to a word.\n5. get the biggest word with synonyms.\n");
printf("6. get all words of a synonym.\n");
printf("7. Save the dictionary to dict.txt file.\n");
printf("8. Exit.\n");
printf("=====================================\n");
printf("\nEnter Your Choice: ");
scanf("%d",&ch);
switch (ch)
{
case 1:
viewDictionary(Root);
break;
case 2:
printf("Enter word: ");
scanf("%s", userWord);
if (findWordNode(userWord)) printf("%s is present in the dict \n", userWord);
else printf("%s isn't found! \n", userWord);
break;
case 3:
printf("Enter word: ");
scanf("%s", userWord);
printLinkedlist(findWordNode(userWord)->synonyms);
break;
case 4:
printf("Enter word: ");
scanf("%s", userWord);
printf("Enter synonym: ");
scanf("%s", userWord2);
AddToWordSynonyms(userWord, userWord2);
break;
case 5:
printf("The word with the height no. of Synonyms is: %s", getMaxSynsWord(Root)->word);
break;
case 6:
printf("Enter a synonym: ");
scanf("%s", userWord);
getSyncWords(Root, userWord);
break;
case 7:
saveTheDictToFile(Root);
printf("The dictionary saved to others/dict.txt, Go and check it!\nGoodbye..!\n");
ch = 8;
break;
case 8:
printf("Goodbye..!\n");
break;
default:
printf("Please Enter a valid option number from 1 to 7\n");
}
}
return 0;
}
Let's address a couple of the issues here:
synonyms.txt
cold: cool,frigid,freezing
good: acceptable,virtuous
readsyn.c
/*
* readsyn.c
*
* SAMPLE OUTPUT:
* Current directory: C:\Users\paulsm\workspace-cdt\readsyn\Debug
* Opening file (..\synonyms.txt)
* Reading file (..\synonyms.txt)
* line=cold: cool,frigid,freezing
* ...
* Currently 4 words
* line=good: acceptable,virtuous...
* Currently 7 words
* Done: found 2 lines
* synonyms[0]:cold synonyms[1]:cool synonyms[2]:frigid synonyms[3]:freezing synonyms[4]:good synonyms[5]:acceptable synonyms[6]:virtuous
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define MAXWORDS 10
#define MAXLINE 80
#define TOKENS ":,"
#define FNAME "..\\synonyms.txt"
int main(int argc, char *argv[])
{
char synonyms[MAXWORDS][MAXLINE] = {0};
char current_folder[MAXLINE];
char line[MAXLINE], *token;
FILE *infile;
int nlines = 0, iword=0;
printf ("Current directory: %s\n", getcwd(current_folder, MAXLINE));
printf ("Opening file (%s)\n", FNAME);
if (!(infile = fopen(FNAME,"r"))) {
perror("File open failed");
return 1;
}
printf ("Reading file (%s)\n", FNAME);
while((fgets(line, MAXLINE, infile) != NULL) && (iword < MAXWORDS))
{
printf("line=%s...\n", line);
if (line[strlen(line)-1] == '\n')
line[strlen(line)-1] = 0;
token = strtok(line, TOKENS);
while (token != NULL) {
strncpy (synonyms[iword], token, MAXLINE);
token = strtok(NULL, TOKENS);
iword++;
}
printf("Currently %d words\n", iword);
nlines++;
}
fclose(infile);
printf ("Done: found %d lines\n", nlines);
for (int i=0; i < iword; i++)
printf ("synonyms[%d]:%s ", i, synonyms[i]);
return 0;
}
Main points:
ALWAYS check if an I/O operation like "fopen()" succeeded or failed.
You can use APIs like getcwd() (among others) to get your current working directory.
If — as in your example — you don't give an absolute path (like "C:\\temp\\f.txt" on Windows, or "/tmp/f.txt" on *nix) for your filename, then the path argument is interpreted relative to that current working directory of the application. In Visual Studio that is by default somewhere buried in the Debug directory of your project; in Linux it would be the current directory of your shell.
I create a program that prompts the user to choose an option, like below:
create a file and name the file.
add component in the file
display the item in the file
exit program
So my problem is the file is created and exists in my directory, but it is empty, so where did I miss something? plus can you check whether the 2 and 3 option program are OK?
Here my program:
#include <stdio.h>
#include <stdlib.h>
int main() {
int num, name;
start:
printf("\n1. Create a file.");
printf("\n2. Add a component to the list.");
printf("\n3. Display the current list of component.");
printf("\n4. Exit program.");
printf("\n\nChoose either these four menu = ");
scanf("%d", &num);
fflush(stdin);
switch (num) {
case 1:
printf("\n\nPlease enter file name: ");
scanf("%d", &name);
FILE *pf = NULL;
char username[250];
char userfile[255];
printf("username: ");
scanf("%s", username);
sprintf(userfile, "%s.txt", username);
fflush(stdin);
goto start;
break;
case 2:
pf = fopen(userfile, "w");
if (!pf) {
fprintf(stderr, "File opening failed!\n");
return EXIT_FAILURE;
}
struct date {
int day;
int month;
int year;
};
struct details {
char name[20];
int price;
int code;
int qty;
struct date mfg;
};
struct details item[50];
int n, i;
printf("Enter number of items:");
scanf("%d", &n);
fflush(stdin);
for (i = 0; i < n; i++) {
fflush(stdin);
printf("Item name: \n");
scanf("%s", item[i].name);
fflush(stdin);
printf("Item code: \n");
scanf("%d", &item[i].code);
fflush(stdin);
printf("Quantity: \n");
scanf("%d", &item[i].qty);
fflush(stdin);
printf("price: \n");
scanf("%d", &item[i].price);
fflush(stdin);
printf("Manufacturing date(dd-mm-yyyy): \n");
scanf("%d-%d-%d", &item[i].mfg.day,
&item[i].mfg.month, &item[i].mfg.year);
}
fclose(pf);
goto start;
break;
case 3:
pf = fopen(userfile, "r");
if (!userfile) {
fprintf(stderr, "File opening failed!\n");
return EXIT_FAILURE;
}
{
printf(" ***** INVENTORY ***** \n");
printf("------------------------------------------------------------------\n");
printf("S.N.| NAME | CODE | QUANTITY | PRICE | MFG.DATE \n");
printf("-------------------------------------------------------- ---------\n");
for (i = 0; i < n; i++)
fprintf("%d %-15s %-d %-5d %-5d %d/%d/%d \n",
i + 1, item[i].name, item[i].code, item[i].qty,
item[i].price, item[i].mfg.day, item[i].mfg.month,
item[i].mfg.year);
printf("------------------------------------------------------------------\n");
}
fclose(pf);
goto start;
break;
case 4:
printf("Exit Program, Thank You, Sayonara");
break;
}
return 0;
}
There are multiple problems in your code:
the test if (!userfile) is incorrect: you should test if (!pf) instead
you open the file for reading, you should open it for writing with "w", or possibly for appending with "a".
you never write to the file. You should use fprintf(pf, ...) instead of printf.
the arrays userfile, item and variables i and n are local inside the switch statement: their contents go out of scope when you go to the start label outside de switch statement. Move all these definitions outside the switch statement.
fflush(stdin); has undefined behavior. You can consume (flush) the rest of the input line with: int c; while ((c = getchar()) != EOF && c != '\n') continue; You can define a function flush() that does it.
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.
Please help me. This is my code so far. The delete record function is not working and can someone help the update record function with following conditions:
- Ask user to input player name.
- Ask user to input player score.
- Ask user to input player level.
- If the player name does not exist on the list, then show message “name of [player name] not found!”
Thanks a lot.
#include <stdio.h>
#include <string.h>
struct Player {
char name[50];
int score;
int level;
};
struct Player data[50];
FILE *ptr;
FILE *ptr2;
int fileSize()
{
int lSize;
int end;
ptr = fopen("text.txt", "r");
lSize = ftell (ptr);
fseek (ptr, 0, SEEK_END);
end = ftell (ptr);
fseek (ptr, lSize, SEEK_SET);
return end;
}
int getNoOfRecords()
{
return (fileSize()/(sizeof(struct Player)));
}
void deletePlayerRecord()
{
char name[50];
int counter=0, i=0;
ptr2 = fopen("text2.txt","a");
int records = getNoOfRecords();
ptr = fopen("text.txt","a+");
do {
printf("Input player name[1..10]: ");
scanf("%[^\n]s", name);
fflush(stdin);
} while (strlen(name)<1 || strlen(name)>10);
while(counter!=records)
{
fread(&data,sizeof(struct Player),1,ptr);
if(strcmp(data[i].name,name)==0)
{
}
else
{
fwrite(&data,sizeof(struct Player),1,ptr2);
}
counter++;
}
fclose(ptr);
fclose(ptr2);
remove("text.txt");
rename("text2.txt","text.txt");
printf("\n%s successfully deleted.\n\n", name);
printf("Press Enter to continue....\n\n");
getchar();
}
void updatePlayerRecord()
{
char name[50];
int counter=0, i=0;
int records = getNoOfRecords();
ptr = fopen("text.txt","a+");
do {
printf("Input player name[1..10]: ");
scanf("%[^\n]s", name);
fflush(stdin);
} while (strlen(name)<1 || strlen(name)>10);
if(counter!=records)
{
fread(&data,sizeof(struct Player),1,ptr);
if(strcmp(data[i].name,name)==0)
{
}
counter++;
}
printf("\nScore and Level successfully updated.\n\n");
printf("Press Enter to continue....\n\n");
getchar();
}
void addPlayerRecord(){
int i=0;
do {
printf("Input player name[1..10]: ");
scanf("%[^\n]s", data[i].name);
fflush(stdin);
} while (strlen(data[i].name)<1 || strlen(data[i].name)>10);
fflush(stdin);
getchar();
data[i].score=0;
data[i].level=0;
ptr = fopen("text.txt", "a");
printf("\n");
fprintf(ptr, "\r\n%s#%d#%d", data[i].name, data[i].score, data[i].level);
fclose(ptr);
printf("\nData successfully added.\n\n");
printf("Press Enter to continue....\n\n");
getchar();
}
void viewPlayerRecord(){
int i=0;
ptr = fopen("text.txt", "r");
printf("Player Name\t\t|Average Score\t|Number of Playing\n");
printf("=======================================================\n");
while(fscanf(ptr, "%[^#]#%d#%d\n", data[i].name, &data[i].score, &data[i].level)!=EOF)
{
printf("%s\t\t\t|%d\t\t\t\t|%d\n", data[i].name, data[i].score, data[i].level);
i++;
}
fclose(ptr);
}
int main() {
int choice;
do{
printf("Score Record Dota Player\n");
printf("========================\n");
printf("1. View Record\n");
printf("2. Update Player Record\n");
printf("3. Add New Player\n");
printf("4. Delete Player\n");
printf("5. Save and Exit\n\n");
do {
printf("Input your choice[1..5]: ");
scanf("%d", &choice);
fflush(stdin);
getchar();
} while (choice < 1 || choice > 5);
switch (choice) {
case 1:
viewPlayerRecord();
break;
case 2:
updatePlayerRecord();
break;
case 3:
addPlayerRecord();
break;
case 4:
deletePlayerRecord();
break;
}
} while(choice!=5);
return 0;
}
There are many issues with your code:
Every operation works on the database file. That may be a good design, but a more usual approach would be to load the database into memory on startup, i.e. to populate your data and then work on this. When exiting the program, you commit all changes to the database file. (Your option 5 is named "Save and exit", but is effectively a null operation. That name hints at the outlined approach.)
You should make up your mind whether your database is a binary file or a text file. You use fprintf and fscanf, which are used for text files, when you add and display records, but you use fwrite and fread, which are used for binary files, when you update and delete records. In my opinion, binary access is a bit easier, because you just have to store and retrieve chunks of a fixed size, namely sizeof(struct Player). Text files are more user-friendly, because they can be displayed and modified in a text editor, but they have to be parsed and require more advanced error handling.
Your fileSize() will only work with binary files, but at the moment you write only text files. It is usually better to use the return values of the file functions to determine whether reading or writig was successful.
When the database file doesn't exist, your view function will crash. Check for file existence and for the correct format.
At the moment, you use data only as scratch space. You osften access data[i], but i is zero throughout your code.
A corrected delete function that works is:
void deletePlayerRecord()
{
struct Player p;
char name[50];
int del = 0;
ptr2 = fopen("text2.txt", "w");
ptr = fopen("text.txt", "r");
do {
printf("Input player name[1..10]: ");
scanf("%[^\n]s", name);
fflush(stdin);
} while (strlen(name)<1 || strlen(name)>10);
while (fscanf(ptr, "%[^#]#%d#%d\n", p.name, &p.score, &p.level) == 3) {
if(strcmp(p.name, name) == 0) {
printf("\n%s successfully deleted.\n\n", name);
del++;
} else {
fprintf(ptr2, "%s#%d#%d\n", p.name, p.score, p.level);
}
}
fclose(ptr);
fclose(ptr2);
remove("text.txt");
rename("text2.txt", "text.txt");
printf("%d character(s) deleted\n\n", del);
}
This code still has many drawbacks:
The success of fopen is not checked.
The fscanf and fprintf formats have to be copied verbatim from the view and add record options. That's bad style. You should probably write readPlayer and writePlayer functions.
The same goes for the input code. Write front-end functions that do the error checking so that you don't have to repeat the whole code over and over again. This makes the code hard to read and also prone to errors.