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.
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)?
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.
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.
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.
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.
@ 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
Désolé de vous embêter pour des choses aussi basiques.
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
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);
}
}
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.
[...] 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...
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.
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.
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.
é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 :
- Edité par edgarjacobs 23 novembre 2019 à 23:30:46
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Remplir une matrice d'entiers
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Bonhomme !! | Jeu de plateforme : Prototype.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent