Compare date read form file with input date - c

i'm having serious problems with a project in C language. I've created a function that takes in input some data about an entry in a sport center, but now i've to modify this function so that this function:
asks in input the last name who's entering
by last name inserted, it must go to the file of registrations, search and read the last date of registration for that last name.
Once found, save this date somewhere and compare it with the expiration date of membership for the member with that last name. If the entry date is less or equal to the expiration date, must allow the inserting of data, otherwise, terminate the program with a message like this: "Your membership has expired".
My difficulties are in the point 2 and 3 of this request. Can someone please help me, i'm in serious trouble
I post the basic code on which i've to do this:
void add_entry()
Date_entry de;
Entry e;
Entry eTemp;
FILE *fEnt; //file corso
FILE *fInd; //file indice del corso
printf("Number: ");
scanf("%d", &e.number);
printf("Name: ");
scanf("%s", &e.name);
printf("Surname: ");
scanf("%s", &e.surname);
printf("Date (DD/MM/YYYY): ");
scanf("%d/%d/%d", &de.day3, &de.month3, &de.year3);
printf("Entry time(HH:MM): ");
scanf("%s", &e.entry_time);
printf("Exit time(HH:MM): ");
scanf("%s", &e.exit_time);
e.deleted = 0;
int cont = 0;
fEnt = fopen(EntryOpen,"r+b");
fread(&eTemp,sizeof(Entry),1,fEnt);
while(eTemp.deleted != 1)
{
fread(&eTemp,sizeof(Entrance),1,fEnt);
cont++;
}
int posInEntry = cont;
fseek(fEnt,cont * sizeof(Entrance),0);
fwrite(&e,sizeof(Entrance),1,fEnt);
fclose(fEnt);
Index x;
Index xTemp;
strcpy(x.key,e.surname);
x.value = e.number;
fInd = fopen(indexOpen,"r+b");
cont = 0;
fread(&xTemp,sizeof(Index),1,fInd);
while(strcmp(xTemp.key,"EMPTY") != 0)
{
fread(&xTemp,sizeof(Index),1,fInd);
cont++;
}
fseek(fInd,cont * sizeof(Index),0);
fwrite(&x,sizeof(Index),1,fInd);
fclose(fInd);
IndexCode y;
IndexCode yTemp;
y.kye = e.number;
y.value = posInEntry;
fInd = fopen(indexCodeOpen,"r+b");
cont = 0;
fread(&yTemp,sizeof(IndexCode),1,fInd);
while(yTemp.key != -1)
{
fread(&yTemp,sizeof(IndexCode),1,fInd);
cont++;
}
fseek(fInd,cont * sizeof(IndexCode),0);
fwrite(&y,sizeof(IndexCode),1,fInd);
fclose(fInd);
IndexCode ind[max];
fInd = fopen(indexCodeOpen,"rb");
int i;
for(i = 0; i < max; i++)
{
fread(&ind[i],sizeof(IndexCode),1,fInd);
}
fclose(fInd);
OrderIndexCode(ind,max);
fInd = fopen(indexCodeOpen,"wb");
for(i = 0; i < max; i++)
{
fwrite(&ind[i],sizeof(IndexCode),1,fInd);
}
fclose(fInd);
printf("Index Update completed.\n");

Related

How can I search array of names in an element of an array

I have this task/function to determine if student's name/complete name already exist in the record.
No student's name should be the same in every input/entry. also no duplicate of entry in record.
The Error of my code:
Is that when I input 5 student names (e.g : A,B,C,D,E) then and search for D the return value will be not found. So I wonder what would be the correct logic for it to search every element if it exist? And when I tried A it says "Already Exist".
#include<stdio.h>
#include<string.h>
int main(){
char studentNames[50][50],names[50][50];
int i,studentcount;
printf("\nEnter number of students: ");
scanf("%d",&studentcount);
for(int i=0; i<studentcount; i++){
printf("\n[Student %d of %d]\n",i+1,studentcount);
printf("Enter name of student %d: \n",i+1);
scanf("%s", studentNames[i]);
}//this is the student record initialize.
/*assumed this is a function where it holds the data name to be searched
e.g
names[i]= "spiderman" then in studentNames[i]="venom",studentNames[i]="harley",studentNames[i]="octopops",
if i loop will it function like this?
the names[i]=spiderman compare to studentnames[i]=venom then if not equal iterate to harley and so on.
That's what I really want to do with my searching but I really dont know how to do it because of my poor logic thinking.
*/
for(int i=0; i<studentcount; i++){
printf("\nEnter Student's Name to be search: ");
scanf("%s",names[i]);
if (strcmp(studentNames[i],names[i]) == 0)
{
printf("Already exist.\n");
return 0;
}
printf("Not found\n");
return 1;
}
}
You probably want something like this:
char CompareStudent() {
printf("\nEnter Student's Name to be search: ");
char searchedname[100];
scanf("%99s", searchedname); // %99s instead of %s prevents buffer overflow
// (not very important at your level)
for (int i = 0; i < studentCount; i++) {
if (strcmp(studentNames[i], searchedname) == 0) {
printf("Already exists.\n");
return 0;
}
}
printf("Not found\n");
return 1;
}
This is your original bogous code with comments:
char CompareStudent() {
printf("\nEnter Student's Name to be search: ");
for (int i = 0; i < studentCount; i++) {
scanf("%s", names[i]); // 1
if (strcmp(studentNames[i], names[i]) == 0)
{
printf("Already exist.\n");
return 0;
}
printf("Not found\n"); // 2
return 1;
}
}
Problems:
You need to ask to input the student to search only once, not each time in the loop
This part must be outside the loop. In your code, we return inconditionally 1 if the student is not in the first element of the array.

My variables changing after moving to the next function

I have a problem in my homework that i cannot seem to solve, The task it to create some sort of tool for a city to handle families information, after I add a family successfuly in the function "add_new_family" and move to "add_new_child" while working with the debugger i've noticed that just by moving up to first or second line of the function my original structure variables are changing randomly, the paretns name changes to garbage and if i move on with the function and actually try to add another child, it saves the information on the parents name and such, i cant seem to figure out the cause of this problem.
Please excuse my memory allocation casting if it bothers anyone, I've read before in stackoverflow that it might not be necessary but my professor insist.
There might be other crucial problems with my code, im a first year student, although it would be appreciated if you note it, but my main focus is just figuring out the cause of those random changes after I send my struct to the "add_new_child" function, I add an image of before and after to make clear of whats happening picture
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#define SIZE 10000;
typedef struct person {
char* name;
int gender;//1-female, 0-male
}Person;
typedef struct {
char* family_name;
Person* mother, *father; // parents' names
Person* *children_list;// list of the children in this family
unsigned child_list_size; // size of child_list array
unsigned current_listChild_size;
}Family;
typedef struct {
Family** list;
unsigned current_listFamily_size; // current size of family
}ListFamilys;
ListFamilys* new_city(ListFamilys* s);
void add_new_family(ListFamilys* s, char* fname);
void add_new_child(ListFamilys* s, char* surname);
void main()
{
ListFamilys* list = (ListFamilys*)malloc(1 * sizeof(ListFamilys));
assert(list);
list = new_city(list);
add_new_family(list, "james");
add_new_child(list, "james");
system("pause");
}
ListFamilys* new_city(ListFamilys* s)
{
assert(s->list = (Family**)calloc(1, sizeof(Family*)));
s->current_listFamily_size = 0;
return s;
}
void add_new_family(ListFamilys* s, char* fname)
{
unsigned int size = SIZE;
if (s->current_listFamily_size >= size)
{
printf("\nAccording to our database, it will not be possible to add another family in Angola, as the city reached its capacity");
return;
}
for (unsigned int i = 0; i < s->current_listFamily_size; i++)
{
if (strcmp(s->list[i]->family_name, fname) == 0)
{
printf("\nERROR 1: A family with the surname of %s already exist in the database", fname);
return;
}
}
s->current_listFamily_size += 1;
/*assert(s = (ListFamilys*)realloc(s, s->current_listFamily_size * sizeof(ListFamilys)));
assert(s->list = (Family**)calloc(1 , sizeof(Family*)));*/
assert(s->list[s->current_listFamily_size - 1] = (Family*)calloc(1, sizeof(Family)));
assert(s->list[s->current_listFamily_size - 1]->father = (Person*)malloc(1 * sizeof(Person)));
assert(s->list[s->current_listFamily_size - 1]->mother = (Person*)calloc(1, sizeof(Person)));
int numOfParents = 0;
printf("Creating new data for the [%s] family, please provide the number of parents (1/2): ", fname);
scanf("%d", &numOfParents);
s->list[s->current_listFamily_size - 1]->family_name = fname;
char tmpname[100];
char tmpname1[100];
int tmpgender = 0;
int tmpgender1 = 0;
switch (numOfParents)
{
case 0:
printf("\nERROR 2: A newly created family cannot contain no parents at all or more than 2 parents, please try again.");
return;
case 1:
printf("\nPlease provide the name of the parent No.1: ");
scanf("%s", tmpname);
printf("\nPlease provide the gender of parent No.1 [1 for female / 0 for male]: ");
scanf("%d", &tmpgender);
if (tmpgender == 0)
{
s->list[s->current_listFamily_size - 1]->father->gender = tmpgender;
s->list[s->current_listFamily_size - 1]->father->name = tmpname;
s->list[s->current_listFamily_size - 1]->mother = NULL;
}
else
{
s->list[s->current_listFamily_size - 1]->mother->gender = tmpgender;
s->list[s->current_listFamily_size - 1]->mother->name = tmpname;
s->list[s->current_listFamily_size - 1]->father = NULL;
}
break;
case 2:
printf("\nPlease provide the name of the parent No.1:");
scanf(" %s", tmpname);
printf("\nPlease provide the gender of parent No.1 [1 for female / 0 for male]: ");
scanf("%d", &tmpgender);
printf("\nPlease provide the name of the parent No.2:");
scanf(" %s", tmpname1);
printf("\nPlease provide the gender of parent No.2 [1 for female / 0 for male]: ");
scanf("%d", &tmpgender1);
if (tmpgender == 0)
{
s->list[s->current_listFamily_size - 1]->father->gender = tmpgender;
s->list[s->current_listFamily_size - 1]->father->name = tmpname;
s->list[s->current_listFamily_size - 1]->mother->gender = tmpgender1;
s->list[s->current_listFamily_size - 1]->mother->name = tmpname1;
}
else
{
s->list[s->current_listFamily_size - 1]->mother->gender = tmpgender;
s->list[s->current_listFamily_size - 1]->mother->name = tmpname;
s->list[s->current_listFamily_size - 1]->father->gender = tmpgender1;
s->list[s->current_listFamily_size - 1]->father->name = tmpname1;
}
break;
default:
printf("\nERROR 2: A newly created family cannot contain no parents at all or more than 2 parents, please try again.");
return;
}
int numOfChildren = 0;
printf("\nPlease provide the number of children in the [%s] family: ", fname);
scanf("%d", &numOfChildren);
if (numOfChildren == 0)
{
s->list[s->current_listFamily_size - 1]->children_list = NULL;
s->list[s->current_listFamily_size - 1]->child_list_size = 0;
s->list[s->current_listFamily_size - 1]->current_listChild_size = 0;
}
else
{
assert(s->list[s->current_listFamily_size - 1]->children_list = (Person**)malloc((numOfChildren + 2) * sizeof(Person*)));
s->list[s->current_listFamily_size - 1]->child_list_size = numOfChildren + 2;
for (int i = 0; i < numOfChildren; i++)
{
char tmpname2[100];
tmpgender = 0;
printf("\nPlease provide the name of the child No.%d:", i+1);
scanf(" %s", tmpname2);
printf("\nPlease provide the gender of child No.%d [1 for female / 0 for male]: ", i+1);
scanf("%d", &tmpgender);
assert(s->list[s->current_listFamily_size - 1]->children_list[i] = (Person*)malloc(1 * sizeof(Person)));
s->list[s->current_listFamily_size - 1]->children_list[i]->gender = tmpgender;
s->list[s->current_listFamily_size - 1]->children_list[i]->name = tmpname2;
}
for (int i = 0; i < 2; i++)
{
s->list[s->current_listFamily_size - 1]->children_list[numOfChildren + i] = NULL;
}
s->list[s->current_listFamily_size - 1]->current_listChild_size = numOfChildren;
}
printf("\nFamily was added to the database SUCCESSFULY.");
return;
}
void add_new_child(ListFamilys* s, char* surname)
{
int truth = 0;
unsigned int index = 0;
for (unsigned int i = 0; i < s->current_listFamily_size; i++)
{
if (strcmp(s->list[i]->family_name , surname) == 0)
{
index = i;
truth = 1;
}
}
if (truth == 0)
{
printf("\nERROR 3: Family wasnt found in the database, try again");
return;
}
char tmpname4[100];
int gender = 0;
if (s->list[index]->current_listChild_size < s->list[index]->child_list_size)
{
printf("\nPlease provide the name of the child: ");
scanf(" %s", tmpname4);
printf("\nPlease provide the gender of child [1 for female / 0 for male]: ");
scanf("%d", &gender);
assert(s->list[index]->children_list[s->list[index]->current_listChild_size] = (Person*)malloc(1 * sizeof(Person)));
s->list[index]->children_list[s->list[index]->current_listChild_size]->gender = gender;
s->list[index]->children_list[s->list[index]->current_listChild_size]->name = tmpname4;
}
else
{
s->list[index]->child_list_size += 1;
s->list[index]->current_listChild_size += 1;
assert(s->list[index]->children_list = (Person**)malloc(1 * sizeof(Person*)));
printf("\nPlease provide the name of the child: ");
scanf(" %s", tmpname4);
printf("\nPlease provide the gender of child [1 for female / 0 for male]: ");
scanf("%d", &gender);
s->list[index]->children_list[s->list[index]->current_listChild_size] = (Person*)malloc(1 * sizeof(Person));
s->list[index]->children_list[s->list[index]->current_listChild_size]->gender = gender;
s->list[index]->children_list[s->list[index]->current_listChild_size]->name = tmpname4;
}
printf("\nChildren information was updated SUCCESSFULY");
return;
}
You're setting the name member to a pointer to a local variable, which becomes invalid when the function returns. You need to make a dynamic copy of the string.
s->list[s->current_listFamily_size - 1]->father->name = strdup(tmpname);
The same thing for the family name, mother's name and all the children names.
As already pointed out in another answer, your string handling is full of bugs as you save pointers to variables instead actually creating a string copy (i.e. strcpy).
Another issue is s->list. It seems you want it to be a pointer to an array of pointers because you access it like: s->list[s->current_listFamily_size - 1]->...
But you never allocate more than one pointer. Here:
s->list = (Family**)calloc(1, sizeof(Family*))
In other words - the only valid index is zero.
s->list[0]->... // Is OK
s->list[1]->... // Is very bad
You need to add more pointers when you add a Family

