Partage
  • Partager sur Facebook
  • Partager sur Twitter

Remplir une matrice d'entiers

remplissage matrice d'entiers à partir d'un scanf

Sujet résolu
    7 mars 2014 à 9:36:06

    Bonjour à tous. 

    J'aurais besoin de votre aide pour un petit problème qui est, j'en suis sûr, complètement bêbête à résoudre... Mais le fait est que je bloque.

    J'explique:

    J'ai donc créé une matrice d'entiers dynamique avec le code suivant: 

    	int i, j, nbLin, nbCol;
    	int** matrice;
    	
    	printf("entrer nombre de lignes");
    	scanf("%d",&nbLin);
    	printf("entrer nombre de colonnes");
    	scanf("%d",&nbCol);
    
    	matrice=malloc(nbLin*sizeof(int*));
    	for(i=0; i<nbLin; i++)
    		matrice[i]=malloc(nbCol*sizeof(int));



    Quand je veux la remplir de "0", rien de bien compliqué, ça ne pose aucun soucis.

    for(i=0; i<nbLin; i++){
    	for(j=0; j<nbCol; j++)
    		matrice[i][j]=0;
    }

    Je n'ai pas besoin de ce dernier bout de code en soit, c'était uniquement dans le but de tester si la création de la matrice fonctionnait.

    Là ou je bloque, c'est quand je veux demander à l'utilisateur de remplir la matrice qu'il a crée, avec des entiers entrés au clavier (donc je suppose avec un scanf) MAIS j'aimerais qu'il le fasse ligne par ligne, et non élément par élément pour un soucis de rapidité.

    Le problème est que je ne sais pas comment lire une ligne d'entiers (séparés par des espaces) et de stocker chaque entier de la ligne que l'utilisateur a entré, dans la matrice.

    Pour exemple, l'utilisateur entrerait pour la première ligne: 15 3 25 8 47 56

    le "15" serait stocké à matrice[0][0]; le "3" serait stocké à matrice[0][1] ETC.

    Arrivé à nbCol-1, on entrerait la seconde ligne et ainsi de suite, jusqu'à arriver à nbLin-1.

    Y a-t-il un quelconque moyen en C de lire plusieurs entiers à la suite (sans savoir le nombre d'entiers qu'on lira, car ce sera en fonction de la taille de la matrice)?

    Merci pour votre futur aide.

    Kris

    • Partager sur Facebook
    • Partager sur Twitter
      7 mars 2014 à 10:44:45

      Bonjour,

      Tu peux faire ton scanf élément par élément, ensuite que l'utilisateur sépare chaque valeur par un espace, une tabulation ou entrée elles seront prises en compte quand même.

      for(i=0; i<nbLin; i++) {
          printf("Ligne %d entrer %d valeurs ",i+1,nbCol);
          for(j=0; j<nbCol; j++) {
              scanf("%d",&matrice[i][j]);
          }
      }
      
      • Partager sur Facebook
      • Partager sur Twitter
        7 mars 2014 à 10:54:41

        La solution la plus simple serait d'aller lire le buffer d'entrée avec une fonction comme fgets(). Ensuite, tu peux parser la ligne d'entrée dans une boucle avec une fonction de gestion des chaînes de caractères (je pense à strtok(), par exemple) et assigner chaque valeur comme tu le souhaites.

        • Partager sur Facebook
        • Partager sur Twitter
        Mon blog : blog.richarddegenne.fr
          7 mars 2014 à 11:18:06

          fromvega a écrit:

          Bonjour,

          Tu peux faire ton scanf élément par élément, ensuite que l'utilisateur sépare chaque valeur par un espace, une tabulation ou entrée elles seront prises en compte quand même.

          for(i=0; i<nbLin; i++) {
              printf("Ligne %d entrer %d valeurs ",i+1,nbCol);
              for(j=0; j<nbCol; j++) {
                  scanf("%d",&matrice[i][j]);
              }
          }
          

          Bonjour,

          merci pour le petit bout de code, j'ai testé, ça fonctionne bien.

          Est-ce qu'on a un moyen de tester si l'utilisateur entre le bon nombre de valeurs sur le scanf? Voir s'il n'en entre ni trop, ni trop peu. Et dans le cas ou il y'aurait une erreur... lui faire répéter l'entrée? J'ai un peu de mal a visualiser le buffer, en fait, ce qu'il fait, ce qu'il prend en compte ou pas, etc.

          :D

          @ Richou D.: ca me paraît bien complexe comme solution, je n'ai jamais utilisé les fonctions que tu cites et ne les connais pas non plus. Tu pourrais peut-être m'en dire plus avec des exemples de codes? ^^' 

          Sinon je ne cherche pas à comprendre et je me contente de la première solution :p

          Désolé de vous embêter pour des choses aussi basiques. :p

          • Partager sur Facebook
          • Partager sur Twitter
            7 mars 2014 à 11:42:14

            Si tu n'as pas encore abordé la lecture/écriture dans les fichiers, alors ça va être compliqué… ^.^

            Pour faire simple, il existe un fichier appelé stdin, qui contient les entrées clavier. La fonction fgets() permet de lire dans un fichier. Donc on va lire dans stdin la dernière entrée.

            Ensuite, strtok() (comprendre string token) permet de "couper" une chaîne de caractère en plusieurs grâce à un délimiteur. Du coup, tu peux isoler chaque mot d'une phrase par exemple. La dernière étape consiste à transformer tes chaînes de caractères en entiers, et pour ça, il y a strtol().

            C'est peut-être un tantinet plus complexe que ce que propose fromvega, mais ici, ta saisie est sécurisée. Comme on dit, NTUI.

            -
            Edité par Richou D. Degenne 7 mars 2014 à 11:42:44

            • Partager sur Facebook
            • Partager sur Twitter
            Mon blog : blog.richarddegenne.fr
              7 mars 2014 à 11:56:23

              scanf tel quel n'est pas sécurisé c'est sûr, il va y avoir des soucis si l'utilisateur saisit autre chose que des chiffres. Tu peux le sécuriser en testant le code retour de scanf, qui est le nombre de saisies valides effectuées (qui doit être égal à 1 car la saisie est faite pour chaque nombre) et ensuite vider le buffer de tous les caractères non lus par scanf avant la saisie suivante.

                  for(i=0; i<nbLin; i++) {
                      printf("Ligne %d entrer %d valeurs ",i+1,nbCol);
                      for(j=0; j<nbCol; j++) {
                          do {
                              r = scanf("%d",&matrice[i][j]);
              
                              /* Vider le buffer */
                              c = getchar();
                              while (!isspace(c) && c != EOF) {
                                  c = getchar();
                              }
                          }
                          while (r != 1);
                      }
                  }
              

              (r et c sont des int)

              -
              Edité par fromvega 7 mars 2014 à 11:58:26

              • Partager sur Facebook
              • Partager sur Twitter
                7 mars 2014 à 11:56:54

                Merci Richou D.

                ca m'éclaire un peu plus, mais la consigne est claire, n'utiliser que ce qui a été vu pour le moment :)

                • Partager sur Facebook
                • Partager sur Twitter
                  7 mars 2014 à 11:58:21

                  Ah oui, c'est une règle absolue ! Ne connaissant pas ton niveau, j'ai proposé la solution qui m'est venue à l'esprit, sans compter qu'elle pourra servir à quelqu'un d'autre qui se posera la même question que toi. :)
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Mon blog : blog.richarddegenne.fr
                    7 mars 2014 à 12:19:10

                    Salut,

                    Richou D. Degenne a écrit:

                    La solution la plus simple[...]

                    Richou D. Degenne a écrit:

                    [...] plus complexe que ce que propose fromvega[...]

                    Faudrait savoir... :-°

                    C'est effectivement plus sécurisé, et ce n'est pas le plus simple... Sinon, on peut aussi utiliser le regex et exploiter le retour de scanf()... Ce n'est pas non plus le mal absolu...

                    Bonne continuation.

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Stringman | Jeux de plateforme : Nouvelle Démo. (màj : 16 Juin 2019)

                      7 mars 2014 à 15:36:50

                      fromvega a écrit:

                      scanf tel quel n'est pas sécurisé c'est sûr, il va y avoir des soucis si l'utilisateur saisit autre chose que des chiffres. Tu peux le sécuriser en testant le code retour de scanf, qui est le nombre de saisies valides effectuées (qui doit être égal à 1 car la saisie est faite pour chaque nombre) et ensuite vider le buffer de tous les caractères non lus par scanf avant la saisie suivante.

                          for(i=0; i<nbLin; i++) {
                              printf("Ligne %d entrer %d valeurs ",i+1,nbCol);
                              for(j=0; j<nbCol; j++) {
                                  do {
                                      r = scanf("%d",&matrice[i][j]);
                      
                                      /* Vider le buffer */
                                      c = getchar();
                                      while (!isspace(c) && c != EOF) {
                                          c = getchar();
                                      }
                                  }
                                  while (r != 1);
                              }
                          }
                      

                      (r et c sont des int)

                      -
                      Edité par fromvega il y a environ 1 heure


                      Solution fonctionne niquel, merci beaucoup. Même si j'ai du mal à comprendre les 3 lignes pour vider le buffer ^^'.

                      D'ailleurs une explication en français, serait la bienvenue.

                      En tout cas , merci encore.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        7 mars 2014 à 16:20:05

                        La partie du code qui vide le buffer permet de lire les caractères présents dans l'entrée standard (le clavier ou un fichier d'entrée) qui n'ont pas été lus par le scanf précédent. Si on ne vide pas le buffer, le pointeur de lecture restera toujours au même endroit en cas d'échec du scanf et on bouclera indéfiniment dans le do ... while.

                        Imagine que l'utilisateur saisit

                        2 jmatrompe 4<entrée>

                        La lecture du 2 avec scanf se passe bien, son code retour est 1 et le vidage du buffer va positionner la lecture avant le j, on passe au scanf suivant

                        La lecture de "jmatrompe" avec scanf retourne 0, le vidage du buffer va lire tous les caractères 1 par 1 (getchar) pour se positionner avant le 4, on reste sur le même scanf

                        La lecture du 4 avec scanf se passe bien, son code retour est 1 et le vidage du buffer va positionner la lecture après <entrée> (\n), on passe au scanf suivant

                        La fonction isspace est utilisée pour tester si le caractère lu est un "séparateur". Regarde le man de la fonction pour voir quels sont les caractères appartenant à cet ensemble, elle inclut notamment l'espace, la tabulation et le retour chariot.

                        La ligne de code

                        while (!isspace(c) && c != EOF) {

                        Signifie qu'on boucle tant que le caractère lu n'est pas un "séparateur" et qu'on n'est pas en fin de fichier. Le cas "Fin de fichier" peut arriver si ton programme est lancé en redirigeant l'entrée standard depuis un fichier:

                        $ lecture_matrice <test.txt

                        Et que ton fichier ne contient pas toutes les valeurs attendues, exemple

                        4

                        4

                        1 2

                        On attend une matrice 4x4 mais on n'a que 2 valeurs, le caractère lu en fin de fichier sera EOF, dans ce cas il faut donc sortir également de la boucle sinon on va boucler indéfiniment. Il faudrait d'ailleurs sortir également de la boucle do while dans ce cas.

                            do {
                                r = scanf("%d",&matrice[i][j]);
                        
                                /* Vider le buffer */
                                c = getchar();
                                while (!isspace(c) && c != EOF) {
                                    c = getchar();
                                }
                            }
                            while (r != 1 && c != EOF);
                        

                        Cette partie de code serait d'ailleurs à transformer en une fonction

                        int  enter_int(int *);

                        Retournant r et auquel on passe l'adresse de la variable récupérant la saisie, que tu pourrais appeler également pour saisir nbLig/NbCol.

                        -
                        Edité par fromvega 7 mars 2014 à 17:36:53

                        • Partager sur Facebook
                        • Partager sur Twitter
                          7 mars 2014 à 21:11:47

                          Et bien... WOW :)

                          T'expliques comme un dieu :p

                          Enfin je comprend mieux. Un grand merci à toi en tout cas. Je vais tâcher de mettre en exécution tout ce que tu m'as appris :)

                          Remarque: je ne sais pas si c'est normal... mais quand on se trompe et qu'on entre par exemple: vjdbczjb5

                          le "5" n'est pas pris en compte.

                          vjdbczjb5 2

                          ici, le premier int à être pris en compte est le 2.

                          Est-ce normal?

                          -
                          Edité par kristouffe 7 mars 2014 à 21:24:17

                          • Partager sur Facebook
                          • Partager sur Twitter
                            8 mars 2014 à 8:44:58

                            Oui c'est normal (enfin c'est le fonctionnement attendu du vidage de buffer ci-dessus), il consomme tous les caractères jusqu'au prochain séparateur qui est l'espace, donc après le 5.
                            • Partager sur Facebook
                            • Partager sur Twitter
                              8 mars 2014 à 9:30:33

                              Oui, je m'en suis rendu compte en fait ^^ C'était une bête une question.

                              Merci encore.

                              • Partager sur Facebook
                              • Partager sur Twitter
                                9 mars 2014 à 9:42:44

                                drx a écrit:

                                Salut,

                                Richou D. Degenne a écrit:

                                La solution la plus simple[...]

                                Richou D. Degenne a écrit:

                                [...] plus complexe que ce que propose fromvega[...]

                                Faudrait savoir... :-°

                                J'avoue… :lol: Je crois que par "la plus simple", je pensais à "la première qui m'est venue à l'esprit". :p
                                • Partager sur Facebook
                                • Partager sur Twitter
                                Mon blog : blog.richarddegenne.fr
                                  20 avril 2019 à 1:15:58

                                  écrire un programme qui demande a l'utilisateur de saisir une matrice carré de dimension au plus 3 et qui réalise des opération sue cette matrice grâce au menu suivant :
                                  1)calculer le déterminent
                                  2)calculer l'inverse
                                  3)calculer la puissance carrée
                                  4)changer la matrice
                                  5)quitter
                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Remplir une matrice d'entiers

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  • Editeur
                                  • Markdown