Tableau à double dimension

Résolu/Fermé
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 - Modifié par CrazyGeekMan le 4/01/2017 à 11:48
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 - 4 janv. 2017 à 17:51
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 :

#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!
A voir également:

2 réponses

[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 4/01/2017 à 14:18
Salut CrazyGeekMan,

char
représente un caractère et non une chaîne de caractères

en déclarant
char 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 des
char
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 un
char
par case (et ton
scanf("%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 sur
char
, pointant vers la zone mémoire allouée à chaque chaîne que tu veux stocker. Si tu le fais au moyen de
malloc()
, tu devras gérer aussi la libération de l'espace avec
free()
...

à ce moment là, ton
printf("%s",mot[i][j]);
sera également content et ne t'enverra plus de warning.


Dal
0
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 131
Modifié par CrazyGeekMan le 4/01/2017 à 14:45
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.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 4/01/2017 à 16:22
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 un
char *** 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 comme
char mot[ligne][colonne][10];
et c'est tout


Dal

P.S. :
malloc(sizeof(char) * 10);
peut s'écrire
malloc(10);
aussi en C, car le type
char
a, par définition, une taille de 1 byte
0
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 131 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
4 janv. 2017 à 17:13
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 !
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 4/01/2017 à 17:53
(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)
0
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 131 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
4 janv. 2017 à 17:51
Eh bien merci beaucoup!
Ces bases m'aideront par la suite :)
Bonne soirée :)
0
jisisv Messages postés 3645 Date d'inscription dimanche 18 mars 2001 Statut Modérateur Dernière intervention 15 janvier 2017 934
Modifié par jisisv le 4/01/2017 à 16:39
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 29
123abcjohand@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)
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
4 janv. 2017 à 15:49
salut jisisv,

Il me semble que notre ami veut stocker des chaînes de caractères dans son tableau à deux dimensions, et non un seul char.


Dal
0
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 131 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
4 janv. 2017 à 17:24
Oui c'est vrai.
Mais merci à vous, ces codes me permettent de mieux comprendre la structure du c ;)
0