IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Problème de char *


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 7
    Points : 5
    Points
    5
    Par défaut Problème de char *
    Bonjour, j'ai un problème sur lequel je bûche depuis quelques jours :

    Je dois écrire une fonction qui inverse une chaine de caractères (Bonjour => ruojnoB). J'ai une en-tête imposée que je ne peux pas modifier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void ReverseString ( char * str, char * res  );
    Quand je fais mon code directement dans le main, je m'en sors, mais dès que je veux appeler la fonction, l'inversion fonctionne bien, mais je n'arrive pas à récupérer le bon pointeur dans res. Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    main()
    {
    	char* string = "Bonjour";
    	char* result = "Jourbon";
     
    	ReverseString ( string, result );
    	printf("Resultat : %s\n",result);
    }
     
     
    void ReverseString ( char * str, char * res  )
    {
    	char tmp[100];
    	int I = 0;
    	int J = strlen(str)-1;
     
    	while ( (tmp[I]=str[J-I]) != '\0')
    		I++;
     
            res=tmp;
    	printf("Resultat temporaire : %s\n",res);
    }
    Ce qui m'écrit :

    Resultat temporaire : ruojnoB
    Resultat : Jourbon


    Si vous pouviez m'aider ce serait sympa, d'avance merci !

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Plusieurs choses ne vont pas dans ton code :
    • tmp[i]=str[J-I]) ==> i n'est pas déclaré
    • while ( (tmp[i]=str[J-I]) != '\0') ==> une affectation et un test dans la même ligne, c'est dur à lire. Ce genre de choses devrait être faits en 2 lignes
    • char tmp[100]; puis res=tmp; ==> à la fin de ta fonction, ta variable locales tmp[100] n'existe plus et donc res pointe sur n'importe quoi (tu as même de la chance que cela ne crashe pas
    • ton paramètre char * str n'est pas modifié ==> il peut être transformé en const char *str pour le garantir et faire en sorte que le compilateur puisse faire plus de contrôles dessus
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 378
    Points : 23 672
    Points
    23 672
    Par défaut
    À mon avis, tu confonds plusieurs choses, problablement héritées d'autres langages (Java ?) :

    Citation Envoyé par oursDamour Voir le message
    Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    main()
    {
    	char* string = "Bonjour";
    	char* result = "Jourbon";
    
    	ReverseString ( string, result );
    	printf("Resultat : %s\n",result);
    }
    
    
    void ReverseString ( char * str, char * res  )
    {
    	char tmp[100];
    	int I = 0;
    	int J = strlen(str)-1;
    
    	while ( (tmp[I]=str[J-I]) != '\0')
    		I++;
    
            res=tmp;
    	printf("Resultat temporaire : %s\n",res);
    }
    • Le passage par référence implicite n'existe pas en C. Dans ton main, ce sont les valeurs de « string » et « result » qui sont transmises à ta fonction. Elles sont passées dans les arguments « str » et « res » qui, eux, agissent comme des variables locales ;
    • « Jourbon » est une chaîne définie en dur dans le code et est, à ce titre, constante. Tu ne peux pas modifier son contenu. « result » est un pointeur qui pointe cette chaîne en mémoire. Tu peux t'arranger pour que ce pointeur pointe autre chose, mais il faut que cet « autre chose » soit bien défini au préalable ;
    • Tu ne peux pas recopier une chaîne dans dans une autre avec « = » comme tu le ferais avec un type natif. Les chaînes, qui sont ici des chaînes de caractères, sont implémentées avec des tableaux de longueur arbitraire. C'est un pointeur vers ces tableaux que tu manipules. Quand tu fais « res = tmp », tu obtiens deux pointeurs différents qui pointent la même chaîne. Vois du côté de strncpy().


    Ce qu'il aurait fallu faire plutôt, c'est déclarer un buffer directement dans la fonction main() comme tu l'as fait dans ta fonction locale, et passer un pointeur vers ce buffer en temps que second argument de ta fonction, pour que celle-ci puisse directement y mettre le résultat.

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Je sais qu'il y a pas mal de trucs qui vont pas, et merci pour vos réponses, mais mon principal problème est que j'ai une fonction (dont je ne peux pas modifier l'en-tête) qui doit inverser une chaine, et qui prend 2 char* en paramètres.

    Le reste est "facultatif", ce que j'aimerais savoir, c'est comment inverser la chaine str, mettre le résultat dans res, et que le programme appelant aie le résultat (je ne sais pas si je suis assez clair, dites le moi ...)

  5. #5
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par oursDamour Voir le message
    Voici mon code :
    Tu peux déjà corriger ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
     
    -------------- Build: Debug in hello ---------------
     
    Compiling: main.c
    Linking console executable: bin\Debug\hello.exe
    C:\dev\hello\main.c:2: warning: return type defaults to `int'
    C:\dev\hello\main.c:2: warning: function declaration isn't a prototype
    C:\dev\hello\main.c: In function `main':
    C:\dev\hello\main.c:3: warning: initialization discards qualifiers from pointer target type
    C:\dev\hello\main.c:4: warning: initialization discards qualifiers from pointer target type
    C:\dev\hello\main.c:6: warning: implicit declaration of function `ReverseString'
    C:\dev\hello\main.c:7: warning: implicit declaration of function `printf'
    C:\dev\hello\main.c:8: warning: control reaches end of non-void function
    C:\dev\hello\main.c: At top level:
    C:\dev\hello\main.c:12: error: conflicting types for 'ReverseString'
    C:\dev\hello\main.c:6: error: previous implicit declaration of 'ReverseString' was here
    C:\dev\hello\main.c: In function `ReverseString':
    C:\dev\hello\main.c:15: warning: implicit declaration of function `strlen'
    C:\dev\hello\main.c:17: error: `i' undeclared (first use in this function)
    C:\dev\hello\main.c:17: error: (Each undeclared identifier is reported only once
    C:\dev\hello\main.c:17: error: for each function it appears in.)
    Process terminated with status 1 (0 minutes, 0 seconds)
    5 errors, 8 warnings
    Ensuite, il n'y a absolument pas besoin d'un tableau intermédiaire. Il suffit d'écrire directement dans le tableau de résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    #include <string.h>
     
    void ReverseString (char const str[], char res[])
    {
       int const len = strlen (str) - 1;
       int i = 0;
     
       while ((res[i] = str[len - i]) != '\0')
       {
          i++;
       }
    }
     
     
    /* test unitaire */
    #include <stdio.h>
    #include <assert.h>
     
    int main (void)
    {
       {
          char result[] = "?????";
          ReverseString ("", result);
          assert (strcmp ("", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("a", result);
          assert (strcmp ("a", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("ab", result);
          assert (strcmp ("ba", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("abc", result);
          assert (strcmp ("cba", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("ab\0c", result);
          assert (strcmp ("ba", result) == 0);
       }
     
       puts ("P A S S E D");
     
       return 0;
    }
    Comme souvent, les solutions les plus simples sont les meilleures...

    EDIT :
    Un peu trop simple. Ce code est faux. Voir la correction plus loin.
    Pas de Wi-Fi à la maison : CPL

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Il me semblait avoir dit clairement que je ne pouvais pas changer l'en-tête de la fonction qui est

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void ReverseString ( char * str, char * res  );

  7. #7
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par oursDamour Voir le message
    Il me semblait avoir dit clairement que je ne pouvais pas changer l'en-tête de la fonction qui est

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void ReverseString ( char * str, char * res  );
    Ça fonctionnera aussi avec cet en-tête...
    Pas de Wi-Fi à la maison : CPL

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Merci beaucoup à tous pour votre aide, j'ai pu résoudre mon problème !


  9. #9
    Membre éprouvé Avatar de orfix
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 707
    Points : 1 132
    Points
    1 132
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Tu peux déjà corriger ça :
    <...>
    Ensuite, il n'y a absolument pas besoin d'un tableau intermédiaire. Il suffit d'écrire directement dans le tableau de résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    #include <string.h>
     
    void ReverseString (char const str[], char res[])
    {
       int const len = strlen (str) - 1;
       int i = 0;
     
       while ((res[i] = str[len - i]) != '\0')
       {
          i++;
       }
    }
     
     
    /* test unitaire */
    #include <stdio.h>
    #include <assert.h>
     
    int main (void)
    {
       {
          char result[] = "?????";
          ReverseString ("", result);
          assert (strcmp ("", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("a", result);
          assert (strcmp ("a", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("ab", result);
          assert (strcmp ("ba", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("abc", result);
          assert (strcmp ("cba", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("ab\0c", result);
          assert (strcmp ("ba", result) == 0);
       }
     
       puts ("P A S S E D");
     
       return 0;
    }
    Comme souvent, les solutions les plus simples sont les meilleures...
    C'est quand même assez étrange que ça puisse fonctionner sans soucis prenant le premier cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    {
          char result[] = "?????";
          ReverseString ("", result);
          assert (strcmp ("", result) == 0);
    }
    len sera égale à -1 lors de la première itération la boucle ressemblera à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while ((res[0] = str[-1 - 0]) != '\0')
    c'est voulu ?
    peut être que cet exemple fera échoué le test unitaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    {
          char result[] = "?????";
          ReverseString ("ab"+1, result);
          assert (strcmp ("b", result) == 0);
          puts(result);
    }
    To start press any key. (reading screen) Where's the "any" key? I see Esc, Catarl, and Pig Up. There doesn't seem to be any "any" key. Wo! All this computer hacking is making me thirsty. I think I'll order a Tab. (presses TAB key). -- HOMER --

  10. #10
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par ssmario2 Voir le message
    C'est quand même assez étrange que ça puisse fonctionner sans soucis prenant le premier cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    {
          char result[] = "?????";
          ReverseString ("", result);
          assert (strcmp ("", result) == 0);
    }
    len sera égale à -1 lors de la première itération la boucle ressemblera à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while ((res[0] = str[-1 - 0]) != '\0')
    Très bonne remarque effectivement. Je n'avais pas vu ce problème. Le comportement est indéterminé (tombe en marche par hasard).

    La correction est simple. Il suffit de ne rien faire si len vaut 0, ce qui est finalement assez logique !

    EDIT : En fait, l'algo est carrément faux et il s'arrête sur un 0 imaginaire !

    ceci fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
    #include <string.h>
     
    void ReverseString (char const str[], char res[])
    {
       int const len = strlen (str);
       int i = 0;
       if (len > 0)
       {
          do
          {
             res[len - 1 - i] = str[i];
             i++;
          }
          while (i < len);
       }
       res[i] = '\0';
    }
     
    /* test unitaire */
    #include <stdio.h>
    #include <assert.h>
     
    int main (void)
    {
       {
          char result[] = "?????";
          ReverseString ("a" + 1, result);
          assert (strcmp ("", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("ab" + 1, result);
          assert (strcmp ("b", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("", result);
          assert (strcmp ("", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("a", result);
          assert (strcmp ("a", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("ab", result);
          assert (strcmp ("ba", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("abc", result);
          assert (strcmp ("cba", result) == 0);
       }
     
       {
          char result[] = "?????";
          ReverseString ("ab\0c", result);
          assert (strcmp ("ba", result) == 0);
       }
     
       puts ("P A S S E D");
     
       return 0;
    }
    Pas de Wi-Fi à la maison : CPL

  11. #11
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par oursDamour Voir le message
    Merci beaucoup à tous pour votre aide, j'ai pu résoudre mon problème !

    Attention le premier code est faux. Le second est correct.
    Pas de Wi-Fi à la maison : CPL

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème bête char*
    Par PP(Team) dans le forum C
    Réponses: 20
    Dernier message: 17/09/2008, 23h29
  2. Problème avec char
    Par choupinette116 dans le forum Débuter
    Réponses: 7
    Dernier message: 23/04/2008, 10h30
  3. Problème Cast char* en std::string
    Par inovah dans le forum SL & STL
    Réponses: 1
    Dernier message: 30/10/2007, 16h32
  4. Classe clavier problème avec char
    Par benjiprog dans le forum Langage
    Réponses: 30
    Dernier message: 30/06/2006, 16h04
  5. [C#] Problème de char[]
    Par GlorfindelHebril dans le forum Windows Forms
    Réponses: 11
    Dernier message: 01/04/2005, 14h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo