Rechercher : dans
Par :

[C] pointeur sur chaîne de caractères

Dernière réponse le 7 nov 2007 à 19:03:25 Onde2Choc, le 21 aoû 2004 à 18:03:17 
 Signaler ce message aux modérateurs

Dans mon long apprentissage du langage C, je suis rendu manipulations de chaînes de caractères avec des pointeurs (chapitre 10/21). Voilà un extrait de code donné en exemple pour contrôler une ligne blanche avec gets() :

while( *(pointeur = gets(input)) != NULL)
{ (instructions) } 
/*reste du programme*/

Mais quand j'entre ces mêmes lignes dans mon compilateur, Dev C++, le compilo lui même ne dis rien mais quand je lance le programme ça cause une erreur ("Le système à repéré une erreur sérieuse. Voulez-vous envoyer le journal etc..."). Est-ce grave docteur ? D'où ça vient ?


BOOM !
Laissez se propager l'onde de choc...

Meilleures réponses pour « [C] pointeur sur chaîne de caractères » dans :
Langage C - Les chaînes de caractères Voir Qu'est-ce qu'une chaîne de caractères ? Une chaîne de caractères (appelée string en anglais) est une suite de caractères, c'est-à-dire un ensemble de symboles faisant partie du jeu de caractères, défini par le code ASCII. En langage C, une chaîne...
Les chaînes de caractères en C++ VoirQu'est-ce qu'une chaîne de caractères ? Une chaîne de caractères (appelée string en anglais) est une suite de caractères, c'est-à-dire un ensemble de symboles faisant partie du jeu de caractères, défini par le code ASCII. En langage C++, une...
VBScript - Les fonctions de chaînes de caractères VoirLes fonctions de chaînes de caractères Fonction Description Filter(InputStrings, Value[, Include[, Compare]]) Sélectionne des chaînes de caractères parmi un tableau de chaînes...
PHP - Expressions régulières VoirQu'est-ce qu'une expression régulière? Les expressions régulières sont des modèles créés à l'aide de caractères ASCII permettant de manipuler des chaînes de caractères, c'est-à-dire permettant de trouver les portions de la chaîne correspondant au...

1

Onde2Choc, le 21 aoû 2004 à 19:08:54

Personne d'assez cultivé et sympa à la fois pour me répondre ?


BOOM !
Laissez se propager l'onde de choc...

Répondre à Onde2Choc

2

Onde2Choc, le 21 aoû 2004 à 19:33:45

Il y en a qui connaissent le C ici ou me*de ?


BOOM !
Laissez se propager l'onde de choc...

Répondre à Onde2Choc

6

kilian, le 21 aoû 2004 à 21:45:22

On est sensés rappliquer au garde à vous??? :-|

Kilian, débutant en tâche de fond.....

Répondre à kilian

7

Guki, le 21 aoû 2004 à 21:51:59

Je crois que l'impatience l'a fait virer dans le dark side ce qui n'arrangera pas ses affaires. ;-)

Répondre à Guki

8

kilian, le 21 aoû 2004 à 21:59:10

:-)

Kilian, débutant en tâche de fond.....

Répondre à kilian

3

josch83, le 21 aoû 2004 à 20:06:12

C'est quoi les instructions (instructions) a l'intérieur de ta boucle.
Si tu nous fil le code on comprendra peut-être un peu mieux.

"There are only 10 types of peoples in the world : Those who understand binary and those who don't."

Répondre à josch83

4

Onde2Choc, le 21 aoû 2004 à 20:15:04

while( *(pointeur = gets(input)) == NULL)
{ 
printf("Vous n'avez pas entré de chaîne. Alors cette fois écris quelque chose : ");
gets(phrase);
 } 
/*reste du programme*/


Par exemple... Mais c'est pas les instructions de la boucle while qui font planter, j'ai vérifié...

BOOM !
Laissez se propager l'onde de choc...

Répondre à Onde2Choc

5

Guki, le 21 aoû 2004 à 21:31:55

On peut avoir le main ou c'est trop long? Le pointeur il pointe sur un autre pointeur?

*(pointeur) pour moi c'est la valeur pointé qui doit être égale à un pointeur NULL

Répondre à Guki

9

Jolkdarr, le 21 aoû 2004 à 23:05:47

Hello !

Règle de base :
il ne faut jamais utiliser un pointeur sans le vérifier au préalable.

Le code correct est donc :

