Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I may need your help to solve this issue...
I'm learning about C and find a problem, how to properly read a binary file.
I have a struct array filled, then wrote on binary file and try to read it, but this isn't show nothing.
The code is in pastebin
My code
#include <stdio.h>
#include <ctype.h>
#include <math.h>
typedef struct {
int id;
char name[100];
char document[14];
float testGrade;
} Candidate;
typedef struct {
int id;
float testGrade;
} Grade;
FILE * openFile(char filename[100], char filemode[3]) {
FILE *p = fopen(filename, filemode);
if (!p) {
printf("Error to open %s file. \nThe program will be closed.",filename);
exit(1);
}
}
void addCandidate(int newId, int numbersOfNewCandidate, char candidateFilename[100], char gradeFilename[100]) {
int counter = 0;
float testGrade = 0;
Candidate*candidate;
candidate= malloc(sizeof(Candidate) * numbersOfNewCandidate);
Grade *grade;
grade= malloc(sizeof(Grade) * numbersOfNewCandidate);
for(;counter< numbersOfNewCandidate; counter++) {
system("#cls||clear");
printf("Adding #%d:",newId);
printf("\n---------------\n");
printf("\nName of candidate: ");
gets(&candidate[counter].name);
printf("\nDocument: ");
gets(&candidate[counter].document);
do {
printf("\nTest grade (between 0 and 10): ");
scanf("%f",&testGrade);
printf("\n---------------\n");
if (testGrade < 0 || testGrade > 10) {
printf("\nERROR!\nTest grade %.2f invalid, please try again with a grade between 0 and 10.\n",testGrade);
}
} while(testGrade < 0 || testGrade > 10);
candidate[counter].id = newId;
grade[counter].id = newId;
candidate[counter].testGrade = testGrade;
grade[counter].testGrate = testGrade;
newId++;
fflush(stdin);
}
FILE *candidateFile = openFile(candidateFilename, "a+b");
fwrite(candidate, sizeof(candidate),numbersOfNewCandidate, candidateFile );
FILE *gradeFile = openFile(gradeFilename, "a+b");
fwrite(grade, sizeof(grade),numbersOfNewCandidate, gradeFile );
fclose(candidateFile);
fclose(gradeFile);
free(candidate);
free(grade);
}
void showCandidate(int typeOfSearch, char valueToSearch[100]) {}
void listAllCandidates(char candid[100]) {
FILE *fp = openFile(candidateFilename, "rb");
//fseek(fp,0,SEEK_SET);
Candidate *candidate = NULL;
candidate = malloc(sizeof(Candidate) + 1);
while(fread(&candidate,sizeof(Candidate),1,fp) == 1) {
printf("\n\nId: %d \nName: %s \nDocument: %s \nGrade: %.2f",candidate->id,candidate->name,candidate->document, candidate->testGrade);
}
getche();
free(candidate);
}
void main(){
int lastId = 0;
char candidateFilename[100] = "candidates.bin";
char gradeFilename[100] = "classificationList.bin";
char option;
do {
system("#cls||clear");
printf("Menu: \n");
printf("1 - Add candidates \n");
// printf("2 - Search by name \n");
// printf("3 - Search by document \n");
// printf("---------------------------\n");
// printf("4 - Show Max Grade, Minimum, Avg \n");
printf("5 - List candidates \n");
printf("6 - Erase files \n");
printf("---------------------------\n");
printf("S - Exit \n");
printf("\n\n");
option = toupper(getche());
switch(option) {
case '1':
system("#cls||clear");
int numbersOfNewCandidate = 0;
int newId = 0;
printf("Home > Add candidates\n\n");
printf("Please give the number of new candidates: ");
scanf("%d",&numbersOfNewCandidate);
newId = lastId;
lastId += numbersOfNewCandidate;
fflush(stdin);
addCandidate(newId + 1, numbersOfNewCandidate, candidateFilename, gradeFilename);
printf("\n\nAdding new candidates: Finished \n");
break;
// case '2':
// printf("\noption %c#\n",option);
// break;
// case '3':
// printf("\noption %c#\n",option);
// break;
// case '4':
// printf("\noption %c?\n",option);
// break;
case '5':
listAllCandidates(candidateFilename);
break;
case '6':
remove(candidateFilename);
remove(gradeFilename);
printf("\nRemoved!!\n");
break;
case 'S':
printf("\noption %c, the program will be ended...\n",option);
break;
default:
printf("\nWrong option!!\n");
break;
}
} while (option != 'S');
}
Please, if you find other issues about my code, try to elucidate me about it..
I already tryed it too, but nothing yet.
while(!feof(fp)) {
fread(&candidate,sizeof(Candidate),1,fp);
printf("\n\nId: %d \nName: %s \nDocument: %s \nGrade: %.2f",candidate->id,candidate->name,candidate->document, candidate->testGrade);
}
Candidate *candidate = NULL;
candidate = malloc(sizeof(Candidate) + 1);
while(fread(&candidate,sizeof(Candidate),1,fp) == 1) {...}
free(candidate);
The first parameter in fread should be a pointer fread(void*,...), and candidate is already declared as a pointer, it should not have a reference operator. The correct usage is:
while(fread(candidate,sizeof(Candidate),1,fp) == 1) {...}
Note that there is no reference & operator in front of candidate
Sometime you see a reference operator, but that's a different case like this:
Candidate cand;
while(fread(&cand,sizeof(cand),1,fp) == 1) {...}
This is an easier method because cand does not need to be allocated with malloc and it does not need free
Unnecessary functions introduce more errors:
FILE * openFile(char filename[100], char filemode[3]) {
FILE *p = fopen(filename, filemode);
if (!p) {
printf("Error to open %s file. \nThe program will be closed.",filename);
exit(1);
}
}
This function is supposed to return a file pointer. Also function parameter can be simply written as const char* filename and const char *filemode. Example:
FILE * openFile(const char* filename, const char* filemode) {
FILE *p = fopen(filename, filemode);
if (!p) printf("Error to open %s file. \nThe program will be closed.",filename);
return p;
}
I would get rid of this function altogether because it's basically useless. Just use fopen. Make sure to close the handle with fclose when you are done.
grade[counter].testGrate = testGrade;
^
This is a typo, it should be grade[counter].testGrade. It is recommended to compile the program with warning level set to maximum, or at least set to level 4. The compiler will tell about about the typos, errors and warnings. You have to be able to compile the program with zero errors and zero warnings. Here is a simple version:
void listAllCandidates(char* candidateFilename)
{
FILE *fin = fopen(candidateFilename, "rb");
Candidate cand;
while(fread(&cand, sizeof(cand), 1, fin))
printf("%s, %s, %d, %f\n", cand.name, cand.document, cand.id, cand.testGrade);
fclose(fin);
}
int main()
{
char candidateFilename[] = "file.bin";
FILE *fout = fopen(candidateFilename, "ab");
Candidate cand;
strcpy(cand.name, "name1");
strcpy(cand.document, "document1");
cand.id = 1;
cand.testGrade = 1.1f;
fwrite(&cand, sizeof(cand), 1, fout);
strcpy(cand.name, "name2");
strcpy(cand.document, "document2");
cand.id = 2;
cand.testGrade = 2.2f;
fwrite(&cand, sizeof(cand), 1, fout);
fclose(fout);
listAllCandidates(candidateFilename);
printf("\n");
return 0;
}
Related
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.
This question already has answers here:
gets() does not work
(3 answers)
Why is gets() not consuming a full line of input?
(7 answers)
Closed 1 year ago.
I am trying to read students data (name, department, roll, sgpa, cgpa), I used fgets function to read name and department, but it skips to the department and can't read name.
here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[100];
char department[50];
int roll;
float sgpa[12];
float cgpa;
} Student;
void add(FILE *fp);
void modify(FILE *fp);
void display(FILE *fp);
FILE * del(FILE * fp);
int main(int argc, char **argv) {
int option;
FILE *fp;
fp = fopen("db.txt", "rb+");
if (fp == NULL) {
fp = fopen("db.txt", "wb+");
if (fp == NULL) {
printf("Can't open the database");
return 0;
}
}
printf("\t1. Add Student");
printf("\n\t2. Modify Student");
printf("\n\t3. Show All Student");
printf("\n\t4. Remove Student");
printf("\n\tEnter Your Option :--> ");
scanf("%d",&option);
switch(option)
{
case 1:
add(fp);
break;
case 2:
// modify(fp);
break;
case 3:
// display(fp);
break;
case 4:
// fp = del(fp);
break;
default:
printf("Unkonw option\n");
}
return 0;
}
void add(FILE *fp) {
Student std;
int i;
float cgpa;
fseek(fp,0,SEEK_END);
printf("\n\tEnter Full Name of Student: ");
fflush(stdin);
fgets(std.name,100,stdin);
std.name[strlen(std.name)-1]='\0';
printf("\n\tEnter Depertment Name: ");
fflush(stdin);
fgets(std.department,50,stdin);
std.department[strlen(std.department)-1]='\0';
printf("\n\tEnter Roll number: ");
scanf("%d",&std.roll);
printf("\n\tEnter SGPA for 12 semesters\n");
for(i=0,cgpa=0; i<12; i++)
{
scanf("%f",&std.sgpa[i]);
cgpa+=std.sgpa[i];
}
cgpa/=12.0;
std.cgpa=cgpa;
fwrite(&std,sizeof(std),1,fp);
}
Is there a way of limiting scanf in C?
I did this, if you're having that many problems with string input giving an eye on my other answer might help you
Here's a more specific answer to your problem on message you place what you wanna print before the input and StringInput you place the array you're using to hold the message
I hope this works since you also use a array for it
also i see this:
fp = fopen("db.txt", "rb+");
if (fp == NULL) {
fp = fopen("db.txt", "wb+");
if (fp == NULL) {
printf("Can't open the database");
return 0;
}
}
which may not be what you want because if it fails because of a sudden glitch by using wb+ you will overwrite it
“r+” – Searches file. Opens the file for both reading and writing. If opened successfully, fopen() loads it into memory and sets up a pointer which points to the first character in it. Returns NULL, if unable to open the file.
“w+” – Searches file. If the file exists, its contents are overwritten. If the file doesn’t exist, a new file is created. Returns NULL, if unable to open the file.
FUNCAUX_MAX_STRING is a macro and you define it like so:
#define FUNCAUX_MAX_STRING 100
This makes it so that the number or elements is 100 and you can easily change every number thats using the macro by simply changing the value once
void readString(char message[FUNCAUX_MAX_STRING], char StringInput[FUNCAUX_MAX_STRING], int maxChars)
{
int sizeString;
do // Repete leitura caso sejam obtidas strings vazias
{
printf("%s", message);
fgets(StringInput, maxChars, stdin);
sizeString = strlen(StringInput);
if (sizeString == 1)
{
printf("Nao foram introduzidos caracteres!!! . apenas carregou no ENTER \n\n");
}
}
while (sizeString == 1);
if(StringInput[sizeString-1] != '\n')
{
cleanBufferStdin();
}
else
{
StringInput[sizeString-1] = '\0';
}
}
void cleanBufferStdin(void)
{
char chr;
do
{
chr = getchar();
}
while (chr != '\n' && chr != EOF);
}
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.
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);
}
I have a program in which I am supposed to add in two functions that will read elements from an array and write them to a file, and to read from a file and put the information into the array.
Questions:
saveFile(char *fileName); The saveFile function will read each element in the array (the person directory) and save the data into a disk file.
loadFile(char *fileName); The loadFile function will read each item in the disk file and load it into the array (the person directory). The loadFile must generate exactly the same data structure and same data that the saveFile function reads.
Add necessary code to call the safeFile and loadFile functions in your program, including: Declare a global file name myDatabase; Call the saveFile(myDatabase) before existing the main function to save the data; Call the loadFile(myDatabase) at the beginning of the main function to load the data back into the array of person directory
So far this is what I have come up with:
void saveFile(char *fileName) {
FILE *fPointer;
fPointer = fopen(fileName, "w");
fprintf(fPointer, directory);
fclose(fPointer);
}
void loadFile(char *fileName) {
FILE *fPointer;
fPointer = fopen(fileName, "r");
while (!feof(fPointer)) {
fgets(directory, MAX, fPointer);
puts(directory);
fclose(fPointer);
}
}
I only have a basic understanding of reading and writing files. My program complies fine, but whenever I run it a file that should contain the values in the array is not created. If someone can explain how I could use my above code to properly implement it with the code that is given to me that would be great!
Here is the entire code:
/**
Course: CSE240
Instructor: Dr. Chen
Assignment Name: Homework 4 Solution
Solved by: Garrett Gutierrez 2/7/2015
**/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#pragma warning(disable: 4996)
#define MAX 100
// Changed: deploma to diploma.
typedef enum { diploma = 0, bachelor, master, doctor } education;
// A struct to hold attributes of a person
struct person {
char name[30];
char email[30];
int phone;
education degree;
};
/******************* Global Variable Section *******************/
struct person directory[MAX]; // an array of structures, 100 entries
int tail = 0; // global variable
/******************* Foward Declaration Section *******************/
void branching(char c);
int delete_person();
void flush();
int insertion();
int print_person(int i);
int print_all();
int search_person();
void shift_data(char* name, char* email, int phone, education educationLevel);
int main()
{
// Print a menu for selection
char ch = 'i';
ungetc('\n', stdin); // Inject the newline character into input buffer
do {
printf("Enter your selection\n");
printf("\ti: insert a new entry\n");
printf("\td: delete an entry\n");
printf("\ts: search an entry\n");
printf("\tp: print all entries\n");
printf("\tq: quit \n");
flush(); // Flush the input buffer. To be discussed later
ch = tolower(getchar()); // Convert any uppercase char to lowercase.
branching(ch);
} while (ch != 113); // 113 is 'q' in ASCII
return 0;
};
// Flush the input buffer. To be discussed later
void flush()
{
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
};
// Branch to different tasks: insert a person, search for a person, delete a person
// print all added persons.
void branching(char c)
{
switch (c) {
case 'i':
insertion();
break;
case 's':
search_person();
break;
case 'd':
delete_person();
break;
case 'p':
print_all();
break;
case 'q':
break;
default:
printf("Invalid input\n");
}
};
// Inserts the person lexigraphically. Note: A < a so all capital letters will be ordered first.
int insertion()
{
education educationLevel = 0;
char name[MAX], email[MAX];
int i = 0, phone;
// Case 1: The structure is filled.
if (tail == MAX) {
printf("There are no more places to insert.\n");
return -1;
}
// Case 2: The structure still has unfilled slots.
else
{
printf("Enter the name:\n");
scanf("%s", name);
printf("Enter the phone number:\n");
scanf("%d", &phone, sizeof(directory[tail].phone));
printf("Enter the e-mail:.\n");
scanf("%s", email);
//********** Question 1 ************
do {
printf("Enter the degree: select 0 for diploma, select 1 for bachelor, select 2 for master, or select 3 for doctor:\n");
scanf("%d", &educationLevel);
if (educationLevel < diploma || educationLevel > doctor)
{
printf("Please enter a value from 0 to 3.\n");
}
} while (educationLevel < diploma || educationLevel > doctor);
//**********************************************
//********* Question 2 ************
shift_data(name, email, phone, educationLevel);
//*****************************************
tail++;
printf("The number of entries = %d\n", tail);
}
return 0;
};
// Print the name, e-mail, phone, and education level of one person in the directory
int print_person(int i)
{
printf("\n\nname = %s\n", directory[i].name);
printf("email = %s\n", directory[i].email);
printf("phone = %d\n", directory[i].phone);
//************ Question 1 ******************
switch (directory[i].degree)
{
case diploma:
printf("degree = diploma\n");
break;
case bachelor:
printf("degree = bachelor\n");
break;
case master:
printf("degree = master\n");
break;
case doctor:
printf("degree = doctor\n");
break;
default:
printf("System Error: degree information corruption.\n");
break;
}
//****************************************
return 0;
}
// Print the name, e-mail, phone, and education level of each person in the directory
int print_all()
{
int i;
//Case 1: The structure is empty
if (tail == 0)
{
printf("No entries found.");
}
// Case 2: The structure has at least one item in it
else
{
for (i = 0; i < tail; i++) {
print_person(i);
}
printf("\n");
}
return 0;
};
//********** Question 3 **************
//Find a person by comparing names.
int search_person()
{
char sname[30];
int i = 0;
struct person* iterator = directory;
printf("Please enter the name to be searched for:\n");
scanf("%s", sname); //sname is an array, no & needed
while (i < tail)
{
if (strcmp(sname, iterator->name) == 0)
{
print_person(i);
return i;
}
iterator++;
i++;
}
printf("The name does not exist.\n");
return -1;
};
//***************************************
// Delete a person after finding that person via their name.
int delete_person()
{
int i, k;
k = search_person();
// Case 1: The person is not in the directory
if (k == -1)
{
printf("The name does not exist.\n");
return -1;
}
// Case 2: The person was found in the directory
else {
for (i = k; i<tail; i++)
{
strcpy(directory[i].name, directory[i + 1].name);
directory[i].phone = directory[i + 1].phone;
strcpy(directory[i].email, directory[i + 1].email);
printf("The index deleted is: %d\n", k);
}
tail--;
return k;
}
};
void shift_data(char* name, char* email, int phone, education educationLevel)
{
int i = 0, j = 0;
// Case 1: Empty List
if (tail == 0)
{
strcpy(directory[tail].name, name);
strcpy(directory[tail].email, email);
directory[tail].phone = phone;
directory[tail].degree = educationLevel;
return;
}
while (i < tail)
{
// Case 2: Beginning or middle of list
if (strcmp(name, directory[i].name) < 0)
{
j = tail;
while (j > i)
{
strcpy(directory[j].name, directory[j - 1].name);
strcpy(directory[j].email, directory[j - 1].email);
directory[j].phone = directory[j - 1].phone;
directory[j].degree = directory[j - 1].degree;
j--;
}
strcpy(directory[i].name, name);
strcpy(directory[i].email, email);
directory[i].phone = phone;
directory[i].degree = educationLevel;
return;
}
i++;
}
// Case 3: End of list
strcpy(directory[tail].name, name);
strcpy(directory[tail].email, email);
directory[tail].phone = phone;
directory[tail].degree = educationLevel;
};
void saveFile(char *fileName) {
FILE *fPointer;
fPointer = fopen(fileName, "w");
fprintf(fPointer, directory);
fclose(fPointer);
}
void loadFile(char *fileName) {
FILE *fPointer;
fPointer = fopen(fileName, "r");
while (!feof(fPointer)) {
fgets(directory, MAX, fPointer);
puts(directory);
fclose(fPointer);
}
}
fprintf is not the correct function to be calling to output structures to a file, and you're using it wrongly anyway.
It requires a format string after the file handle which decides how the items in the rest of the call will be formatted.
The function you want is fwrite (and fread to get them back). These read and write the underlying data in full.
For example, to write the entire directory structure array, you would use something like:
size_t written = fwrite (directory, sizeof (directory), 1, fPointer);
if (written != 1) puts ("Something went horribly wrong");
And reading it back is pretty much the same except using fread instead of fwrite.
That's probably the easiest approach but, since it reads and writes the entire array, it's not really the most efficient in terms of space taken on disk. You could do it piecemeal, one record at a time but that introduces code complexity and is probably not really necessary for a 100-element array.
If you opt for storing the entire array regardless, you'll probably want to save away tail as well so you can remember how many items in the array are in use:
size_t written = fwrite (&tail, sizeof (tail), 1, fPointer);
if (written != 1) puts ("Something went horribly wrong");
void loadFile(char *myDatabase)
{
FILE *fileBuffer = fopen(myDatabase, "rb");
if (fileBuffer != NULL)
{
fread(&tail, sizeof(tail), 1, fileBuffer);
for (int i = 0; i < tail; i++)
{
fread(directory[i].name, sizeof(directory[i].name), 1, fileBuffer);
fread(&directory[i].phone, sizeof(&directory[i].phone), 1, fileBuffer);
fread(directory[i].email, sizeof(directory[i].email), 1, fileBuffer);
fread(&directory[i].degree, sizeof(&directory[i].degree), 1, fileBuffer);
}
fclose(fileBuffer);
}
This is what I have for the same code..