Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 01/04/2017, à 13:54

plouf1221

Modifier un pointeur sur chaine passé en paramétre [Résolu]

Bonjour,

Toujours dans la même idée mais un peu différent, changer le pointeur sur chaine passé en paramétre es ce possible ?

#include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
 
 void make_uppercase(char *word) {
     for (char*p=word;*p;p++)
         if ( *p <= 'z' && *p >= 'a'  )
             *p += 'A' -'a';
 }                                                                                                                                                                                                            
 
 int main(int argc, char *argv[]) {
     char *chaine = "bon-jour";
     printf("%s\n", chaine);
     make_uppercase(chaine);
     printf("%s\n", chaine);
     return EXIT_SUCCESS;
 }

Ceci me génère : erreur de segmentation (code dumped)

J'essaye de faire le jeu du pendu ou plus de le refaire voici mon code :
Fonction implicite :

#include<stdio.h>                                                                                                                                                                                            
 #include<stdlib.h>
 #include<string.h>
 
 typedef struct _pendu S_pendu;
 typedef struct _pendu* pendu;
 
 struct _pendu {
     char tried[26];         // caractere déja testé on ne compte pas ce coup
     int remaining_letters;  // nbr lettres restantes
     int remaining_tries;    // nbr tentatives restantes
     char *word;             // mot à trouver
 };
 
 void S_pendu_init(pendu P, char *word, int nb_tries) {
     int len = strlen(word);
     char first = word[0];
     char last = word[len - 1];
     P->word = word;
     P->remaining_tries = nb_tries;
     P->remaining_letters = len;
     for (int i = 0; i < 26; i++) {
         P->tried[i] = 0;    // Vaut 1 lorsque la i lettre a été testée et 0 sinon
     }
     if (len <= 1) {
         P->remaining_letters = 0;
         return;
 
     P->remaining_letters -= 2;  // premiere et derniere lettre connus
     }
     if ( (first >= 'A' ) && (first) <= 'Z' )
             P->tried[first - 'A'] = 1;
 
     if ( (last >= 'A' ) && (last) <= 'Z' )
             P->tried[last - 'A'] = 1;
 
     for (int i = 1; i <= len -2; i++) {
         char c = word[i];
     if ( (c == last) || (c == first) || (c < 'A') || (c > 'Z') )
             P->remaining_letters--;
     }
 
     printf("word = %s remaining_letters = %d\n", P->word, P->remaining_letters);
 }
 
 void make_uppercase(char *word) {
     for (char *p = word; *p != '\0'; p++)
         if (*p >= 'a'&& *p <= 'z')
             *p += 'A' - 'a';
 }

Voici le main :

int main(int argc, char* argv[]) {
     S_pendu P;                                                                                                                                                                                               
     char *word;
     int nb_tries;
 
     if (argc >= 2)
         word = argv[1];
     else
         word = "Exeptionnellement";
 
     if (argc >=3)
         nb_tries = atoi (argv[2]);
     else
         nb_tries = 7;
 
     printf("Jeu du pendu. Vous avez le droit a %d essaie.\n", nb_tries);
 
     make_uppercase(word);
 
     S_pendu_init(&P, word, nb_tries);
 
     return EXIT_SUCCESS;
 }

C'est le meme mécanisme dans les deux cas car word est déclaré comme :
char *word et non comme une chaine de caractere "pure".
Et dans mon début de pendu je n'ai pas d'erreur de segmentation à la seul condition de mettre le mot par défaut
"Exeptionnellement" le tout en majuscule c'est a dire EXEPTIONNELLEMENT.

Es ce que quelqu'un pourrai m'expliquer :
- pourquoi dans le test.c j'ai une erreur et dans le pendu.c j'ai aucune erreur de segmentation alors que j'ai l'impression que l'on fait
  exactement la même chose
- pourquoi faut t'il mettre le mot Exeptionnellement le mot en majuscule pour éviter une erreur de segmentation.

Merci pour votre aide.

Dernière modification par plouf1221 (Le 04/04/2017, à 11:31)

Hors ligne

#2 Le 01/04/2017, à 14:16

grigouille

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

plouf1221 a écrit :
         word = "Exeptionnellement";
 

Tu veux modifier une zone mémoire non modifiable -> segfault.


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#3 Le 01/04/2017, à 14:17

plouf1221

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

J'ai trouvé la réponse à la deuxième question :
La fonction make_uppercase ne se déclenche pas si l'on mets toutes les lettres en majuscules.
Autrement dit cette fonction ne fait rien comme si elle n'existait pas.
C'est bien la même erreur dans un cas comme dans l'autre.

Hors ligne

#4 Le 01/04/2017, à 14:22

plouf1221

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

Si je déclare word comme ceci :
char word[] alors je peux la modifier. La preuve le code de pingouinux :

#include<stdio.h>                                                                                                                                                                                           
#include<stdlib.h>
#include<string.h>

 void make_uppercase(char *word) {
     for (char*p=word;*p;p++)
         if ( *p <= 'z' && *p >= 'a'  )
             *p += 'A' -'a';
 }
 
 int main(int argc, char *argv[]) {
     char chaine[] = "bon-jour";
     printf("%s\n", chaine);
     make_uppercase(chaine);
     printf("%s\n", chaine);
     return EXIT_SUCCESS;
 }

La chaine est correctement mis en majuscule.

Hors ligne

#5 Le 01/04/2017, à 14:35

grigouille

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

copie les chaînes :

int main(int argc, char* argv[]) {
     S_pendu P;                                                                                                                                                                                               
     char word[1024];
     int nb_tries;
 
     if (argc >= 2)
	     strcpy(word, argv[1]);
     else
	     strcpy(word,"Exeptionnellement");
 
     if (argc >=3)
         nb_tries = atoi (argv[2]);
     else
         nb_tries = 7;
 
     printf("Jeu du pendu. Vous avez le droit a %d essaie.\n", nb_tries);
 
     make_uppercase(word);
 
     S_pendu_init(&P, word, nb_tries);
 
     return EXIT_SUCCESS;
 }

Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#6 Le 01/04/2017, à 14:39

plouf1221

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

Ok je vais copier les chaines mais cela ne répond pas à la question.
Dans le cas général ou word = argv[1] ?
Je risque de me retrouvé exactement dans la même situation que la première c'est a dire :

