Caty Battjes
Caty Battjes

Reputation: 25

Having trouble printing out my structure array in c

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

Answers (3)

Loc Tran
Loc Tran

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

bitflip-at
bitflip-at

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

dbush
dbush

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

Related Questions