Reputation: 25
My current project in class is to make a program that acts as a phone book using structs. I have coded out the 'add contacts' function and the 'show contacts' function, but when I have more than one contact, the 'show contacts' function shows gibberish for all of the contacts expect for the most recent one. Can anybody help me find the problem?
Here is my current code. If anything is confusing let me know and I will try to respond as fast as I can.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct contact { // Data structure that holds contact information
char FirstName[10]; // Array for first name
char LastName[10]; // Array for last name
int PhoneNum; // Phone number
};
int main (){
// Setting up variables
int Function = 0;
int Choice = 0;
char FName[200][10];
char LName[200][10];
int PNum = 0;
int n = 1;
struct contact *con[200];
int b = 0;
do{ // Will loop through the main function until the user decides to exit the program
// Prints out the main menu of the phone book
printf("\nPhone Book");
printf("\n[1] Add a contact");
printf("\n[2] Delete a contact");
printf("\n[3] Show contacts");
printf("\n[4] Exit program");
printf("\n\nWhat function would you like to use?\n"); // Asks for user input
scanf("%d", &Choice);
switch(Choice){
case 1: // Case to add a contact into the phone book
printf("\nYou chose to add a contact.");
printf("\nFirst name: ");
scanf("%s", &FName[b]);
printf("\nLast name: ");
scanf("%s", &LName[b]);
printf("\nPhone number (Numbers only): ");
scanf("%d", &PNum);
printf("\nRecord added to the phone book");
// Records the information given into the structure
struct contact *con = (struct contact*)malloc(n*sizeof(struct contact));
int a = (n - 1);
printf("\na is %d", a);
strcpy(con[a].FirstName, FName[b]);
strcpy(con[a].LastName, LName[b]);
con[a].PhoneNum = PNum;
int b = (b+1);
n++;
printf("\nn is %d", n);
// Prints out the given information
printf("\nNew contact:");
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
break;
case 2: // Case to delete a contact from the phone book
printf("\nYou chose to delete a contact.");
break;
case 3: // Case to see all of the entered contacts
printf("\nYou chose to show the contacts.");
for(a = 0; a < (n - 1); a++){
printf("\nContact #%d", a);
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
}
break;
case 4:
printf("Goodbye!");
break;
}
}while (Choice != 4);
return 0;
}
This is the output I get when I run my code.
Phone Book
[1] Add a contact
[2] Delete a contact
[3] Show contacts
[4] Exit program
What function would you like to use?
1
You chose to add a contact.
First name: Test
Last name: 1
Phone number (Numbers only): 1234567
Record added to the phone book
a is 0
n is 2
New contact:
First name: Test
Last name: 1
Phone number: 1234567
Phone Book
[1] Add a contact
[2] Delete a contact
[3] Show contacts
[4] Exit program
What function would you like to use?
1
You chose to add a contact.
First name: test
Last name: 2
Phone number (Numbers only): 8901234
Record added to the phone book
a is 1
n is 3
New contact:
First name: test
Last name: 2
Phone number: 8901234
Phone Book
[1] Add a contact
[2] Delete a contact
[3] Show contacts
[4] Exit program
What function would you like to use?
3
You chose to show the contacts.
Contact #0
First name: Pq
Last name: q
Phone number: 1095516483
Contact #1
First name: test
Last name: 2
Phone number: 8901234
Upvotes: 2
Views: 715
Reputation: 1180
There are some issues on your code:
1> Scope of variable a, b, con should be in main function, you are override the scope of variable a, b from main function scope to in-case scope by re-declare them inside case block code.
int b = b+1;
int a = (n-1);
struct contact *con = (struct contact*)malloc(n*sizeof(struct contact));
In case block code, please just assign them new value:
b = b+1;
a = (n-1);
con = (struct contact*)malloc(n*sizeof(struct contact));
2> The con pointer should be changed from
struct contact *con[200];
by define a initialized size for it. and if the size is out of range, we need to realloc the con in case of add new item:
int size = 200;
struct contact *con = (struct contact *)malloc(size * sizeof(struct contact));
// in case of the size of out of range
if (n >= size)
{
size = size * 2;
con = (struct contact*)realloc(con, size * sizeof(struct contact));
}
Here is my solution:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct contact { // Data structure that holds contact information
char FirstName[10]; // Array for first name
char LastName[10]; // Array for last name
int PhoneNum; // Phone number
};
int main() {
// Setting up variables
int Function = 0;
int Choice = 0;
char FName[200][10];
char LName[200][10];
int PNum = 0;
int n = 1;
int size = 200;
struct contact *con = (struct contact *)malloc(size * sizeof(struct contact));
int b = 0, a = 0;
do { // Will loop through the main function until the user decides to exit the program
// Prints out the main menu of the phone book
printf("\nPhone Book");
printf("\n[1] Add a contact");
printf("\n[2] Delete a contact");
printf("\n[3] Show contacts");
printf("\n[4] Exit program");
printf("\n\nWhat function would you like to use?\n"); // Asks for user input
scanf("%d", &Choice);
switch (Choice) {
case 1: // Case to add a contact into the phone book
printf("\nYou chose to add a contact.");
printf("\nFirst name: ");
scanf("%s", &FName[b]);
printf("\nLast name: ");
scanf("%s", &LName[b]);
printf("\nPhone number (Numbers only): ");
scanf("%d", &PNum);
printf("\nRecord added to the phone book");
// Records the information given into the structure
if (n >= size)
{
size = size * 2;
con = (struct contact*)realloc(con, size * sizeof(struct contact));
}
a = (n - 1);
printf("\na is %d", a);
strcpy(con[a].FirstName, FName[b]);
strcpy(con[a].LastName, LName[b]);
con[a].PhoneNum = PNum;
b = (b + 1);
n++;
printf("\nn is %d", n);
// Prints out the given information
printf("\nNew contact:");
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
break;
case 2: // Case to delete a contact from the phone book
printf("\nYou chose to delete a contact.");
break;
case 3: // Case to see all of the entered contacts
printf("\nYou chose to show the contacts.");
for (a = 0; a < (n - 1); a++) {
printf("\nContact #%d", a);
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
}
break;
case 4:
printf("Goodbye!");
break;
}
} while (Choice != 4);
return 0;
}
Upvotes: 3
Reputation: 149
As @Some programmer dude suggested you need to reallocate your array if you want to make it bigger and keep your data.
So essentially something like this
// Records the information given into the structure
struct contact *con = (struct contact*)malloc(n*sizeof(struct contact));
should be at the start of your main
function like so:
// dynamically allocate memory which can hold e.g. 1 struct
struct contact *con = malloc(sizeof(struct contact));
and when you resize your memory chunk on the heap, that is what malloc does for you, you should resize or realloc
it like so:
// grow array
con = realloc(con, n * sizeof(struct concat));
Read the man page for further Information: realloc man page, or type man 3 realloc
or man realloc
on your terminal.
EDIT As @dbush suggested
You declare 2 variables named con. At the start struct contact *con[200];
and in the switch statement you allocate memory and save it into struct concat *con
.
So the reason why you still get undefined results on option "3" (show all contact) is, that you actually are reading the contacts from the array struct contact *con[200];
and not from the memory pointed by struct contact *con;
Greetings
Upvotes: 0
Reputation: 223739
You're defining a new variable called con
inside of your switch
statement. This variable mask the variable of the same name defined at the top of the function. This is the one you're adding a record to.
When you later go to print the list, it's actually reading from this inner con
. However, since you're re-entering the switch
statement, the variable's contents is uninitialized because you jump over the initializer because of the switch and you invoke undefined behavior. You get "lucky" that you're able to print the last instance read in, probably because the variable still happened to contain the old value from the last iteration.
Also, the outer version of con
is declared as an array of pointers. You probably want just a pointer here so it can point to a dynamically allocated array.
So define con
like this:
struct contact *con = NULL;
And change the "add" case to not define the variable. Also, you don't need separate variables to read in the values. You can read them directly into an instance of the struct:
n++;
con = realloc(n*sizeof(struct contact));
printf("\nYou chose to add a contact.");
printf("\nFirst name: ");
scanf("%s", con[n-1].FirstName);
printf("\nLast name: ");
scanf("%s", con[n-1].LastName);
printf("\nPhone number (Numbers only): ");
scanf("%d", &con[n-1].PhoneNum );
printf("\nRecord added to the phone book");
printf("\nn is %d", n);
printf("\nNew contact:");
printf("\nFirst name: %s", con[n-1].FirstName);
printf("\nLast name: %s", con[n-1].LastName);
printf("\nPhone number: %d", con[n-1].PhoneNum);
printf("\n");
Then you'll also need to move a
down to the "show" portion:
for( int a = 0; a < (n - 1); a++){
Upvotes: 1