while( (pointeur = gets(input)) == NULL)
{
printf("Vous n'avez pas entré de chaîne. Alors cette fois écris quelque chose : ");
}
/*reste du programme*/

Répondre à Jolkdarr

10

Onde2Choc, le 22 aoû 2004 à 08:39:09

J'ai testé le même code sur mon win98 et il fonctionne parfaitement... En effet guki c'est la valeur de l'adresse pointée qui doit être nulle, ce qui est le cas lorsque tu entres une ligne blanche : le pointeur pointe sur un caractère nul.
Par contre Jolkdarr, le pointeur de ton code, tel que tu l'utilises, est juste initialisé pour pointer sur input, et c'est l'adresse mémoire qui va être testée... Or comme le caractère nul est tout de même stocké en mémoire, ce test donnera toujours 0, c'est à dire que le while ne fonctionnera jamais. Voila les instructions d'initialisations :

char input[256], *pointeur = input;
Pour la version de mon win98 et
char input[256], *pointeur;
pointeur = input;
Pour la version winXP, j'ai raccourci le tout sur mon win98. input étant un pointeur vers input[0], seule l'adresse mémoire intéresse le pointeur donc pas de "*" devant pointeur.

Pour Kilian et Guki, une seule chose à dire : tschhh... hoooo... tschh.... hooooo.... :-) la patience n'est pas la 1ere de mes qualités dans certaines situations !

BOOM !
Laissez se propager l'onde de choc...

Répondre à Onde2Choc

11

Guki, le 22 aoû 2004 à 08:56:03

Bon si je reprend les bouts d'information:

char input[256];
char *pointeur;

pointeur = &input[0];
while( *(pointeur = gets(input)) == NULL)
{
printf("Vous n'avez pas entré de chaîne. Alors cette fois écris quelque chose : ");
gets(phrase);
}

donc *(pointeur) est la valeur pointée donc un char qui devrait être égale à un pointeur (adresse) NULL soit en entier 32 bits sur un CPU 32 bits qui contient le nombre 0 je crois que ça pose problème au niveau de la comparaison.

Répondre à Guki

12

Onde2Choc, le 22 aoû 2004 à 10:00:29

Si ça peut aider, mon tapis de souris est rouge.


BOOM !
Laissez se propager l'onde de choc...

Répondre à Onde2Choc

13

Ravachol, le 22 aoû 2004 à 10:07:00

Ben voila l'erreur ... gets ne fonctionne qu'avec des tapis bleu sous zindozs.

La pensée ne commence qu'avec le doute.
ROGER MARTIN DU GARD

Répondre à Ravachol

14

Guki, le 22 aoû 2004 à 10:08:17

Remplace NULL par 0 pour voir.

Répondre à Guki

15

Jolkdarr, le 22 aoû 2004 à 11:22:16

Hello !

Manifestement, je n'ai pas été assez clair. Je répète donc :
Règle : NE JAMAIS UTILISER UN POINTEUR SANS LE TESTER.