#include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
 
 void make_uppercase(char *word) {
     for (char*p=word;*p;p++)
         if ( *p <= 'z' && *p >= 'a'  )
             *p += 'A' -'a';
 }                                                                                                                                                                                                            
 
 int main(int argc, char *argv[]) {
     char *chaine = "bon-jour";
     printf("%s\n", chaine);
     make_uppercase(chaine);
     printf("%s\n", chaine);
     return EXIT_SUCCESS;

Hors ligne

#7 Le 01/04/2017, à 14:43

grigouille

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

grigouille a écrit :
     if (argc >= 2)
	     strcpy(word, argv[1]);
     else
	     strcpy(word,"Exeptionnellement");

Tu as lu mon code ? Tu comprends ce que tu fais ?


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#8 Le 01/04/2017, à 14:47

plouf1221

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

Je devine, tu fais pratiquement la même chose que moi
si argc >= 2
word <-argv[1]

C'est équivalent non ?

if (argc >= 2)
         strcpy(word, argv[1]);

Après c'est juste le découpage des cas possible qui est différent tu utilises strcpy et pas moi.
Mais au final cela ne change pas à ma connaissance quelque chose de particulier, sinon éclaire moi.

Dernière modification par plouf1221 (Le 01/04/2017, à 14:55)

Hors ligne

#9 Le 01/04/2017, à 15:10

plouf1221

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

J'ai utilisé les strcpy et mis en minuscule exeptionnellement sauf la premiere lettre
j'ai exactement la même erreur (core dumped).
Donc comme je vous disait, ca ne change pas grand chose au final.

Hors ligne

#10 Le 01/04/2017, à 17:33

grigouille

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

Sans le code, on ne peut rien te dire.


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#11 Le 01/04/2017, à 17:44

pingouinux

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

Bonjour,

grigouille a écrit :

Sans le code, on ne peut rien te dire.

Si, on peut dire qu'exeptionnellement ne s'écrit ainsi qu'exceptionnellement.

Hors ligne

#12 Le 03/04/2017, à 12:00

plouf1221

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

Le code avec les strcpy.

Fonction implicite :

#include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
 
 typedef struct _pendu S_pendu;
 typedef struct _pendu* pendu;
 
 struct _pendu {
     char tried[26];         // caractere déja testé on ne compte pas ce coup
     int remaining_letters;  // nbr lettres restantes
     int remaining_tries;    // nbr tentatives restantes
     char *word;             // mot à trouver
 };
 
 void S_pendu_init(pendu P, char *word, int nb_tries) {
     int len = strlen(word);                                                                                                                                                                                  
     char first = word[0];
     char last = word[len - 1];
     P->word = word;
     P->remaining_tries = nb_tries;
     P->remaining_letters = len;
     for (int i = 0; i < 26; i++) {
         P->tried[i] = 0;    // Vaut 1 lorsque la i lettre a été testée et 0 sinon
     }   
     if (len <= 1) {
         P->remaining_letters = 0;
         return;
 
     P->remaining_letters -= 2;  // premiere et derniere lettre connus
     }   
     if ( (first >= 'A' ) && (first) <= 'Z' )
             P->tried[first - 'A'] = 1;
 
     if ( (last >= 'A' ) && (last) <= 'Z' )
             P->tried[last - 'A'] = 1;
 
     for (int i = 1; i <= len -2; i++) {
         char c = word[i];
     if ( (c == last) || (c == first) || (c < 'A') || (c > 'Z') )
             P->remaining_letters--;
     }   
 
     printf("word = %s remaining_letters = %d\n", P->word, P->remaining_letters);
 }
 
 void make_uppercase(char *word) {
     for (char *p = word; *p != '\0'; p++)
         if (*p >= 'a'&& *p <= 'z')
             *p += 'A' - 'a';
 }

Le main :

int main(int argc, char* argv[]) {                                                                                                                                                                           
     S_pendu P;
     char *word;
     int nb_tries;
 
     if (argc >= 2)
         strcpy(word,argv[1]);
     else
         strcpy(word,"Exptionnelememt");
 
     if (argc >=3)
         nb_tries = atoi (argv[2]);
     else
         nb_tries = 7;
 
     printf("Jeu du pendu. Vous avez le droit a %d essaie.\n", nb_tries);
 
     make_uppercase(word);
 
     S_pendu_init(&P, word, nb_tries);
 
     return EXIT_SUCCESS;
 }

Dernière modification par plouf1221 (Le 03/04/2017, à 12:00)

Hors ligne

#13 Le 03/04/2017, à 15:29

plouf1221

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

Je veux juste savoir comment on fait en c pour modifier la chaine "bon-jour" via une fonction

#include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
 
 void make_uppercase(char *word) {
     for (char*p=word;*p;p++)
         if ( *p <= 'z' && *p >= 'a'  )
             *p += 'A' -'a';
 }                                                                                                                                                                                                            
 
 int main(int argc, char *argv[]) {
     char *chaine = "bon-jour";
     printf("%s\n", chaine);
     make_uppercase(chaine);
     printf("%s\n", chaine);
     return EXIT_SUCCESS;
 }

Avec ce code cela me génére un erreur (core dumped)

Hors ligne

#14 Le 03/04/2017, à 19:51

grigouille

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

grigouille a écrit :
     char word[1024];

Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#15 Le 04/04/2017, à 11:30

plouf1221

Re : Modifier un pointeur sur chaine passé en paramétre [Résolu]

C'est impossible de le modifier, c'est un pointeur constant.
Obliger de la déclarer en tableau de char pour le modifier.

Hors ligne