3
votes

Avoir du mal à imprimer mon tableau de structure en c

Mon projet actuel en classe est de créer un programme qui agit comme un annuaire téléphonique en utilisant des structs. J'ai codé la fonction «ajouter des contacts» et la fonction «afficher les contacts», mais lorsque j'ai plus d'un contact, la fonction «afficher les contacts» affiche du charabia pour tous les contacts attendus pour le plus récent. Quelqu'un peut-il m'aider à trouver le problème?

Voici mon code actuel. Si quelque chose est déroutant, faites-le moi savoir et j'essaierai de répondre aussi vite que possible.

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

C'est le résultat que j'obtiens lorsque j'exécute mon code.

#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;   
}


4 commentaires

Vous avez struct contact * con défini deux fois. Est-ce votre intention?


Vous allouez une nouvelle mémoire pour con chaque fois que vous ajoutez un nouveau contact. Vous devez réallouer la mémoire pour l'augmenter .


Eugene, je l'ai défini au début pour en faire un tableau, mais sans la deuxième définition, le code a plus d'erreurs.


Un mec programmeur, pouvez-vous me montrer à quoi cela ressemblerait?


3 Réponses :


1
votes

Comme @Certains programmeurs l'ont suggéré, vous devez réallouer votre tableau si vous voulez l'agrandir et conserver vos données.

Donc, essentiellement quelque chose comme ça

// grow array 
con = realloc(con, n * sizeof(struct concat));

devrait être au début de votre fonction main comme ceci:

// dynamically allocate memory which can hold e.g. 1 struct
struct contact *con = malloc(sizeof(struct contact));

et quand vous redimensionnez votre morceau de mémoire sur le tas, c'est ce que fait malloc pour vous, vous devriez le redimensionner ou le réallouer comme ceci:

// Records the information given into the structure
   struct contact *con = (struct contact*)malloc(n*sizeof(struct contact));

Lisez la page de manuel pour plus d'informations: realloc man page , ou tapez man 3 realloc ou man realloc sur votre terminal.

MODIFIER Comme @dbush l'a suggéré

Vous déclarez 2 variables nommées con. Au début struct contact * con [200]; et dans l'instruction switch, vous allouez de la mémoire et l'enregistrez dans struct concat * con .

Donc, la raison pour laquelle vous obtenez toujours des résultats non définis sur l'option "3" (afficher tous les contacts) est que vous lisez en fait les contacts du tableau struct contact * con [200]; et pas de la mémoire pointée par struct contact * con;

Salutations


2 commentaires

J'ai essayé cela, mais maintenant, lors de l'impression, il montre un tas de charabia pour les deux contacts


Si vous obtenez une sortie chaotique, vous accédez à la mémoire qui n'est pas initialisée mais qui est allouée (c'est le cas pour la réallocation où aucun mem n'est copié). Vous pourriez vérifier ceci. Regardez chaque ligne sur laquelle vous travaillez avec le pointeur qui pointe vers la mémoire du tas.



1
votes

Vous définissez une nouvelle variable appelée con à l'intérieur de votre instruction switch . Cette variable masque la variable du même nom définie en haut de la fonction. C'est celui auquel vous ajoutez un enregistrement.

Lorsque vous imprimerez plus tard la liste, elle lit en fait à partir de cette con interne. Cependant, comme vous entrez à nouveau l'instruction switch , le contenu de la variable n'est pas initialisé car vous sautez par-dessus l'initialiseur à cause du commutateur et vous appelez comportement non défini . Vous avez "de la chance" de pouvoir imprimer la dernière instance lue, probablement parce que la variable contenait toujours l'ancienne valeur de la dernière itération.

De plus, la version externe de con est déclaré comme un tableau de pointeurs . Vous voulez probablement juste un pointeur ici pour qu'il puisse pointer vers un tableau alloué dynamiquement.

Alors définissez con comme ceci:

for( int a = 0; a < (n - 1); a++){

Et changez la casse "ajouter" pour ne pas définir la variable. De plus, vous n'avez pas besoin de variables séparées pour lire les valeurs. Vous pouvez les lire directement dans une instance de la structure:

            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");

Ensuite, vous devrez également déplacer a vers la partie "show" :

struct contact *con = NULL;


0 commentaires

3
votes

Il y a quelques problèmes avec votre code:

1> La portée de la variable a, b, con doit être dans la fonction principale, vous remplacez la portée de la variable a, b de la portée de la fonction principale à la portée au cas les déclarer à nouveau dans le code de bloc de cas.

#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;
}

Dans le code de bloc de cas, veuillez leur attribuer une nouvelle valeur:

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));
}

2> Le pointeur con doit être remplacé par

struct contact *con[200];

en lui définissant une taille initialisée. et si la taille est hors limites, nous devons réallouer le con en cas d'ajout d'un nouvel élément:

b = b+1;
a = (n-1);
con = (struct contact*)malloc(n*sizeof(struct contact));   

Voici ma solution:

int b = b+1;
int a = (n-1);
struct contact *con = (struct contact*)malloc(n*sizeof(struct contact));


1 commentaires

Merci, j'ai parcouru le code que vous avez corrigé et cela a fonctionné pour moi cette fois!