Tableau à double dimension
Résolu
CrazyGeekMan
Messages postés
971
Statut
Membre
-
CrazyGeekMan Messages postés 971 Statut Membre -
CrazyGeekMan Messages postés 971 Statut Membre -
Bonjour,
Mon programme n'a pas de grand intérêt mais c'était pour m'exercer sur les tableaux.
D'après le shell j'ai une erreur
Test.c:23:11: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("%s",mot[i][j]);
Pourtant j'ai bien initialisé mot [ligne] [colonne] en char et je n'ai crée aucun pointeur..
Voici le code :
Merci pour votre aide!
Mon programme n'a pas de grand intérêt mais c'était pour m'exercer sur les tableaux.
D'après le shell j'ai une erreur
Test.c:23:11: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("%s",mot[i][j]);
Pourtant j'ai bien initialisé mot [ligne] [colonne] en char et je n'ai crée aucun pointeur..
Voici le code :
#include <stdio.h>
#define ligne 2
#define colonne 3
void main()
{
int i,j;
char vide;
char mot[ligne][colonne];
for(i=0;i<ligne;i++)
{
for(j=0;j<colonne;j++)
{
printf("\n Rentre la valeur %d,%d \n",i,j);
scanf("%s",&mot[i][j]);
scanf("%c",&vide);
}
}
for(i=0;i<ligne;i++)
{
for(j=0;j<colonne;j++)
{
printf("%s",mot[i][j]);
}
}
}
Merci pour votre aide!
2 réponses
-
Salut CrazyGeekMan,
char
représente un caractère et non une chaîne de caractères
en déclarantchar mot[ligne][colonne];
tu ne fais que réserver de l'espace pour un seul caractère dans chaque case de ton tableau bidimensionnel (un char étant en fait un type entier, l'entier étant normalement la représentation ASCII du caractère)
une chaîne de caractères en C est un emplacement en mémoire où sont stockés deschar
et terminée par le caractère "null", soit'\0'
:
https://www.commentcamarche.net/contents/118-langage-c-les-chaines-de-caracteres#qu-est-ce-qu-une-chaine-de-caracteres
ton tableau est donc mal déclaré et ta mémoire mal allouée si tu veux stocker autre chose que unchar
par case (et tonscanf("%s",&mot[i][j]);va certainement écrire dans des zones mémoires non allouées, occasionnant une corruption de la mémoire, des core dumps,...)
pour faire un tableau bidimensionnel de chaînes de caractères, tu dois mettre dans chaque case les pointeurs surchar
, pointant vers la zone mémoire allouée à chaque chaîne que tu veux stocker. Si tu le fais au moyen demalloc()
, tu devras gérer aussi la libération de l'espace avecfree()
...
à ce moment là, tonprintf("%s",mot[i][j]);sera également content et ne t'enverra plus de warning.
Dal-
D'accord merci pour la réponse.
Et moi comme un con j'ai essayé de compiler avec l'option-fno-stack-protector
...
Je ne vois pas ce que tu veut dire par "tu dois mettre dans chaque case les pointeurs sur char, pointant vers la zone mémoire allouée à chaque chaîne que tu veux stocker." :(
Je dois créer 6 pointeurs pointant vers 6 chaînes de caractères? (6 char?)
Désolé pour le boulet que je suis. -
pour stocker des chaînes de caractères dans un tableau à deux dimensions, tu peux faire comme cela :
#include <stdio.h> #include <stdlib.h> #define ligne 2 #define colonne 3 int main(void) { int i,j; char * mot[ligne][colonne]; /* à ce stade, mot contient assez d'espace pour stocker 2x3=6 * pointeurs sur des char */ /* allocation d'espace pour des chaînes de 10 caractères * (y compris le '\0' terminal) pointées par ces * pointeurs, ou une taille variable, si tu veux */ for(i=0;i<ligne;i++) for(j=0;j<colonne;j++) mot[i][j] = malloc(sizeof(char) * 10); /* mettre des chaînes dedans et faire ce qu'on a à faire * avec */ int c; for(i=0;i<ligne;i++) { for(j=0;j<colonne;j++) { printf("\nRentre le mot à la position %d,%d (9 lettres au plus)\n",i,j); while (scanf("%9[^\n]", mot[i][j]) != 1) /* we want non empty things */ ; while ((c = getchar()) != '\n' && c != EOF) /* discard what remains in stdin */ ; } } printf("\n\n"); for(i=0;i<ligne;i++) for(j=0;j<colonne;j++) printf("%s\n",mot[i][j]); /* libération de l'espace occupé par les chaînes */ for(i=0;i<ligne;i++) for(j=0;j<colonne;j++) free(mot[i][j]); return 0; }
il y a plusieurs façons de faire
par exemple, alternativement, tu peux tout faire avec des pointeurs et des allocations dynamiques, en déclarant ta structure de données comme étant unchar *** mot
(c'est utile si le nombre de lignes et de colonnes, outre la taille des chaînes, sont indéterminés à l'avance ou peuvent varier en cours d'exécution)
si tu n'as pas besoin de tailles variables, tu peux aussi te passer des mallocs / free en déclarant un truc commechar mot[ligne][colonne][10];
et c'est tout
Dal
P.S. :malloc(sizeof(char) * 10);
peut s'écriremalloc(10);
aussi en C, car le typechar
a, par définition, une taille de 1 byte- D'accord je vois maintenant une belle utilité du malloc (j'utilisais toujours l'allocation dynamique jusqu'ici).
Je vais encore étudié cette partie du code :while (scanf("%9[^\n]", mot[i][j]) != 1) /* we want non empty things */ ; while ((c = getchar()) != '\n' && c != EOF) /* discard what remains in stdin */ ;
Il y a deux boucles while sans aucune instructions, je n'ai jamais vu ça ^^
Merci !
-
(j'utilisais toujours l'allocation dynamique jusqu'ici)
si tu n'utilisais pas de malloc, je pense que tu veux dire "allocation statique"
pour :while (scanf("%9[^\n]", mot[i][j]) != 1) /* we want non empty things */ ; while ((c = getchar()) != '\n' && c != EOF) /* discard what remains in stdin */ ;
1.
le premier while s'assure que scanf renvoie 1 (c'est à dire qu'il a pu capturer un élément provenant de stdin correspondant au masque demandé), le scanf étant dans le test du while, il n'y a rien d'autre à mettre à la suite, et le point virgule reporté en 2ème ligne (après le commentaire) est une façon de montrer à un lecteur du code que c'est intentionnel
pour le masque"%9[^\n]"
, il :
- consomme dans stdin tous les caractères jusqu'au retour à la ligne exclu (y compris les espaces ou tabulations)
- en ignorant les caractères au delà du 9ème
si vraiment tu ne prends en compte que des mots et que si l'utilisateur saisit des espaces, cela signifie qu'il a terminé son mot, tu peux faire"%9s"
et les espaces et les caractères qui suivent éventuellement ne seront pas capturés par scanf qui limitera sa capture à 9 caractères où les espaces ou tabulations sont interdits et en laissant dans le flux stdin le reste
2.
le 2ème while est une façon répandue de vider le flux stdin en C (contenue dans le test du while sur le même principe), pour retirer les caractères qui peuvent y être laissés par scanf (notamment '\n' et/ou dans notre cas tous caractères saisis dépassant la taille de 9 caractères), de façon à ce qu'ils ne viennent pas à être consommés par le prochain appel à scanf (ou une autre fonction exploitant le flux stdin)
-
-
Ceci fonctionnera mieux et se rapprochera des standards:
#include <stdlib.h> #include <stdio.h> const unsigned int lignes = 2; const unsigned int colonnes = 3; int main(int argc, char *argv[]) { int i,j; // char vide; char mot[lignes][colonnes]; for(i = 0; i < lignes; i++) { for(j = 0; j < colonnes; j++) { printf("\n Rentre la valeur mot[%2d,%2d] \n",i,j); scanf("%c", &mot[i][j]); /* scanf("%c", &vide); */ } } for(i = 0; i < lignes; i++) { for(j = 0; j < colonnes; j++) { printf("%c", mot[i][j]); } } return EXIT_SUCCESS; }
Remarquons le caractère de formatage en ligne 29123abcjohand@bata:~/src/Cgcc -Wall -o fill_tab fill_tab.cll_tab
johand@bata:~/src/CCM/C$ echo 123abc | ./fill_tab
Rentre la valeur mot[ 0, 0]
Rentre la valeur mot[ 0, 1]
Rentre la valeur mot[ 0, 2]
Rentre la valeur mot[ 1, 0]
Rentre la valeur mot[ 1, 1]
Rentre la valeur mot[ 1, 2]
123abc
-
Gates gave ^W sold you the windows.
GNU gave us the whole house.(Alexandrin)