Sort an array based on variable upon insertion

I have been writing a small program for a library database of book structures. An array is malloc allocated and initialized with 0's in each indexes ibsn long variable and a menu is prompted allowing choices. Upon adding a book it is placed into the first available position in the array (first position where the ISBN number is !=0).
My question is how can I add a book to the array whereby it places it sorted by the isbn number first checking if there is space in array?
Example: Book with ISBN 1234 entered into array; Second book added with ISBN 123 and is placed at first index moving the previous book to the next index.
void addbook(book_t* lib, int size)
{
int i;
//// Loop through the array until you find an empty element
for (i = 0; i < size; i++) {
/// Found an empty element
if ((lib + i)->isbn == 0) {
//// Ask for and store the book details
printf("Please enter the book name\n");
scanf("%s", (lib + i)->name);
printf("Please enter the book author\n");
scanf("%s", (lib + i)->author);
printf("Please enter the book number\n");
scanf("%ld", &(lib + i)->isbn);
printf("Please enter the book price\n");
scanf("%lf", &(lib + i)->price);
printf("We will now ask you for the release date of the book by day then month then year");
printf("\nPlease enter release date for this book (dd):"); //user able to change default
scanf("%d", &(lib + i)->releaseDate.date);
printf("\nPlease enter release month for this book (mm):"); //user able to change default
scanf("%d", &(lib + i)->releaseDate.month);
printf("\nPlease enter release year for this book (yyyy):"); //user able to change default
scanf("%d", &(lib + i)->releaseDate.year);
printf("\nDate entered is (%d / %d / %d)", (lib + i)->releaseDate.date, (lib + i)->releaseDate.month, (lib + i)->releaseDate.year); //user able to change default
/// Set i to size so that the loop finished
i = size;
}
//// If no empty element found and at the last element of the array
/// then library is not found
else if (i == size - 1)
{
printf("The array is full\n");
}
}
}
I have employed a similar method when deleting a book whereby if the book searched is found it is moved to the last space in the array and has its variables set to 0.
void deleteBook(book_t *lib, int size) {
int i, j, location = 0;
long searchISBN;
int found = 0;
printf("Enter ISBN to search\n");
scanf("%ld", &searchISBN);
for (i = 0; i < size; i++) {
if ((lib + i)->isbn == searchISBN) {
found++;
printf("Book Name %s\n", (lib + i)->name);
printf("Book Author %s\n", (lib + i)->author);
printf("Book ISBN %ld\n", (lib + i)->isbn);
printf("Book Price %lf\n", (lib + i)->price);
location = i;
i = size;
} else
if (i == size - 1) {
location++;
}//add to location and try again
}
if (found == 1) {
for (j = location; j < size; j++) {
strcpy(lib->name, (lib + j)->name);
strcpy(lib->author, (lib + j)->author);
(lib)->isbn = (lib + j)->isbn;
(lib)->price = (lib + j)->price; //user able to change default
(lib)->releaseDate.date = (lib + j)->releaseDate.date;
(lib)->releaseDate.month = (lib + j)->releaseDate.month;
(lib)->releaseDate.year = (lib + j)->releaseDate.year;
}//end swapping of elements
strcpy(lib->name, "0");
strcpy(lib->author, "0");
(lib)->isbn = 0;
(lib)->price = 0;
(lib)->releaseDate.date = 0;
(lib)->releaseDate.month = 0;
(lib)->releaseDate.year = 0;
} else {
printf("not found");
}
}//end deleteBook method
Your function deleteBook does not work correctly: it copies the fields of all entries after the found one over the first entry in the array. You should just copy the remaining entries as a block with memmove(). Use memmove() as opposed to memcpy() because the source and destination memory areas overlap.
Here is a corrected version:
#include <stdio.h>
#include <string.h>
void deleteBook(book_t *lib, int size) {
long searchISBN;
int found = 0;
printf("Enter ISBN to search\n");
if (scanf("%ld", &searchISBN) != 1)
return;
for (int i = 0; i < size;) {
if (lib[i].isbn == searchISBN) {
book_t book = { 0 }; // empty book record
found++;
// display book data before erasing it
printf("Book Name %s\n", lib[i].name);
printf("Book Author %s\n", lib[i].author);
printf("Book ISBN %ld\n", lib[i].isbn);
printf("Book Price %lf\n", lib[i].price);
// copy the remainder elements one position to the left
memmove(lib + i, lib + i + 1, sizeof(*lib) * (size - i - 1))
// reinitialize the last entry
memcpy(lib + size - 1, &book, sizeof(*lib));
// rescan the current entry in case of duplicates
// hence do not increment i
} else {
i++; // test the next entry
}
}
if (found == 0) {
printf("not found");
}
}
You can use a similar technique to insert a new entry at the appropriate position in the table:
void addbook(book_t *lib, int size) {
book_t book = { 0 }; // empty book record
int i, used;
// Loop through the array and pack empty elements
for (i = used = 0; i < size; i++) {
if (lib[i].isbn != 0) {
if (used < i) {
memcpy(lib + used, lib + i, sizeof(*lib));
}
used++;
}
}
// reset unused elements:
for (i = used; i < size; i++) {
if (lib[i].isbn != 0) {
memcpy(lib + i, &book, sizeof(*lib));
}
}
// check if the array is full:
if (used >= size) {
printf("The array is full\n");
return;
}
// Ask for and store the book details to local book structure
printf("Please enter the book name\n");
if (scanf("%s", book.name) != 1)
return;
printf("Please enter the book author\n");
if (scanf("%s", book.author) != 1)
return;
printf("Please enter the book number\n");
if (scanf("%ld", &book.isbn) != 1)
return;
printf("Please enter the book price\n");
if (scanf("%lf", &book.price) != 1)
return;
printf("We will now ask you for the release date of the book by day then month then year");
printf("\nPlease enter release date for this book (dd):");
if (scanf("%d", &book.releaseDate.date) != 1)
return;
printf("\nPlease enter release month for this book (mm):");
if (scanf("%d", &book.releaseDate.month) != 1)
return;
printf("\nPlease enter release year for this book (yyyy):");
if (scanf("%d", &book.releaseDate.year) != 1)
return;
printf("\nDate entered is (%d / %d / %d)",
book.releaseDate.date, book.releaseDate.month, book.releaseDate.year);
//// Loop through the array until you find location to insert book
for (i = 0; i < used; i++) {
if (lib[i].isbn > book.isbn)
break;
}
// book should be inserted at position i
// shift book with larger ISBNs
memmove(lib + i + 1, lib + i, sizeof(*lib) * (used - i));
used++;
// copy book into the array
memcpy(lib + i, &book, sizeof(*lib));
}
For production code, you would need to handle the scanf errors appropriately.
These insertion and deletion methods are not very efficient because on average half the database is copied for every operation. A more efficient implementation would use linked lists to avoid copying the data and make it easier to handle a variable number of books.

