IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

affichage erroné de mon tableau


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Femme Profil pro
    débutant en C pour le fun
    Inscrit en
    Octobre 2021
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : débutant en C pour le fun
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2021
    Messages : 6
    Par défaut affichage erroné de mon tableau
    Bonjour,

    je débute en C et je souhaite construire une matrice carrée dont la dimension est saisie par l'utilisateur. Je veux dans un premier temps creer la matrice carrée avec des zero et j'impose des valeurs aux 4 termes en haut à gauche de ma matrice (c'est pour la suite de mon pg). J'affiche ensuite la matrice a des fins de vérifications,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    void creer_matrice(int nb,int mat[nb][nb]){
      int i,j;
      for(i = 0; i < nb+1; i++)
      {
        for(j = 0; j < nb+1; j++)
        {
          mat[i][j]=0;
        }
      }
      mat[0][0]=2;
      mat[0][1]=3;
      mat[1][0]=6;
      mat[1][1]=-5;
    }
     
    void afficher_matrice(int nb,int mat[nb][nb]){
      int i,j;
      for(i=0; i <=nb; i++){
        for(j = 0; j <=nb; j++){
          printf("%i",mat[i][j]);
          }
        printf("\n");
      }
    }
     
     
    int main(){
      int nb_ut;
      do{
          printf("Entrez la taille de la matrice (2,4,8 ou 16):");
          scanf("%i",&nb_ut);
          printf("\n");
      }while(nb_ut!=1 && nb_ut!=2 && nb_ut!=4 && nb_ut!=8 && nb_ut!=16); /* verification de nb_ut*/
      nb_ut--; /*pour dimmensionner la matrice, on part de zero*/
      int mat[nb_ut][nb_ut]; /*déclaration de la matrice*/
      creer_matrice(nb_ut,mat); /*creer la matrice de zero*/
      afficher_matrice(nb_ut,mat); /*affichage de la matrice d'origine pour verif*/
    }
    et donc si je poste ici, c'est parce que ça ne fonctionne pas .... j'ai un 6 qui se balade en bout de première ligne ....d'où il sort lui ?

    Si vous avez une piste, j'y ai passé quelques heures ...

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 772
    Par défaut
    Saches que ton code C, c'est du code C avec des tableaux à longueur variable (VLA, "Variable-Length Array" en anglais) ... déprécié avec la norme C11.
    Je ne considère pas ce sucre syntaxique intéressant à utiliser, à par pour du code vite fait ... mais passons

    Ensuite, tu fais 1 passage paramètre tableau. Même 1 passage tableau 2D.
    Comme ton code ne fait qu'1 seul fichier .c, cela ne pose pas de problème. Mais saches que cette syntaxe ne sert à rien : il faut passer par la syntaxe pointeur (avec le test NULL)
    On va me dire que le compilateur peut faire des tests de bornes avec cette syntaxe. Effectivement.
    Et que même la syntaxe tableau 2D ne sert pas à grand chose : je préfère, la syntaxe 1D avec 1 peu de maths.
    Mais tu es au début, donc passons

    Après tu te mélanges les pinceaux
    Si tu veux créer 1 tableau de N cases, tu crées 1 tableau de N et tu le parcours de 0 à (N-1) inclus
    Mais tu ne crées pas 1 tableau de (N - 1) cases et pour compenser, tu ne le parcours pas de 0 à N inclus
    Tu as 1 ligne et 1 colonne en moins, et tu parcours 1 ligne et 1 colonne en plus

  3. #3
    Membre à l'essai
    Femme Profil pro
    débutant en C pour le fun
    Inscrit en
    Octobre 2021
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : débutant en C pour le fun
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2021
    Messages : 6
    Par défaut


    merci pour le "code vite fait", ça fait plaisir de se sentir encouragé

    j'ai pas tout compris de ton histoire de tableau que je constuis avec pas le bon nombre de termes.

    Je demande à l'utilisateur de saisir nb, qui sera la taille de ma matrice carrée, ensuite je retranche 1 pour justement balayer de 0 à nb-1, c'est bien ce que j'ai codé non ?

    je me plongerai dans les tableaux/pointeurs un autre jour du coup, j'espérais que mon pg ne necessitait pas de gros boulversements mais visblement si, et comme je n'ai jamais fait de pointeur, bah ce sera pour un autre jour ...


    Sandrine

  4. #4
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 772
    Par défaut
    Citation Envoyé par scoic Voir le message
    j'ai pas tout compris de ton histoire de tableau que je constuis avec pas le bon nombre de termes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      nb_ut--; /*pour dimmensionner la matrice, on part de zero*/
      int mat[nb_ut][nb_ut]; /*déclaration de la matrice*/
    Comment déclarer et utiliser un tableau « à plusieurs dimensions » ?, lien developpez en français
    Édit : n'utilise pas la syntaxe sizeof(t) / sizeof(t[0]), mais met la limite à la place. Comme tu vas apprendre les pointeurs plus tard, tu vas te faire avoir

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Entrez la taille de la matrice (2,4,8 ou 16):
    1 matrice carrée de
    • dimension 1, a 1 éléments
    • dimension 2, a 4 éléments
    • dimension 3, a 9 éléments
    • dimension 4, a 16 éléments

    Donc soit ta taille est le nombre de lignes/ colonnes (et donc ton code est faux) soit il faut définir "taille"

  5. #5
    Membre à l'essai
    Femme Profil pro
    débutant en C pour le fun
    Inscrit en
    Octobre 2021
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : débutant en C pour le fun
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2021
    Messages : 6
    Par défaut
    moi je veux des matrices carrées avec 2, 4, 8, ou 16 lignes et pareil en colonnes donc. La taille, c'est la "longueur" du coté de ma matrice.

  6. #6
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 315
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 315
    Billets dans le blog
    5
    Par défaut
    Bonjour.

    Bienvenue dans le monde merveilleux du C . Avec son cortège d'incompréhension. .

    Un tableau à n dimensions n'existe pas en électronique. C'est à dire qu'écrire Tab [2][2] sera traduit par le compilateur en une suite de quatre données qui se suivent en principe.

    En partant de ce constat le tableau Tab aura une adresse en mémoire pour la première donnée. L'adresse suivante sera pour la donnée suivante et ainsi de suite. Ceci est vrai si les données sont des entiers. Si les données sont des données plus longues alors l'adresse suivante devra être incrémentée de la taille des données. Mais faisons simple ici pour ne pas trop complexifier la chose.

    Alors écrire Tab[2][2] par exemple revient à écrire Tab[4]. Il suffit pour atteindre une donnée de faire un petit calcul. Par exemple si on désire Tab (1, 3) on aura pour les x = 1 et pour les y = 3 * 2. 2 étant la largeur du tableau. Ainsi Tab[x + y] nous donnera accès à la donnée de coordonnées (1, 3). On pourra en partant de ce principe écrire des fonctions qui nous permettrons d'accéder à une donnée et d'écrire une donnée.

    Mais pourquoi écrire tout ça alors qu'il suffit d'écrire Tab[1][3] ? Effectivement le compilateur traduit cette écriture dans les fonctions mathématiques sus-citées. L'idée est qu'en C on travaille avec les pointeurs. Tab[0] correspond à la première donnée du tableau et comme nous l'avons vu la première donnée est située sur la première adresse du tableau. Donc écrire Tab indique l'adresse du tableau.

    Comme tu débutes je n'utiliserai pas de structures dans les exemples qui suivent pour ne pas t'embrouiller plus que de raison.

    Commençons par voir une fonction pour initialiser une matrice à 0. C'est à dire que toutes les données ont la valeur 0. Il existe la fonction memset(); pour faire çà mais ce n'est pas l'idée ici. C'est pour montrer comment utiliser les pointeurs avec les tableaux.

    Nous transmettrons à cette fonction un tableau à une dimension ainsi que la taille d'un côté. Comme tu travailles avec des matrices carrées on gagne la transmission d'une donnée. Le prototype de la fonction aura cette forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void matrix_init (int *tab, uint size);
    Comme tu peux le voir tab est transmis sous forme de pointeur. La taille est du type unsigned int. Je ne vois pas comment un tableau pourrait avoir une taille négative. Voyons maintenant le contenu. Tout d'abord il nous faut tester les paramètres transmis. On va tester le pointeur pour voir qu'il n'est pas nul et la taille qu'elle ne soit pas égale à 0.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void matrix_init (int *tab, uint size)
    {
      if (tab==NULL)
        return;
      if (size == 0)
        return;
    Remarque : return; avec une fonction de type void permet de sortir de la fonction en ne renvoyant rien.

    Passons maintenant à l'initialisation. L'écriture sous forme de pointeur d'un tableau de la forme *tab peut comme on l'a vu plus haut s'écrire aussi tab[0]. Cette forme t'est familière. Utilisons-la. Une simple boucle suffira ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void matrix_init (int *tab, uint size)
    {
      if (tab==NULL)
        return;
      if (size == 0)
        return;
     
      for (int i=0; i < size*size; i++)
        tab[i] = 0;
    }
    Création d'une matrice :
    Ici la notion d'allocation dynamique de mémoire est abordée. Pour faire simple soit on écrit int Tab[4]; par exemple et l'allocation de la mémoire pour ce tableau est locale. On la nomme allocation dans la pile. C'est à dire que le tableau n'existe que dans la fonction où il est déclaré. Il faut privilégier cette écrire puisqu'elle nous évite des fuites de mémoire à cause de notre manque de rigueur . J'y reviendrai. Cependant cette forme d'écriture implique que l'on connaisse la taille du tableau. Dans le cas contraire il nous faut passer par l'allocation dynamique.

    L'allocation dynamique, ou allocation dans le tas, permet d'allouer une taille de tableau dans la limite de la mémoire de l'ordinateur utilisé. Cette allocation devra être libérée une fois son utilisation terminée. Pour allouer on utilisera la fonction malloc(); et pour libérer on utilisera la fonction free();. Ces deux fonctions utilisent ou renvoient des pointeurs. Je pense que tu commences à comprendre que la clef en C est la maîtrise des pointeurs.
    Voila le prototype de notre fonction. Nous transmettons simplement une taille et en retour nous aurons un pointeur sur une mémoire allouée dans le tas. Elle pourra renvoyer NULL si une erreur est survenue :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int *matrix_new (uint size);
    Comme pour fonction précédente nous testerons le paramètre transmis puis nous renverrons le résultat de la fonction malloc(); :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int *matrix_new (uint size)
    {
      if (size == 0)
        return NULL;
     
      return malloc (sizeof (int), size*size);
    }
    Remarque : Pour désallouer le tableau alloué avec la fonction matrix_new(); on utilisera la fonction free (tab);. je te laisse le soin d'aller voir la documentation officielle de malloc(); et de free (); sur le net ou dans ton livre de C préféré pour leur utilisation respective.

    Voila les deux premières fonctions de ton programme. À toi d'écrire les fonctions d'accès et d'écriture dans ta matrice. Pour t'aider voila les prototypes qu'elles pourraient avoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void matrix_set (int *tab, int i, int j, int data);
    int matrix_get (int *tab, int i, int j);
    i et j étant respectivement l'ordonnée et l'abscisse de la matrice. Pense à faire tous les tests nécessaires sur les paramètres transmis.

  7. #7
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    691
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 691
    Par défaut
    Salut,

    Citation Envoyé par Sve@r Voir le message
    VLA est créé à l'exécution. C'est un truc récent rajouté comme une espèce de de "rustine" pour permettre de créer des tableaux variables plus simplement que la méthode originelle basée sur l'allocation mémoire (qui reste quand-même possible).
    Non pas vraiment. VLA existait déjà aux débuts du C, présent notamment dans GCC 0.9 en 1987, pour ne citer que celui là, et son usage a été officialisé dans le standard de 1999.

    Citation Envoyé par scoic Voir le message
    je me plongerai dans les tableaux/pointeurs un autre jour du coup, j'espérais que mon pg ne necessitait pas de gros boulversements mais visblement si, et comme je n'ai jamais fait de pointeur, bah ce sera pour un autre jour ...
    Quelques ajustements sont suffisants. Tu peux construire un tableau de 16x16 et n'en utiliser qu'une partie. Illustration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    //demander la taille n : 2, 4, 8...
    int mat[16][16]= {0}; // construction du tableau, toutes les cases sont à 0. 
    f_matrice(mat, n); // faire_quelque_chose_de_matrice, sa signature peut être f_matrice(int mat[n], size_t /*ou int si tu veux*/ n)

  8. #8
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 772
    Par défaut
    Citation Envoyé par kaitlyn Voir le message
    Quelques ajustements sont suffisants. Tu peux construire un tableau de 16x16 et n'en utiliser qu'une partie.
    Tu peux faire autrement , mais le code devient lourd ... à moins de passer par des macros pour copier-coller du code.
    Évidemment avec 1 allocation dynamique la question est vite répondue.

    En C, tu peux créer 1 bloc { /* */ }, et y mettre dedans toutes les variables que tu veux et qui durent le temps du bloc. Très pratique par exemple, lorsque tu as besoin d'1 gros tableau temporaire à créer.
    Et justement, dans le switch, c'est la seule solution pour créer des variables temporaires pour 1 cas.

    J'ai initialisé en matrice diagonale pour mieux voir la matrice
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    #include <stdio.h>
    #include <stdlib.h>
     
     
    void matrix_init(int* mat, size_t size) {
        size_t row, col;
     
        for (row=0; row < size; ++row) {
            for (col=0; col < size; ++col) {
                *(mat + row*size + col) = ((row != col)? 0: 1);
            }
        }
    }
     
     
    void matrix_display(int* mat, size_t size) {
        size_t row, col;
     
        printf("matrix_display - size: %lu\n", size);
     
        for (row=0; row < size; ++row) {
            for (col=0; col < size; ++col) {
                printf("%i ", *(mat + row*size + col));
            }
            printf("\n");
        }
        printf("\n");
    }
     
     
    int main(/*int argc, char* argv[]*/) {
        size_t size = 8; // 2, 4, 8, 16
     
        switch (size) {
        case 2: {
            int mat[2][2] /*= {0}*/;
     
            matrix_init((int*) mat, size);
            matrix_display((int*) mat, size);
        } break;
     
        case 4: {
            int mat[4][4] /*= {0}*/;
     
            matrix_init((int*) mat, size);
            matrix_display((int*) mat, size);
        } break;
     
        case 8: {
            int mat[8][8] /*= {0}*/;
     
            matrix_init((int*) mat, size);
            matrix_display((int*) mat, size);
        } break;
     
        case 16: {
            int mat[16][16] /*= {0}*/;
     
            matrix_init((int*) mat, size);
            matrix_display((int*) mat, size);
        } break;
     
        default:
            printf("main - error: invalide size\n");
        }
     
    //  Example
        {
            int mat[160][160] /*= {0}*/; // segmentation fault if too big
     
            matrix_init((int*) mat, 160);
            matrix_display((int*) mat, 160);
        }
     
     
        return EXIT_SUCCESS;
    }

Discussions similaires

  1. Réponses: 5
    Dernier message: 25/03/2014, 06h02
  2. Réponses: 1
    Dernier message: 28/11/2013, 13h43
  3. Réponses: 4
    Dernier message: 20/08/2011, 13h06
  4. affichage de mon tableau
    Par kharg dans le forum Débuter
    Réponses: 7
    Dernier message: 08/09/2008, 00h03
  5. Réponses: 2
    Dernier message: 26/12/2006, 12h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo