Partage
  • Partager sur Facebook
  • Partager sur Twitter

Tableau double dimension et double pointeurs

    1 juin 2021 à 19:16:30

    Bonsoir, j'essaye de faire passer un tableau 2D dans une fonction mais je y arrive pas.. Je ne comprends pas comment faire pour que ce tableau[][] passe dans en paramètre de la fonction *ft_strjoin qui prend en paramètre un double pointeur ** ! Si vous pouvez m'éclairer ça serait super ! (En sachant que size représente la taille de strs et que Strjoin est une fonction qui va concatener l'ensemble des chaines de caractères pointées par strs en les séparants à l'aide de sep)


    Merci d'avance !

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <time.h>
    #include <unistd.h>
    
    
    int        ft_strlen(char *str)
    {
        int n;
        
        n = 0;
        while (str[n])
            n++;
        return (n);
    }
    
    char    *ft_strcpy(char *dest, char *src)
    {
        int i;
        
        i = -1;
        while (src[++i])
            dest[i] = src[i];
        dest[i] = '\0';
        return (dest);
    }
    
    char    *ft_strjoin(int size, char **strs, char *sep)
    {
        char    *dest;
        int        i;
        int        j;
        
        i = 0;
        j = 0;
        while (i < size)
            j += ft_strlen(strs[i++]);
        if (size > 0)
            j += (size - 1) * ft_strlen(sep);
        dest = malloc((j + 1) * sizeof(char));
        if (!dest)
            return (NULL);
        i = 0;
        j = 0;
        while (i < size)
        {
            ft_strcpy(dest + j, strs[i]);
            j += ft_strlen(strs[i]);
            if (++i < size)
                j += dest + j + ft_strlen(sep) - ft_strcpy(dest + j, sep);
        }
        dest[j] = '\0';
        return (dest);
    }
    
    int main()
    {
        char tab[3][5] = {"hey", "hello", "hola"};
        char sep[6] ="allo";
        int size = 3;
        
        char *retour = ft_strjoin(size, tab, sep);
        
        printf("%s", retour);
        
        return 0;
    }
    



    -
    Edité par NoéDormoy 1 juin 2021 à 19:22:50

    • Partager sur Facebook
    • Partager sur Twitter
      1 juin 2021 à 19:31:40

      Bonjour

      tu ne peux pas donner un char[][] comme argument à une fonction qui attend un paramètre de type char **.

      Tu dois lui donner un char * [] ou un char ** …

      Par exemple dans ton main avec un minimum de modifications :

      int main()
      {
          char* tab[3]= {"hey", "hello", "hola"};
          char sep[6] ="allo";
          int size = 3;
           
          char *retour = ft_strjoin(size, tab, sep);
           
          printf("%s", retour);
           
          return 0;
      }
      

      Pointeurs et tableaux sont deux choses différentes.

      • Partager sur Facebook
      • Partager sur Twitter
        1 juin 2021 à 19:53:42

        Merciii ! J'avais pas compris qu'il fallait faire comme ça :)
        • Partager sur Facebook
        • Partager sur Twitter
          1 juin 2021 à 22:14:02

          Si tu voulais garder ton tableau de tableau de 5 char. il fallait changer le prototype de la fonction en :

          char    *ft_strjoin(int size, char(*strs)[5], char *sep)

          Mais bon, ça marche que pour des tableaux de 5 chars.

          -
          Edité par rouloude 1 juin 2021 à 22:15:35

          • Partager sur Facebook
          • Partager sur Twitter
            2 juin 2021 à 9:36:27

            Si c'est un tableau 2D, il faut donner les deux tailles, non ? (Ou bien en fixer une, comme dans la solution de rouloude.)

            -
            Edité par robun 2 juin 2021 à 9:38:26

            • Partager sur Facebook
            • Partager sur Twitter
              2 juin 2021 à 10:23:18

              robun a écrit:

              Si c'est un tableau 2D, il faut donner les deux tailles, non ? (Ou bien en fixer une, comme dans la solution de rouloude.) 

              Son tableau à bien les deux tailles : 

              char tab[3][5] = {"hey", "hello", "hola"};    

              C'est un tableau de trois tableaux de cinq char. 

              Quand on l'envoi à une fonction, on envois son adresse, donc le paramètre est de type pointeur sur tableau de cinq char.

              Comme c'est un pointeur on ne connait pas le nombre de tableau, qui par conséquent doit être passé en paramètre.

              Il y a la possibilité de passer par un simple pointeur et d'envoyer les deux tailles ex :

              #include <stdio.h>
              
              void ft_print_tab(char *strs, int x, int y)
              {
                  for(int i=0; i<x; i++) puts(strs+i*y);
              }
              
              int main(void)
              {
                  char tab[3][6] = {"hey", "hello", "hola"};
              
                  ft_print_tab(tab[0], 3, 6);
              
                  return 0;
              }

                (Mon exemple est avec des tableaux de 6 char, parce que 5 char pour le "hello" c'est un peu court) !

              -
              Edité par rouloude 2 juin 2021 à 10:24:10

              • Partager sur Facebook
              • Partager sur Twitter
                2 juin 2021 à 12:19:32

                rouloude a écrit:

                Quand on l'envoi à une fonction, on envois son adresse, donc le paramètre est de type pointeur sur tableau de cinq char.

                Le pointeur envoyé est de type "pointeur sur tableau de cinq char", mais lorsque la fonction le récupère il est recopié dans un "pointeur de pointeur de char", non ? Du coup j'ai du mal à comprendre pourquoi il n'y a pas besoin de transmettre le 5 à la fonction (je comprends que si la fonction utilise un pointeur sur tableau de cinq char, ça marche, mais je ne comprends pas pourquoi c'est le cas).
                • Partager sur Facebook
                • Partager sur Twitter
                  2 juin 2021 à 13:12:04

                  Salut,

                  En fait, il faut comprendre ce qui est demandé en termes de mémoire

                  char tab[3][6] = {"hey", "hello", "hola"};


                  est une déclaration qui définit un tableau consistant en une zone mémoire contiguë de 18 chars où on peut stocker 3 chaînes de 5 char au plus. Grâce au sucre syntaxique du C, les chaînes sont initialisées et l'espace mémoire contigu est rempli. La contiguïté du stockage en mémoire des informations est illustrée par la fonction ft_print_tab() proposée par rouloude.

                  char* tab[3]= {"hey", "hello", "hola"};

                  est une déclaration qui définit un tableau de 3 pointeurs sur char, où on peut stocker ... 3 pointeurs sur char dans une zone contiguë de la mémoire. Le contenu pointé est stocké ailleurs en mémoire. Le sucre syntaxique du C permet l'initialisation de ce tableau d'une manière identique, mais il se passe quelque chose de totalement différent.

                  Evidemment, on n'accède pas aux chaînes contenues dans ces deux cas de la même façon.

                  -
                  Edité par Dlks 2 juin 2021 à 13:13:24

                  • Partager sur Facebook
                  • Partager sur Twitter
                    2 juin 2021 à 13:32:20

                    robun a écrit:

                    mais lorsque la fonction le récupère il est recopié dans un "pointeur de pointeur de char", non ? 

                    La fonction récupère l'adresse du tableau et l'affecte au paramètre. paramètre est une variable locale à la fonction qui a le type déclaré dans le prototype de la fonction. Son type ne change pas.

                    Si tu avais mis le type pointeur de pointeur sur char comme type dans l'exemple tu aurais un Warning de type incompatible.

                    Exemple sur un tableau de 4 tableaux de ce que tu veux :

                       --- 
                      | P | Le pointeur (paramètre de la fonction) contient l'adresse du tableau  
                       --- 
                        |
                        |
                        |
                        |
                        |    L1              L2              L3              L4
                        |   --- --- --- ---|--- --- --- ---|--- --- --- ---|--- --- --- ---|---
                        '->| 0 | 1 | 2 | 3 | 0 | 1 | 2 | 3 | 0 | 1 | 2 | 3 | 0 | 1 | 2 | 3 | hors tableau 
                            --- --- --- ---|--- --- --- ---|--- --- --- ---|--- --- --- ---|---

                    Il n'y a qu'un pointeur, le paramètre de la fonction.

                    Pour que ce soit un pointeur de pointeur, il faudrait deux pointeurs, ce qui n'est pas le cas.

                    -
                    Edité par rouloude 2 juin 2021 à 13:45:44

                    • Partager sur Facebook
                    • Partager sur Twitter
                      2 juin 2021 à 14:49:48

                      rouloude a écrit:

                      Si tu avais mis le type pointeur de pointeur sur char comme type dans l'exemple tu aurais un Warning de type incompatible.

                      Mais c'est bien un pointeur de pointeur de char qui est indiqué dans le prototype de la fonction :

                      char *ft_strjoin(int size, char **strs, char *sep)
                                                     -là-

                      Alors oui, un pointeur de pointeur de char, c'est un pointeur. Mais je ne vois pas où la fonction a l'information sur la longueur.

                      Mais je vous crois, hein ! Après, ce n'est pas grave si je ne comprends pas, je ne compte pas utiliser de choses aussi subtiles...

                      -
                      Edité par robun 2 juin 2021 à 14:50:37

                      • Partager sur Facebook
                      • Partager sur Twitter
                        2 juin 2021 à 15:09:40

                        robun a écrit:

                        Mais c'est bien un pointeur de pointeur de char qui est indiqué dans le prototype de la fonction :

                        char *ft_strjoin(int size, char **strs, char *sep)
                                                       -là-

                        Alors oui, un pointeur de pointeur de char, c'est un pointeur. Mais je ne vois pas où la fonction a l'information sur la longueur.


                        Comme la fonction traite des chaînes, elle a juste besoin de savoir combien il y en a (paramètre size).

                        Elle peut alors passer d'un pointeur à l'autre sans dépasser le nombre size.

                        Quand à la taille des chaînes pointées par chaque pointeur, elle la détermine avec strlen.

                        Elle n'a besoin de rien d'autre pour fonctionner.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          2 juin 2021 à 16:16:55

                          Son prototype n'est pas bon pour un tableau de tableau, c'est pour cela qu'il est venu poser sa question.

                          Moi je parlais en considérant le bon prototype pour un tableau de tableau de 5 char :

                          char    *ft_strjoin(int size, char(*strs)[5], char *sep)

                          J'aurais du le préciser.

                          Son prototype fonctionne avec un tableau de pointeur (solution White Crow).

                          -
                          Edité par rouloude 2 juin 2021 à 16:20:53

                          • Partager sur Facebook
                          • Partager sur Twitter
                            2 juin 2021 à 16:45:03

                            Merci a tous pour les explications supplémentaires :) !!
                            • Partager sur Facebook
                            • Partager sur Twitter
                              2 juin 2021 à 16:55:43

                              Le plus est de se souvenir qu'en C on passe les arguments par copie. Pour éviter d'avoir à copier potentiellement de grandes quantité de données, tout argument de type tableau est, de manière totalement transparente, transformé en pointeur sur le premier élément.

                              Cela signifie que quel que soit le type T, les deux déclarations suivantes sont totalement équivalentes :

                              void foo( T array[] );
                              
                              void foo( T *array);

                              Ici on s'en fout de la taille car quelle que soit la taille, le premier élément aura toujours le même type.

                              Les déclarations suivantes le sont tout autant :

                              void foo( T array[3] );
                              
                              void foo( T array[5] );
                              
                              void foo( size_t n, T array[n] );
                              
                              void foo( size_t n, T array[*] );
                              

                              Il y a cependant une petite nuance avec :

                              void foo( T array[static 5] );
                              

                              Cette dernière déclaration indique au compilateur que l'argument est un pointeur sur le premier élément d'un tableau d'au moins 5 éléments.

                              Maintenant si tu as un tableau 2D = un tableau de tableau, de la même manière il sera transformé en pointeur sur son premier élément, premier élément qui sera de type tableau …

                              On passe donc de `T array[X][Y]` à pointeur sur le premier élément de type `T [Y]` ce qui se traduit en `T (*array)[Y]`.




                              • Partager sur Facebook
                              • Partager sur Twitter
                                2 juin 2021 à 18:28:14

                                rouloude a écrit:

                                Son prototype n'est pas bon pour un tableau de tableau, c'est pour cela qu'il est venu poser sa question.

                                Moi je parlais en considérant le bon prototype pour un tableau de tableau de 5 char :

                                char    *ft_strjoin(int size, char(*strs)[5], char *sep)
                                Ah oui, cette fois je comprends ! (J'étais intervenu parce que NoéDormoy avait dit avoir compris juste avant ton message où tu donnais le bon prototype, donc je pensais qu'il était resté sur l'ancien. J'aurais dû être plus précis moi aussi.)
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  3 juin 2021 à 16:08:47

                                  robun a écrit:

                                  rouloude a écrit:

                                  Son prototype n'est pas bon pour un tableau de tableau, c'est pour cela qu'il est venu poser sa question.

                                  Moi je parlais en considérant le bon prototype pour un tableau de tableau de 5 char :

                                  char    *ft_strjoin(int size, char(*strs)[5], char *sep)

                                  Ah oui, cette fois je comprends ! (J'étais intervenu parce que NoéDormoy avait dit avoir compris juste avant ton message où tu donnais le bon prototype, donc je pensais qu'il était resté sur l'ancien. J'aurais dû être plus précis moi aussi.)


                                  Mon prototype marchait ! C'est juste ma déclaration de mon tableau dans le main qui était mauvaise !
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    3 juin 2021 à 16:38:48

                                    NoéDormoy a écrit:

                                    Mon prototype marchait ! C'est juste ma déclaration de mon tableau dans le main qui était mauvaise !

                                    On n'a pas dit le contraire, il marchait à condition de lui envoyer un tableau de pointeur sur char !

                                    Mais pour un tableau de tableau de char, il ne marchait pas ! C'est pourtant ce type de tableau que tu voulais envoyer à ta fonction dans ton code et dans ton message :

                                    NoéDormoy a écrit:

                                    j'essaye de faire passer un tableau 2D dans une fonction mais je y arrive pas.

                                    Mais en fait tu voulais lui envoyer un simple tableau de pointeurs sur char et la on ne parle plus de tableau 2D (tableau de tableau). Ce n'est pas la même chose.



                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      4 juin 2021 à 16:52:19

                                      rouloude a écrit:

                                      NoéDormoy a écrit:

                                      Mon prototype marchait ! C'est juste ma déclaration de mon tableau dans le main qui était mauvaise !

                                      On n'a pas dit le contraire, il marchait à condition de lui envoyer un tableau de pointeur sur char !

                                      Mais pour un tableau de tableau de char, il ne marchait pas ! C'est pourtant ce type de tableau que tu voulais envoyer à ta fonction dans ton code et dans ton message :

                                      NoéDormoy a écrit:

                                      j'essaye de faire passer un tableau 2D dans une fonction mais je y arrive pas.

                                      Mais en fait tu voulais lui envoyer un simple tableau de pointeurs sur char et la on ne parle plus de tableau 2D (tableau de tableau). Ce n'est pas la même chose.

                                      Oui C'est vrai haha je me suis mal exprimé ;) !



                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      Tableau double dimension et double pointeurs

                                      × 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.
                                      • Editeur
                                      • Markdown