Copying variables for an array to another array with the array being a struct with chars

First off Ill show you how I'm defining struct StudentRecord
typedef struct{
char SN[10];
char lname[20];
float GPA;
}StudentRecord;
Now the point of this is to read in information from a .dat file which this program does successfully but when I go to save the array that I have made (more on this below) it give me a very weird output this code has a 2 global variables
StudentRecord* studentRecordList;
int studentRecordSize;
the studentRecordSize is going to be the first input line from the file, the function for reading the files looks like the following.
void load_records(){
FILE* student_file = fopen("StudentRecordFile.dat", "r");
if(student_file == 0){
perror("cannot open StudentRecordFile.dat in load_records");
}
//free existing student list
if(studentRecordList != 0){
free(studentRecordList);
}
//get number of students in the list
fscanf(student_file, "%d",&studentRecordSize);
//create and load new student list
studentRecordList = (StudentRecord*)malloc(studentRecordSize * sizeof(StudentRecord));
int i;
for(i = 0; i < studentRecordSize;i++){
fscanf(student_file,"%s %s %s %f", studentRecordList[i].SN,studentRecordList[i].fname,studentRecordList[i].lname,&studentRecordList[i].GPA);
}
fclose(student_file);
}
Now from the driver you are given 4 options to 0-exit(also saves to the file), 1-find(just a search through the array), 2-add(add another student to the array), 3-modify, 4-delete.
the function for adding a student to the array is where I'm getting my problem for some reason it is messing up my output file and changing all my GPA variables to 0.000000 and leaving random blank spaces throughout the document. Anyway here is what it looks like.
void add_record(){
char fname[20];
char lname[20];
char SN[10];
float GPA;
printf("Enter the Students first Name: ");
scanf("%s", &fname);
printf("\nEnter the Students last Name: ");
scanf("%s", &lname);
printf("\nEnter the Students number: ");
scanf("%s", &SN);
printf("\nEnter the Students GPA: ");
scanf("%f", &GPA);
StudentRecord* tempList;
tempList = (StudentRecord*)malloc(studentRecordSize * sizeof(StudentRecord));
int i;
studentRecordSize = studentRecordSize+1;
for(i = 0; i < studentRecordSize -1; i ++){
tempList[i].GPA = studentRecordList[i].GPA;
strncpy(tempList[i].SN, studentRecordList[i].SN,10);
strncpy(tempList[i].fname, studentRecordList[i].fname,20);
strncpy(tempList[i].lname , studentRecordList[i].lname,20);
}
printf("%f", &tempList[i].GPA );
free(studentRecordList);
studentRecordList = (StudentRecord*)malloc(studentRecordSize * sizeof(StudentRecord));
for(i=0; i < studentRecordSize; i ++){
//adds the new student at the end of the array.
if(i == studentRecordSize){
strncpy(*studentRecordList[i].fname, &fname,20);
strncpy(*studentRecordList[i].lname, &lname,20);
studentRecordList[i].GPA = GPA;
strncpy(*studentRecordList[i].SN, &SN,10);
}
strncpy(studentRecordList[i].fname, tempList[i].fname,20);
strncpy(studentRecordList[i].lname , tempList[i].lname,20);
studentRecordList[i].GPA = tempList[i].GPA;
strncpy(studentRecordList[i].SN , tempList[i].SN,10);
}
free(tempList);
}
Also if your curious here is what my save_records function looks like otherwise ignore.
void save_records(){
FILE* student_file = fopen("StudentRecordFile.dat", "w");
if(student_file == 0){
perror("cannot open StudentRecordFile.dat in load_records");
}
fprintf(student_file,"%d\n",studentRecordSize);
int i;
for(i = 0; i < studentRecordSize; i++){
fprintf(student_file,"%s\n%s\n%s\n%f\n", studentRecordList[i].SN, studentRecordList[i].fname, studentRecordList[i].lname, &studentRecordList[i].GPA);
}
}
If you need anything else let me know and ill be sure to add it, thanks.
Please try this:
in save_records() open your file binary
fopen(student_file , "wb");
then use fwrite to write the record
fwrite( &studentRecordList[i] , sizeof( studentRecordList) , 1 , student_file );
It is also easier, if you can, to write the number of records to a separate file that you open text.
This code has some problems:
for(i=0; i < studentRecordSize; i ++){
//adds the new student at the end of the array.
if(i == studentRecordSize){ // <- This can never be TRUE !!!
strncpy(*studentRecordList[i].fname, &fname,20); // Wrong
strncpy(*studentRecordList[i].lname, &lname,20);
studentRecordList[i].GPA = GPA;
strncpy(*studentRecordList[i].SN, &SN,10);
}
// Should the code below be an else ?
// If not you'll access outside tempList
strncpy(studentRecordList[i].fname, tempList[i].fname,20);
strncpy(studentRecordList[i].lname , tempList[i].lname,20);
studentRecordList[i].GPA = tempList[i].GPA;
strncpy(studentRecordList[i].SN , tempList[i].SN,10);
}
Maybe you wanted to do:
for(i=0; i < studentRecordSize; i ++){
if(i == (studentRecordSize-1)){
// Add the new record
strncpy(studentRecordList[i].fname, fname,20);
strncpy(studentRecordList[i].lname, lname,20);
studentRecordList[i].GPA = GPA;
strncpy(studentRecordList[i].SN, SN,10);
}
else
{
// Copy from the temp list
strncpy(studentRecordList[i].fname, tempList[i].fname,20);
strncpy(studentRecordList[i].lname , tempList[i].lname,20);
studentRecordList[i].GPA = tempList[i].GPA;
strncpy(studentRecordList[i].SN , tempList[i].SN,10);
}
}
A more simple version of the add function could be:
void add_record(){
char fname[20];
char lname[20];
char SN[10];
float GPA;
printf("Enter the Students first Name: ");
scanf("%s", &fname);
printf("\nEnter the Students last Name: ");
scanf("%s", &lname);
printf("\nEnter the Students number: ");
scanf("%s", &SN);
printf("\nEnter the Students GPA: ");
scanf("%f", &GPA);
StudentRecord* tempList;
tempList = (StudentRecord*)malloc(studentRecordSize * sizeof(StudentRecord));
int i;
for(i = 0; i < studentRecordSize; i ++){
tempList = studentRecordList[i];
}
free(studentRecordList);
studentRecordSize = studentRecordSize+1;
studentRecordList = (StudentRecord*)malloc(studentRecordSize * sizeof(StudentRecord));
for(i=0; i < (studentRecordSize-1); i ++){
studentRecordList[i] = tempList[i];
}
free(tempList);
// Add the new record
strncpy(studentRecordList[(studentRecordSize-1)].fname, fname,20);
strncpy(studentRecordList[(studentRecordSize-1)].lname, lname,20);
studentRecordList[(studentRecordSize-1)].GPA = GPA;
strncpy(studentRecordList[(studentRecordSize-1)].SN, SN,10);
}

