Comparer une chaine vide en C
Résolu/Fermé
valgoku
Messages postés
187
Date d'inscription
lundi 17 avril 2006
Statut
Membre
Dernière intervention
22 janvier 2013
-
12 janv. 2010 à 22:02
mamiemando Messages postés 33387 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 novembre 2024 - 20 janv. 2010 à 16:52
mamiemando Messages postés 33387 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 novembre 2024 - 20 janv. 2010 à 16:52
A voir également:
- Caractere vide
- Coeur vide ✓ - Forum Réseaux sociaux
- Formate pour taxer client frigo vide ✓ - Forum Vos droits sur internet
- Caractère ascii - Guide
- Caractere speciaux - Guide
- Caractères spéciaux : comment taper des |—[©\½→}… - Guide
5 réponses
mamiemando
Messages postés
33387
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
27 novembre 2024
7 803
13 janv. 2010 à 00:26
13 janv. 2010 à 00:26
Il faut très clairement choisir la deuxième solution si tu veux écrire ton programme "sérieusement". Une chaîne de caractère classique est un tableau (un bloc mémoire).
Chaque "case" fait la taille d'un octet, interprété comme un char (d'où la notation char[] ou char *). Par convention, on considère que le caractère '\0' arrête la fin de cette chaîne. Dans ton code tu écris '\o' ce qui n'a rien à voir avec '\0' (backslash 0). '\0' (qui en fait est un octet dont tous les bits sont nuls) désigne le caractère de fin de chaîne. C'est notamment lui qui permet aux fonctions printf, strlen etc... de savoir quand s'arrêter de lire des octets en mémoire (sans ce caractère, ces fonctions dépasseraient la chaîne et atteindrait une zone mémoire qui déclencherait une erreur de segmentation).
Note que quand tu écris :
... en réalité tu manipules un bloc mémoire de 5 chars :
- string[0] == 'p'
- string[1] == 'l'
- string[2] == 'o'
- string[3] == 'p'
- string[4] == '\0'
Ainsi on pourrait écrire :
En fait, ce qu'il faut bien voir c'est que 'p', 'l', ... sont autant de constantes codées sur un octet et qui associent chaque caractère et son code ascii
http://www.manpagez.com/man/7/ascii/
C'est la raison pour laquelle par exemple 'p' == 112 (cf lien précédent). Pour s'en convaincre :
En particulier le caractère fin de chaîne, noté '\0', vaut en réalité 0.
D'autre part, si tu révises ton cours sur les pointeurs tu verras que chaine[i] équivaut à *(chaine+i). En particulier chaine[0] == *(chaine + 0) = *chaine. Comme en C un if est vrai si la valeur passée entre parenthèse du if est non nulle, on peut donc directement écrire :
... ou en encore plus compressé, avec l'autre syntaxe du if ... else ... du C :
Alors maintenant, revenons à la version avec strlen :
C'est très mauvais pour la raison suivante : imagine que ta chaîne fasse 100000 chars. La fonction strlen va devoir parcourir toute la chaîne, ce qui va l'occuper un petit moment avant de renvoyer 100000 (+1). C'est bien dommage, car en fait la seule chose qu'on a besoin de savoir, c'est si le premier caractère vaut '\0' ou non, ce qui est immédiat au lieu d'avoir un coût proportionnel à la longueur de la chaîne. Alors certes la version avec strlen est "plus lisible" quand on débute en C. Mais il faut l'oublier le plus vite possible !
Bonne chance
Chaque "case" fait la taille d'un octet, interprété comme un char (d'où la notation char[] ou char *). Par convention, on considère que le caractère '\0' arrête la fin de cette chaîne. Dans ton code tu écris '\o' ce qui n'a rien à voir avec '\0' (backslash 0). '\0' (qui en fait est un octet dont tous les bits sont nuls) désigne le caractère de fin de chaîne. C'est notamment lui qui permet aux fonctions printf, strlen etc... de savoir quand s'arrêter de lire des octets en mémoire (sans ce caractère, ces fonctions dépasseraient la chaîne et atteindrait une zone mémoire qui déclencherait une erreur de segmentation).
Note que quand tu écris :
char *string = "plop";
... en réalité tu manipules un bloc mémoire de 5 chars :
- string[0] == 'p'
- string[1] == 'l'
- string[2] == 'o'
- string[3] == 'p'
- string[4] == '\0'
Ainsi on pourrait écrire :
if(chaine[0] == '\0') { printf("La chaîne est vide\n"); } else { printf("La chaîne est non vide et contient [%s]\n",chaine); }
En fait, ce qu'il faut bien voir c'est que 'p', 'l', ... sont autant de constantes codées sur un octet et qui associent chaque caractère et son code ascii
http://www.manpagez.com/man/7/ascii/
C'est la raison pour laquelle par exemple 'p' == 112 (cf lien précédent). Pour s'en convaincre :
#include <stdio.h> int main(){ char c; c = 112; printf("%c\n",c); c = 'p'; printf("%c\n",c); return 0; }
En particulier le caractère fin de chaîne, noté '\0', vaut en réalité 0.
D'autre part, si tu révises ton cours sur les pointeurs tu verras que chaine[i] équivaut à *(chaine+i). En particulier chaine[0] == *(chaine + 0) = *chaine. Comme en C un if est vrai si la valeur passée entre parenthèse du if est non nulle, on peut donc directement écrire :
if(*chaine) { // *chaine <=> chaine[0] et '\0' <=> 0 printf("La chaîne est vide\n"); } else { printf("La chaîne est non vide et contient [%s]\n",chaine); }
... ou en encore plus compressé, avec l'autre syntaxe du if ... else ... du C :
*chaine ? printf("La chaîne est vide\n") : printf("La chaîne est non vide et contient [%s]\n",chaine);
Alors maintenant, revenons à la version avec strlen :
if(strlen(chaine)){ // si la longueur est non nulle, ce test est vrai printf("La chaîne est non vide\n"); }else{ printf("La chaîne est vide\n"); }
C'est très mauvais pour la raison suivante : imagine que ta chaîne fasse 100000 chars. La fonction strlen va devoir parcourir toute la chaîne, ce qui va l'occuper un petit moment avant de renvoyer 100000 (+1). C'est bien dommage, car en fait la seule chose qu'on a besoin de savoir, c'est si le premier caractère vaut '\0' ou non, ce qui est immédiat au lieu d'avoir un coût proportionnel à la longueur de la chaîne. Alors certes la version avec strlen est "plus lisible" quand on débute en C. Mais il faut l'oublier le plus vite possible !
Bonne chance