I have this program that is supposed to handle assigning seats to passengers.
I cannot figure out what is causing my seg fault. I am using an array of structs and that may be where the problem is coming from.
I think its probably a problem with dereferencing some struct members, but I can't find where.
Here is my code:
struct seat
{
// Max Name of 32 chars
char name[32];
// Seat Number
int sNum;
// Seat taken = 1, open = 0
int taken;
};
// Function headers
void seat(struct seat plane[][10]);
void mani(struct seat plane[][10]);
void pass(int seat, char name[], int class);
int main()
{
// My airline plane is 6 seats per row, 10 rows
// Row 1/2 are First Class
// Row 3/4 are Business Class
// Init counter variables to keep track of the number
// of First Class/Business seats already taken
// also the user input var
int input, ticketin, class1 = 0, class2 = 0, class3=0, sNum, i;
char namein[32];
// Vars for pass function
char passname[32];
int passclass;
int passseat;
// Init a 2d array 6 colums 10 rows
struct seat plane[6][10];
for (i=0; i<sizeof(plane); i++)
{
plane[i]->sNum = i+1;
plane[i]->taken = 0;
}
// Begin user input loop
// Menu with 3 options:
// Display the seating chart, indicating taken seats
// Display the manifest
// Display a boarding pass - seat number, name, class
do
{
do
{
// Prompt user for ticket selection
printf("Please type 1 for \"First Class\"\n");
printf("Please type 2 for \"Business Class\"\n");
printf("Please type 3 for \"Economy Class\"\n");
scanf(" %d", &ticketin);
// Check for valid input
if (ticketin == 1)
{
// Check to make sure first class is not full
if (class1 < 12)
{
class1 += 1;
printf("First class is open!\n");
} else {
printf("First class is full, please choose another class\n");
}
} else if (ticketin == 2)
{
// Check to make sure business class is not full
if (class2 < 12)
{
class2 += 1;
printf("Business class is open!\n");
} else {
printf("Business class is full, please choose another class\n");
if (class1 < 12)
{
printf("Upgrade to First Class by entering 1");
}
}
} else if (ticketin == 3)
{
// Check to make sure business class is not full
if (class3 < 12)
{
class3 += 1;
printf("Economy class is open!\n");
} else
{
printf("Economy class is full, please choose another class\n");
if (class1 < 12)
{
printf("Upgrade to First Class by entering 1");
}
if (class2 < 12)
{
printf("Upgrade to Business Class by entering 2");
}
}
} else
{
ticketin = 4;
}
// Prompt the user for their name
printf("Please input your name:\n");
scanf(" %s", namein);
} while (ticketin == 4);
// Handle loading the new passenger into plane array
switch (ticketin)
{
case 1:
for (i=0; i<12; i)
{
if (plane[i]->taken == 0)
{
plane[i]->taken = 1;
strcpy(plane[i]->name, namein);
sNum = plane[i]->sNum;
} else
{
i++;
}
}
case 2:
for (i=12; i<24; i)
{
if (plane[i]->taken == 0)
{
plane[i]->taken = 1;
strcpy(plane[i]->name, namein);
sNum = plane[i]->sNum;
} else
{
i++;
}
}
case 3:
for (i=24; i<60; i)
{
if (plane[i]->taken == 0)
{
plane[i]->taken = 1;
strcpy(plane[i]->name, namein);
sNum = plane[i]->sNum;
} else
{
i++;
}
}
}
printf("Menu Options: \n");
printf("(1) Display the seating chart\n");
printf("(2) Display the passenger manifest\n");
printf("(3) Display a boarding pass\n");
printf("(4) Quit\n");
// Prompt user for their selection
printf("Please enter your menu selection:\n");
scanf(" %d", &input);
// Switch case handling function calls
switch (input)
{
case 1:
seat(plane);
break;
case 2:
mani(plane);
break;
case 3:
printf("Please input a seat number\n");
scanf(" %d", &passseat);
if (passseat < 12)
{
passclass = 1;
} else if (passseat < 24)
{
passclass = 2;
} else
{
passclass = 3;
}
pass(passseat, plane[passseat-1]->name, passclass);
break;
default:
printf("invalid menu option or quitting\n");
break;
}
} while (input != 4);
}
// Display seating chart function
void seat(struct seat plane[][10])
{
int i, sNum;
for (i=0; i<sizeof(plane); i++)
{
if (plane[i]->taken == 1)
{
printf("Seat %d is taken\n", i++);
} else
{
printf("Seat %d is not taken\n", i++);
}
}
}
// Display Manifest function
void mani(struct seat plane[][10])
{
int i;
for (i=0; i<sizeof(plane); i++)
{
if (plane[i]->taken == 1)
{
printf("Passenger %s in seat %d\n", plane[i]->name, i++);
}
}
}
// Display boarding pass function
void pass(int seat, char name[], int class)
{
printf("Boarding pass for %s\n", name);
printf("Seat Number: %d\n", seat);
switch (class)
{
case 1:
printf("First Class");
break;
case 2:
printf("Business Class");
break;
case 3:
printf("Economy Class");
break;
}
}
There are probably other errors, but this is the most obvious one:
for (i=0; i<sizeof(plane); i++)
{
plane[i]->sNum = i+1;
plane[i]->taken = 0;
}
sizeof(plane) is the number of bytes in the plane array. This is 10 * 6 * sizeof(struct seat), so you're writing way outside the array. If you want to know the number of elements in an array, you have to divide the size of the array by the size of an array element:
for (i=0; i<sizeof(plane)/sizeof(*plane); i++)
{
plane[i]->sNum = i+1;
plane[i]->taken = 0;
}
But your code is only initializing the first element in each row of the array.
Since it's a 2-dimensional array, you need nested loops. And you should use normal member access with . rather than pointer indirection.
for (i=0; i<sizeof(plane)/sizeof(plane[0]); i++)
{
for (int j = 0; j < sizeof(plane[i])/sizeof(plane[i][0]); j++)
{
plane[i][j].sNum = i+1;
plane[i][j].taken = 0;
}
}
You could simplify all the sizeof stuff by defining macros:
#define ROWS 6
#define COLS 10
and then using these macros in the array declaration and the for loop limits.
Similar changes need to be made in other code that loops over the plane array.
Related
This is the code that I have. Currently the code prints out all the seats at once. I need it to print one seat and then restart to the user prompt. it can not assign the same seat and should show first class full when there are no more seats.
int main(int argc, char** argv) {
int firstClass[] = {1, 2, 3, 4}; //first class array
int firstLen = 4; // first class length
int userInput;
int i;
//user prompt
printf("Please type 1 for First Class\n");
printf("Please type 2 for Economy\n");
printf("Please type 0 to Quit\n");
printf("\n");
scanf("%d", &userInput); // scanning for user input
if(userInput = 1){
for(i = 0; i < 4; i++){
if(i < firstLen){
printf("Class: First Seat Number: %d\n", firstClass[i]);
}
else{
printf("First Class Full. Next flight is tomorrow.");
}
}
}
}
You can track which seats are taken with a variable. Each time a user selects 1 print out the seat number for that index, and then increment the index.
You'll then wrap this in a loop (for or while) and only exit the loop when the user enters 0. Make sure you define the variable used to track the current index outside of the loop.
Something like this:
int main(void)
{
const int first_class[] = {1, 2, 3, 4};
const size_t first_class_size = sizeof(first_class) / sizeof(first_class[0]);
size_t first_class_index = 0;
int user_input = 0;
do
{
print_menu();
scanf("%d", &user_input);
if (user_input == 1)
{
if (first_class_index < first_class_size)
{
printf("Here is your ticket information:\n");
printf("Seat Number: %d, Class: First\n\n", first_class[first_class_index++]);
continue;
}
printf("No first class seats are available.\n\n");
}
} while(user_input != 0);
}
I was resolving an example I see in a book about C programming. This particular problem I saw in this book was about matching a kind of 'customer code'(integer) which was okay for me. But I have troubles applying the same logic for a two dimensional string where I want to prove my login.
This is from the book, which goes fine.
/*
This program searches a sorted list of customer IDs in order to get credit totals
*/
#include <stdio.h>
int main()
{
int ctr; // Loop counter
int idSearch; // Customer to look for (the key)
int found = 0; // 1 (true) if customer is found
/* Defines the 10 elements in each of the parallel arrays */
int custID[10] = {313, 453, 502, 101, 892, 475, 792, 912, 343, 633};
float custBal[10]={0.00, 45.43, 71.23, 301.56, 9.08, 192.41, 389.00, 229.67, 18.31, 59.54};
int tempID, inner, outer, didSwap, i; // For sorting
float tempBal;
// First, sort the arrays by customer ID
for (outer=0; outer<9; outer++)
{
didSwap=0; // Becomes 1 (true) if list is not yet ordered
for (inner=outer; inner<10; inner++)
{
if (custID[inner] < custID[outer])
{
tempID = custID[inner]; // Must switch both arrays of they
tempBal = custBal[inner]; // are no longer linked
custID[inner] = custID[outer];
custBal[inner] = custBal[outer];
custID[outer] = tempID;
custBal[outer]=tempBal;
didSwap = 1; // True because a swap took place
}
}
if (didSwap == 0)
{
break;
}
}
/* Interact with the user looking to find a balance */
printf("\n\n*** Customer Balance Lookup ***\n");
printf("What is the customer number? ");
scanf(" %d", &idSearch);
// Now, look for the ID in the array
for (ctr=0; ctr<10; ctr++)
{
if (idSearch == custID[ctr]) // Do they match?
{
found = 1; // Yes, match flag is set to TRUE
break; // No need to keep looping
}
if (custID[ctr] >idSearch) // No need to keep searching
{
break;
}
}
// Once the loop has completed, the ID was either found
// (found = 1) of not
if (found)
{
if (custBal[ctr]>100)
{
printf("\n** That customer's balance is $%.2f.\n", custBal[ctr]);
printf("No additional credit.\n");
}
else // Balance is less than $100.00
{
printf("\n**The customer's credit is good!\n");
}
}
else // The ID was not found
{
printf("** You have entered an incorrect customer ID.");
printf("\n ID %3d was not found in the list.\n", idSearch);
}
return(0);
}
This is what I tried to create in order to do a login.
#include <stdio.h>
#include <string.h>
int main()
{
int ctr; // Loop counter
char userSearch[20], passSearch[10]; // to look for (the key)
int found = 0; // 1 (true) if it is found
/* Defines the 5 elements in each of the parallel arrays */
char user[5][20] = {"John", "Ivan", "Paul", "Robert", "Leo"};
char pass[5][10]={"1111", "2222", "3333", "4444", "5555"};
int inner, outer, didSwap, i; // For sorting
char tempUser, tempPass;
for (outer=0; outer<4; outer++)
{
didSwap=0; // Becomes 1 (true) if list is not yet ordered
for (inner=outer; inner<5; inner++)
{
if (user[inner] != user[outer])
{
strcpy(tempUser, user[inner]);
strcpy(tempPass, pass[inner]);
strcpy(user[inner], user[outer]);
strcpy(pass[inner], pass[outer]);
strcpy(user[outer], tempUser);
strcpy(pass[outer], tempPass);
didSwap = 1;
}
}
if (didSwap == 0)
{
break;
}
}
printf("User: ");
scanf(" %s", userSearch);
printf("Password: ");
scanf(" %s", passSearch);
for (ctr=0; ctr<5; ctr++)
{
if ((strcmp(userSearch, user[ctr])==0) && (strcmp(passSearch, pass[ctr])==0)) // Do they match?
{
found = 1;
break;
}
}
if (found)
{
printf("You entered sucessfully.");
}
else
{
printf("** You have entered an incorrect data.");
printf("\n %s was not found.\n", userSearch);
}
return(0);
}
What exactly is wrong with my last code? How can I get to make a proper login with two-dimensional string arrays? I want to put like 100 users for example, and pointing each user is not an option so I thought this way would be a good idea, with this algorithm. But not sure what is my mistake.
I'm new to programming so I'm trying to write a small program were I can show car information but also add cars to my "library"
right now my out come for 1.Show cars looks like this:
ID BRAND PICS
bbb188 BMW 1 2 3
AAA-999 VOLVO 4 5 6
CCC-999 CITROEN 1 2 3
but after I add a new car the PICS does not show.
so if I would add AAA-111 VOLVO 1. this is the outcome:
bbb188 BMW 1 2 3
AAA-999 VOLVO 4 5 6
CCC-999 CITROEN 1 2 3
AAA-111 VOLVO -398253632 3 3
I just get random numbers for pics and always 3 values.
Could anyone help me with this, and please show me how to do it instead.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX 1000
#define IDSIZE 20
#define BRANDSIZE 50
#define PICSIZE 10
typedef struct{
char id[IDSIZE+1];
char brand[BRANDSIZE+1];
int *pic;
} Car;
void printCar(Car *pCar,int imagecount)
{
printf(" %s ",pCar->id);
printf(" %s ",pCar->brand);
for(int i=0; i<imagecount; i++){
printf(" %d",pCar->pic[i]);
}
printf("\n");
}
Car initCar(char itsId[],char itsBrand[],int *itsPic, int imagecount)
{
Car newCar;
strcpy(newCar.id, itsId);
strcpy(newCar.brand, itsBrand);
newCar.pic = itsPic;
return newCar;
}
void PrintList(Car aLista[],int imagecount, int carcount)
{
for(int i = 0; i<imagecount; i++)
printCar(&aLista[i],carcount);
}
void AddCar(Car aList[], int *pAt, Car theCar)
{
aList[(*pAt)++]=theCar;
}
Car NewCar(Car minapatienter[], int patientCount)
{
Car newCar;
gets(newCar.id);
printf("type in ID \n");
gets(newCar.id);
printf("type in brand\n");
gets(newCar.brand);
bool imageInputDone = false;
int imageCount=0;
while(imageInputDone == false)
{
printf("type in image reference \n");
int newImage;
scanf("%d",&newImage);
newCar.pic = &newImage;
imageCount++;
printf("vill du \n1.Add another image reference \n2.exit\n");
int input;
scanf("%d", &input);
printf("input: %i\n",input);
switch(input)
{
case 1:
printf("Adding one more image\n");
break;
case 2:
printf("Leaving loop\n");
imageInputDone = true;
break;
default:
while (input<1 || input<2)
;
printf("Input correct number\n");
break;
}
return newCar;
}
}
int main(void)
{
int carCount=0;
int imagecount=0;
Car myCar[MAX];
int input;
int test[3]={1,2,3};
int test2[3]={4,5,6};
myCar[0]= initCar("bbb188","BMW", test, 3);
myCar[1] = initCar("AAA-999","VOLVO", test2, 3);
myCar[2] = initCar("CCC-999", "CITROEN", test,3);
carCount=3;
imagecount=3;
do {
printf("1. Show cars \n2. Add car \n");
scanf("%d",&input);
switch(input)
{
case 1:
printf("ID BRAND PICS \n");
PrintList(myCar,carCount, imagecount);
break;
case 2:
AddCar(myCar,&carCount,NewCar(myCar,carCount));
printf("ID BRAND PICS \n");
PrintList(myCar,carCount, imagecount);
} //break;
} while (input < '1'|| input < '2');
return 0;
}
Your NewCar function have some problems. The newImage is in stack memory. When you do assignment newCar.pic = &newImage; the newCar.pic will point to undefined memory region because newImage was out of its scope. better way, we just use its value only, don't use address operator here. And one more thing, the newCar.pic is an pointer (array of int). So you need to allocate it before use. When you add more image item, you need to reallocate it. And initialize the pic to NULL pointer as well.
Here is my modification your NewCar function:
Car NewCar(Car minapatienter[], int patientCount)
{
Car newCar;
gets(newCar.id);
printf("type in ID \n");
gets(newCar.id);
printf("type in brand\n");
gets(newCar.brand);
newCar.pic = NULL;
bool imageInputDone = false;
int imageCount=0;
while(imageInputDone == false)
{
printf("type in image reference \n");
int newImage;
scanf("%d",&newImage);
// Rellocation
newCar.pic = realloc(newCar.pic, (imageCount+1)*sizeof(int));
newCar.pic[imageCount] = newImage;
imageCount++;
printf("vill du \n1.Add another image reference \n2.exit\n");
int input;
scanf("%d", &input);
printf("input: %i\n",input);
switch(input)
{
case 1:
printf("Adding one more image\n");
break;
case 2:
printf("Leaving loop\n");
imageInputDone = true;
break;
default:
while (input<1 || input<2)
;
printf("Input correct number\n");
break;
}
return newCar;
}
}
You get the same number of images printed for each car because you only have a global counter. You need a counter per image:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX 1000
#define IDSIZE 20
#define BRANDSIZE 50
#define PICSIZE 10
typedef struct Car
{
char id[IDSIZE+1];
char brand[BRANDSIZE+1];
int *pic;
int imagecount;
} Car;
With this change there is no need to pass a count for printing:
void printCar(Car *pCar)
{
printf(" %s ", pCar->id);
printf(" %s ", pCar->brand);
for(int i=0; i<pCar->imagecount; i++)
{
printf(" %d",pCar->pic[i]);
}
printf("\n");
}
The counter needs to be stored during initialization:
Car initCar(char itsId[], char itsBrand[], int *itsPic, int imagecount)
{
Car newCar;
strcpy(newCar.id, itsId);
strcpy(newCar.brand, itsBrand);
newCar.pic = itsPic;
newCar.imagecount = imagecount;
return newCar;
}
When you print your list, you mix up count of images and count of cars:
void PrintList(Car aLista[], int imagecount, int carcount)
{
for(int i = 0; i<imagecount; i++)
printCar(&aLista[i],carcount);
}
This must be:
void PrintList(Car aLista[], int carcount)
{
for (int i = 0; i < carcount; i++)
printCar(&aLista[i]);
}
Adding the car to your array is basically OK, but you might check if you reach MAX cars.
void AddCar(Car aList[], int *pAt, Car theCar)
{
aList[(*pAt)++]=theCar;
}
Now the biggest problem. This function hads issues with memory usage and weird loops.
Car NewCar(void)
{
Car newCar = {0}; // initialze with empty strings and NULL pointers.
// TODO: Replace gets with fgets!
// gets(newCar.id); // WHY read before you prompt??
printf("type in ID \n");
gets(newCar.id);
printf("type in brand\n");
gets(newCar.brand);
bool imageInputDone = false;
int imageCount=0;
while(imageInputDone == false)
{
printf("type in image reference \n");
int newImage;
scanf("%d",&newImage);
imageCount++;
int *newpics = realloc(newCar.pic, (imageCount) * sizeof(int));
newpics[imageCount-1] = newImage;
newCar.pic = newpics;
// TODO: Check for NULL
printf("vill du \n1.Add another image reference \n2.exit\n");
int input;
scanf("%d", &input);
printf("input: %i\n",input);
while (input < 1 || input > 2)
switch(input)
{
case 1:
printf("Adding one more image\n");
break;
case 2:
printf("Leaving loop\n");
imageInputDone = true;
break;
default:
printf("Input correct number\n");
break;
}
newCar.imagecount = imageCount;
return newCar;
}
}
And finally...
int main(void)
{
int carCount=0;
Car myCar[MAX];
int input;
int test[3] = {1,2,3};
int test2[3] = {4,5,6};
myCar[0] = initCar("bbb188", "BMW", test, 3);
myCar[1] = initCar("AAA-999", "VOLVO", test2, 3);
myCar[2] = initCar("CCC-999", "CITROEN", test, 3);
carCount=3;
do
{
printf("1. Show cars \n2. Add car \n");
scanf("%d", &input);
switch(input)
{
case 1:
printf("ID BRAND PICS \n");
PrintList(myCar, carCount);
break;
case 2:
AddCar(myCar, &carCount, NewCar());
printf("ID BRAND PICS \n");
PrintList(myCar, carCount);
} //break;
} while (input < 1 || input > 2); // compare as integers, not characters. Don't use < operator
return 0;
}
The code is not tested. Remaining errors are left for exercise. ;)
I'm writing this program in c where I need to re-prompt the user after an invalid input. I came to a solution only to discover that if the user enters another invalid input after the re-prompt then it continues. Can someone please show me a better solution to this? I'll show you what I had anyway:
#include <stdio.h>
#include <ctype.h>
main()
{
int ctr; // loop counter
int custID[10] = {1, 3, 5, 9, 10, // ID array
6, 4, 7, 8, 2};
double custBal[10] = {153.56, 1300.45, 684.45, 990.45, 45.54, // Balance array
1100.34, 594.45, 1340.45, 1000.00, 1134.00};
int IDsearch; // For interaction
int found = 0; // Search criteria
int inner, outer, tempID, didSwap; // For sorting the arrays
double tempBal;
char ans;
/* Firs step: Sort the arrays for efficiency */
for(outer = 0; outer < 9; outer++) // <9 and not <10, because 9 numbers will be bubble sorted
{ // the highest (10th) will remain at the bottom
didSwap = 0; // Turns one after the arrays sort
for(inner = outer; inner < 10; inner++)
{
if(custID[inner] < custID[outer]) // Ascending sort
{
tempID = custID[inner]; // Must include both,
tempBal = custBal[inner]; // otherwise the arrays wont be linked
custID[inner] = custID[outer];
custBal[inner] = custBal[outer];
custID[outer] = tempID;
custBal[outer] = tempBal;
didSwap = 1; // Flag that a swap took place
}
}
if(didSwap == 0)
{
break;
}
}
/* Second step: Interacting with the program */
printf("***Customer Balance Search***\n");
do
{
printf("Which ID number do you want to check?\n");
scanf(" %d", &IDsearch);
for(ctr = 0; ctr < 10; ctr++)
{
if(IDsearch == custID[ctr])
{
found = 1;
break;
}
}
if(found)
{
if(custBal[ctr] < 1000)
{
printf("\nCustomer #%d has a balance of $%.2f.\n", custID[ctr], custBal[ctr]);
printf("Credit is good!\n");
}
else
{
printf("\nCustomer #%d has a balance of %.2f.\n", custID[ctr], custBal[ctr]);
printf("Credit is bad! No more credit!\n");
}
}
else
{
printf("\nCustomer #%d was not found!\n", IDsearch);
printf("Please enter a correct ID number!\n\n");
continue;
}
printf("\nDo you want to search another ID number?\n");
printf("Enter (Y)es or (N)o\n");
scanf(" %c", &ans);
ans = toupper(ans);
}
while((found != 1) || (ans == 'Y' && ans != 'N'));
printf("\nExiting...\n\n");
return (0);
}
Please reset found
do {
found = 0;
// ...
at the start of the do-while loop. It is not enough to initialise it when defined.
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;
}
}
}