C - Alphabetically sorting arrays error

I'm working on a phone book assignment for my CECS class and I ran into a problem with alphabetically sorting the contacts. The program will allow me to sort up to 3 contacts, however when I try to sort more than 3, the program starts spitting out garbage variables and possibly crashing.
void Sort(phone *phonebook, int *num_entries)
{
int tracker = *num_entries;
if (tracker >= 0)
{
phone *temp = (phone*) calloc(tracker, sizeof(phone));
if (temp== NULL)
printf("\n\nOut of memory\n\n");
else
{
int i, j;
for (i = 0; i < tracker; i++)
{
for (j = i+1; j < tracker; j++)
{
//Combines first and last names into 1 name for easy comparison
strcpy(phonebook[i].totalname, phonebook[i].fName);
strcpy(phonebook[j].totalname, phonebook[j].fName);
strcat(phonebook[i].totalname, phonebook[i].lName);
strcat(phonebook[j].totalname, phonebook[j].lName);
printf("\nTotal name = %s\nTotal name = %s", phonebook[i].totalname, phonebook[j].totalname); //Done so I can verify it worked correctly
if (strcmp(phonebook[i].totalname, phonebook[j].totalname) > 0)
{
strcpy(temp[i].fName, phonebook[i].fName);
strcpy(temp[i].lName, phonebook[i].lName);
temp[i].number = phonebook[i].number;
temp[i].area = phonebook[i].area;
strcpy(phonebook[i].fName, phonebook[j].fName);
strcpy(phonebook[i].lName, phonebook[j].lName);
phonebook[i].number = phonebook[j].number;
phonebook[i].area = phonebook[j].area;
strcpy(phonebook[j].fName, temp[i].fName);
strcpy(phonebook[j].lName, temp[i].lName);
phonebook[j].number = temp[i].number;
phonebook[j].area = temp[i].area;
}
}
}
printf("\n\nSuccessfully sorted!\n\n");
}
}
else
printf("\n\nYou need people in the phone book before you can sort it.\n\n");
}
-------------------------
typedef struct PhoneBook
{
char fName[20];
char lName[20];
char totalname[40];
float number;
int area;
} phone;
Edited to add the structure. And I don't use qsort because we haven't learned about it in class and the TA's are rather strict about not using stuff we haven't learned.
void Add(phone *phonebook, int *num_entries)
{
int tracker = *num_entries;
if (tracker == 0)
{
printf("\n\nSomething's wrong here\n\n");
}
else
{
const int newSize = tracker + 1;
phone *temp = (phone*) realloc(phonebook, (newSize * sizeof(phone)));
if (temp!=NULL)
{
phonebook = temp;
}
else
phonebook = NULL;
}
if (phonebook == NULL)
printf("\n\nOut of memory, can't add more to your phonebook\n\n");
else
{
printf("\n\nEnter the first name: ");
scanf("%s", phonebook[tracker].fName);
printf("\nPlease enter the last name: ");
scanf("%s", phonebook[tracker].lName);
printf("\nPlease enter the area code: ");
scanf("%d", &phonebook[tracker].area);
printf("\nPlease enter the phone number (no dashes allowed): ");
scanf("%f", &phonebook[tracker].number);
*num_entries += 1;
printf("\nContact Added.\n\n");
}
}
Edited again to show the code to add people to the phone book (also broken). After 3-4 entries, it starts placing garbage values for entries.
int main()
{
int userInput = 8; //means exit
int num_entries = 1;
phone *phonebook = (phone*) calloc(1 , sizeof(phone));
if (phonebook == NULL)
printf("\n\nOut of memory\n\n");
else
{
do
{
system("cls");
printf("Menu: \n");
printf("1) Add a Contact\n");
printf("2) Delete a Contact\n");
printf("3) Display Phone Book\n");
printf("4) Alphabetically Sort\n");
printf("5) Find a Contact\n");
printf("6) Random Contact\n");
printf("7) Delete All\n");
printf("8) Exit\n\n");
scanf(" %d", &userInput);
switch (userInput)
{
case 1: //Add a Friend
Add(phonebook, &num_entries);
break;
case 2: //Delete a Friend
Delete(phonebook, &num_entries);
break;
case 3: //List all contacts
Display(phonebook, &num_entries);
break;
case 4:
Sort(phonebook, &num_entries);
break;
case 5:
Find(phonebook, &num_entries);
break;
case 6:
Random(phonebook, &num_entries);
break;
case 7:
DeleteAll(phonebook, &num_entries);
break;
case 8:
free(phonebook);
break;
}
system("PAUSE");
}while(userInput != 8);
}
return 0;
}
Edited to show the calls for each function
Well I can't post photos without more reputation so here's the links:
Photo 1 - Adding 3 contacts works fine: http://s980.photobucket.com/user/valondon/media/C%20Realloc%20Errors/Erroronerealloc_zpsc8228131.png.html?sort=3&o=0
Photo 2 - The phone book after the fourth contact was added: http://s980.photobucket.com/user/valondon/media/C%20Realloc%20Errors/Errorthreerealloc_zps246b76e3.png.html?sort=3&o=2
Problem is with the outer loop.
If you have say 'n' entries in the array to sort, then you have to compare the first entry of the array with remaining 'n-1' entries. After first entry is compared with all 'n-1' entries that means first entry is properly located at its location in sorted array. Now you have left with 'n-1' entries to sort. Now if you want to compare 2nd entry of the array then you have to compare that 2nd entry with remaining 'n-1-1' (only 'n-1' entries left to sort and you have taken 2nd entry to compare with rest of the entries). this goes on till the end.
In your code you can change the code like below (the loop part):
Note: I have created a temp variable of temp of structure phone.
phone temp;
for (i = 0; i < tracker - 1; i++)
{
for (j = i+1; j <= tracker - 1; j++)
{
//Combines first and last names into 1 name for easy comparison
strcpy(phonebook[i].totalname, phonebook[i].fName);
strcpy(phonebook[j].totalname, phonebook[j].fName);
strcat(phonebook[i].totalname, phonebook[i].lName);
strcat(phonebook[j].totalname, phonebook[j].lName);
printf("\nTotal name = %s\nTotal name = %s", phonebook[i].totalname, phonebook[j].totalname); //Done so I can verify it worked correctly
if (strcmp(phonebook[i].totalname, phonebook[j].totalname) > 0)
{
strcpy(temp.fName, phonebook[i].fName);
strcpy(temp.lName, phonebook[i].lName);
temp.number = phonebook[i].number;
temp.area = phonebook[i].area;
strcpy(phonebook[i].fName, phonebook[j].fName);
strcpy(phonebook[i].lName, phonebook[j].lName);
phonebook[i].number = phonebook[j].number;
phonebook[i].area = phonebook[j].area;
strcpy(phonebook[j].fName, temp.fName);
strcpy(phonebook[j].lName, temp.lName);
phonebook[j].number = temp.number;
phonebook[j].area = temp.area;
}
}
}
printf("\n\nSuccessfully sorted!\n\n");
}
The problem is with your for loops.
In your example, j is equal to i+1 in the second loop. i has a maximum value of tracker - 1, so j can be equal to tracker. This will cause you to overshoot the array, which can trash memory.
Try changing them to:
for (i = 0; i < tracker - 1; i++)
{
for (j = 0; j < tracker - i - 1; j++)
The other issue is that in your inner loop, you are using [i] and [j] to index your swaps. If you change every [i] in that loop to [j+1], you'll have a working bubble sort.
Your inner loop ends up as:
phone temp; /* I created a stack variable called temp - saves the need for allocation */
for (i = 0; i < tracker - 1; i++)
{
for (j = 0; j < tracker - i - 1; j++)
{
//Combines first and last names into 1 name for easy comparison
strcpy(phonebook[j+1].totalname, phonebook[j+1].fName);
strcpy(phonebook[j].totalname, phonebook[j].fName);
strcat(phonebook[j+1].totalname, phonebook[j+1].lName);
strcat(phonebook[j].totalname, phonebook[j].lName);
printf("\nTotal name = %s\nTotal name = %s", phonebook[j+1].totalname, phonebook[j].totalname); //Done so I can verify it worked correctly
if (strcmp(phonebook[j+1].totalname, phonebook[j].totalname) > 0)
{
strcpy(temp.fName, phonebook[j+1].fName);
strcpy(temp.lName, phonebook[j+1].lName);
temp.number = phonebook[j+1].number;
temp.area = phonebook[j+1].area;
strcpy(phonebook[j+1].fName, phonebook[j].fName);
strcpy(phonebook[j+1].lName, phonebook[j].lName);
phonebook[j+1].number = phonebook[j].number;
phonebook[j+1].area = phonebook[j].area;
strcpy(phonebook[j].fName, temp.fName);
strcpy(phonebook[j].lName, temp.lName);
phonebook[j].number = temp.number;
phonebook[j].area = temp.area;
}
}
}

Resources