Question

Avec le morceau de code suivant, je reçois un résultat très bizarre. Pourquoi la valeur du dernier élément de tous les éléments en écrasant tableau précédent? Je pense qu'il ya un problème plus grand que tout ce problème immmediate.

#include <stdio.h>

main()
{
    int i, cases;
    char num[1000000];

    scanf("%d", &cases);
    char* array[cases];

    //store inputs in array
    for(i=0; i<cases; i++)
    {
        scanf("%s", &num);
        array[i] = &num;
    }

    //print out array items and their memory addresses
    for(i=0; i<cases; i++)
    {
        printf("%d %s\n", i, array[i]);  //print (array index) (array value) 
        printf("%d %p\n", i, &array[i]); //print (array index) (array address) 
    }
}

Inputs:
3 <-- number of lines to follow
0   <-- put in array[0]
1   <-- put in array[1]
2   <-- put in array[2]

Outputs
0 3         <-- why is this being overwritten with the last element?
0 0013BCD0
1 3         <-- why is this being overwritten with the last element?
1 0013BCD4
2 3
2 0013BCD8

Pas de solution correcte

Autres conseils

Le résultat est ici la ligne array[i] = &num; vous définissez la valeur de l'élément array[i] à l'adresse du tableau de num; puisque array est un tableau de caractères, je pense qu'il est tronquer votre adresse de tableau de num, et l'octet de poids faible se trouve être un 3.

Cependant. Cela dit, votre personnage num [1000000] est la forme hideuse, et vous ne devriez pas faire cela, du tout. Allouer sur le tas, et choisissez un plus petit nombre, pour l'amour du ciel. En outre, le scanf ( « % s », et num) ne vous donnera pas réellement ce que vous voulez. Voici un indice; utiliser une boucle getc () pour lire les nombres; cela évite besoin de faire une pré-allocation d'un tableau pour scanf ().

Il est parce que vous mettez dans tous les index du tableau la même adresse (l'adresse de l'omble num [1000000];).

Il est une erreur qui vous mènera à l'allocation dynamique (calloc, malloc, nouveau, etc).

Vive!

Dans votre première boucle, vous devriez être (mais vous n'êtes pas) l'écriture de chaque entrée dans un élément différent du tableau num; au lieu que vous écrivez toujours au même endroit, à savoir à &num.

char * chaine [cas];

Ceci est attribué à la compilation, pas l'exécution. Et les cas ne sont pas initialisés (même si je pense que vous voulez que cela fonctionne dynamiquement de toute façon.) Donc, vous devez soit preallocate la mémoire, ou se familiariser avec la famille malloc des fonctions de la bibliothèque.

Remplacer

//store inputs in array
for(i=0; i<cases; i++)
{
    scanf("%s", &num);
    array[i] = &num;
}

avec

array[0] = num;
//store inputs in array
for(i=0; i<cases; i++)
{
    scanf("%s", array[i]);
    array[i+1] = array[i] + strlen(array[i]) + 1;
}

pour balayer chaque chaîne dans le premier espace disponible dans num[], et régler l'élément suivant de array[] pour pointer vers l'espace disponible suivant. Maintenant, votre printf() des cordes fonctionnera. L'original a été scanner chaque chaîne en début de num[].

Note:.. scanf() avec %s sans fioritures est aussi mauvais que gets(), car il ne met aucune limite sur la quantité de données qui seront Slurped dans Ne pas utiliser dans le code réel

Remplacer

    printf("%d %p\n", i, &array[i]); //print (array index) (array address) 

avec

    printf("%d %p\n", i, (void*)(array[i])); //print (array index) (array address) 

pour imprimer réellement les adresses stockées dans a[], plutôt que les adresses des éléments de a[]. Le casting est nécessaire parce que %p attend un pointeur-tovoid de sorte que vous devez fournir un.

Cest votre code qui est fixé:

#include <stdio.h>

main(void)
{
    int i, cases;

    scanf("%d", &cases);
    char* array[cases];

    //store inputs in array
    for(i=0; i<cases; i++)
    {
        char *num = malloc(100000);
        scanf("%s", num);
        array[i] = num;
    }

    //print out array items and their memory addresses
    for(i=0; i<cases; i++)
    {
        printf("%d %s\n", i, array[i]);  //print (array index) (array value)
        printf("%d %p\n", i, (void*)&array[i]); //print (array index) (array address)
    }
    return 1;
}

Vous pouvez aussi bien utiliser

char *num = calloc(100000, sizeof(char));

qui est un peu peu sur la défensive. Je ne sais pas pourquoi vous avez besoin 100000. Vous pouvez le faire en utilisant dynamiquement malloc. Cela implique plus de travail, mais est très robuste.

Ce qui est hapenning dans votre code est que vous stockez la chaîne% s à l'adresse de num qui ne change pas, alors vous attribuez tableau d'éléments [i] à cette adresse. Affectation en C est rien d'autre puis stocker la référence, vous ne stockez pas l'élément itself- ce serait gaspillage d'espace. Donc, en tant que point à l'adresse (magasin seulement la référence), la valeur du changement adresse, ainsi elle donc la référence, c'est la raison pour laquelle ils sont tous en train de changer à 2 (non 3 comme vous l'avez dit dans votre post) tous les éléments du tableau.

Il est pour des choses telles que C ++ semble être fait. l'analyse syntaxique d'entrée de l'utilisateur et les allocations dynamiques sont effectuées de manière plus sûre, et dans un jeu d'enfant. Je ne peux pas penser à un système où vous avez ce genre d'une interface utilisateur, où on ne pouvait pas passer à C ++.

Bien sûr, si cela est seulement un extrait de test d'un autre code qui souffre du problème, bien sûr ...


Votre code souffre de plusieurs erreurs courantes pour les débutants C et des choses qui ne devraient pas être faites de cette façon de nos jours.

Si je comprends bien, vous voulez enregistrer les chaînes d'entrée utilisateur sereval (votre exemple de sortie est un peu trompeur, parce que vous montrer que des chiffres).

Vous préparez le tableau pour contenir tous (cas compter) pointeurs vers des chaînes, mais vous ne réservez mémoire pour une chaîne. Vous devez le faire pour chaque chaîne, donc des cas. Pour garder les choses simples en termes de la leçon « allocation dynamique de mémoire », je vous recommande de le faire de cette façon. char* array[cases][10000]; Cela vous donne des cas des chaînes de caractères 10k

Vous avez probablement aussi ne veulent pas avoir des pointeurs séparés à vos éléments du tableau. Cela commence à donner un sens si vous voulez trier les éléments d'un tableau lorsque ces éléments sont plus grandes que les pointeurs lui-même. Dans ce cas, votre gain de performance est de ne pas avoir déplacer (copier) de gros morceaux, mais seulement les pointeurs (4 octets). Dans votre cas, un int est aussi 4 octets. Et vous ne triez pas de toute façon:)

scanf() est dangereux, pour le moins. Dans votre deuxième application, vous lui demandant d'écrire une chaîne à l'adresse du tableau. Cela semble être une simple erreur, mais peut conduire à de nombreux problèmes. Vous voulez sans doute le faire de cette façon: scanf("%d", &array[i]); (Malheureusement, je n'ai pas un compilateur à portée de main, donc je ne suis pas sûr à 100%). déposer la ligne suivante:)


Question aux spécialistes Markdown: Pourquoi est-il si sacrément impossible d'avoir des listes combinées avec le code-blocs

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top