gets() renvoie un pointeur NULL si un problème est rencontré (comme lecture d'un EOF par exemple). Il faut donc absolument tester le pointeur avant toute utilisation.

Exemple de code qui marche sauf dans le cas où le pointeur renvoyé est NULL (par exemple, tapez CTRL+D sous linux au moment d'entrer la chaîne => segmentation fault):

#include <stdio.h>

int main(int N, char * A[])
{
char input[500];
char* pointeur;

while (*(pointeur = gets(input)) == '\0')
{
printf("Entrez une chaine svp.\n");
}

printf("Vous avez entre %s\n", input);

return 0;
}


Exemple de code qui marche dans tous les cas (même quand on entre CTRL+D) :

#include <stdio.h>

int main(int N, char * A[])
{
char input[500];
char* pointeur;

/* test du pointeur avant son utilisation (obligatoire!) */
while ((pointeur = gets(input)) == NULL || *pointeur == '\0')
{
printf("Entrez une chaine svp.\n");
}

printf("Vous avez entre %s\n", input);

return 0;
}


J'espère que c'est plus clair cette fois.

Take care !

Répondre à Jolkdarr

16

Jolkdarr, le 22 aoû 2004 à 12:00:01

Pour mémoire :

#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif

Si le compilateur n'a rien dit, c'est qu'il a compilé en tant que compilateur C++ et non C. Par conséquent, changer NULL par 0 ne changera rien car c'est déjà la valeur de la macro.

Take care !

Répondre à Jolkdarr

17

Guki, le 22 aoû 2004 à 13:49:35

Ah bon parce que C++ implémente différemment NULL je croyais que la base était le C faudrait qu'on m'explique.

ISO/IEC 14882:1998
20.4.6
...
Header <cstring>
The contents are the same as the Standard C library header <string.h>, ...

Bien essayé quand même. ;-)

Répondre à Guki

18

Guki, le 22 aoû 2004 à 14:04:35

Bon j'ai parlé trop vite ça m'apprendra effectivement C++ ne fait pas la même chose ce qui semble étrange tout de même.

PS: pas taper merci.

Répondre à Guki

19

Hot Metal, le 22 aoû 2004 à 14:31:30

Salut

Ne jamais utiliser gets(); mais plutot fgets();.

extrait du man de linux.

N'utilisez jamais gets().  Comme il est impossible de savoir à l'avance
       combien de caractères seront lus par gets(), et comme  celui-ci  écrira
       tous les caractères lus, même s'ils débordent du buffer, cette fonction
       est extrèmement dangereuse à utiliser. On a déjà  utilisé  ce  dysfonc-
       tionnement pour créer des trous de sécurité.  UTILISEZ TOUJOURS fgets()
       A LA PLACE DE gets().


Pour le probleme
#include <stdio.h> 
 
int main(int N, char * A[]) 
{ 
 char input[500]; 
 
 memset(input,0,sizeof(input));
 do
 { 
   printf("Entrez une chaine svp.\n"); 
   fgets(input,sizeof(input),stdin);

 /* verifie si un valeur est dans input, le /r pour win32 seulement */
 } while ((input[0] == 0) || (input[0] == '/n') || (input[0] == '/r')) ;
 
 printf("Vous avez entre %s\n", input); 
 
 return 0; 
} 

Répondre à Hot Metal

20

Jolkdarr, le 22 aoû 2004 à 22:36:30

Hello !

Ce programme ne "plante" pas car on n'utilise pas de pointeur initialisé avec la valeur retournée par fgets. Le problème cette fois, c'est que la fonction fgets n'élimine pas les espaces comme le fait gets. Par exemple, si on l'utilisateur ne rentre pas de chaîne et tape des espaces avant de faire RETURN, il voit le message suivant :

Vous avez entre

=> à reprendre un peu...

Autre remarques :
a) Avec les vieux compilateurs pre-ANSI C, il n'était pas toujours possible de fournir des "initialisateurs" pour les tableaux locaux définis dans les fonctions. Seule l'initialisation de tableaux globaux (tableaux définis à l'extérieur de toute fonction) était possible. Ces compilateurs étant rares, il n'est plus la peine de s'inquiéter et on peut alors écrire (si on veut) :

char input[500] = { 0 };

pour initialiser le tableau sans utiliser la fonction memset.

b) le compte-rendu retourné par la fonction n'est jamais testé (on risque une boucle infinie). Il est préférable de le faire comme dans l'exemple suivant fourni par Microsoft pour l'API du système Windows :

/* This program uses fgets to display * a line from a file on the screen. */
#include <stdio.h>

int main( void )
{
FILE *stream;
char line[100];

if( (stream = fopen( "crt_fgets.txt", "r" )) != NULL )
{
if ( fgets( line, 100, stream ) == NULL)
printf( "fgets error\n" );
else printf( "%s", line);
fclose( stream );
}
}

Répondre à Jolkdarr

21

Jolkdarr, le 22 aoû 2004 à 22:42:35

J'oubliais :

Remarque très importante :
Ecrire '\n' et '\r' et non '/n', '/r'.
Ca marchera mieux... ;)

Take care !

Répondre à Jolkdarr

23

Hot Metal, le 23 aoû 2004 à 00:35:32

Oups petite erreur :)

Répondre à Hot Metal

22

Jolkdarr, le 22 aoû 2004 à 22:45:50

Au temps pour moi, gets n'élimine pas les espaces non plus...
Faut les filtrer si on ne les veut pas.

Répondre à Jolkdarr

24

Onde2Choc, le 23 aoû 2004 à 08:50:08

Oula... fgets(), FILE, fopen, fclose... tout ça j'ai pas encore vu ! Je suis qu'un simple débutant : je viens de terminer le chapitre sur les structures et de commencer celui sur la portée des variables. Mais sinon j'ai copié collé vos codes et ils fonctionnent.


BOOM !
Laissez se propager l'onde de choc...

Répondre à Onde2Choc