/* 06 - octobre -2024 v1.07 M.Lokbani IFT1169 - gcc14.2.0 08 - octobre -2020 v1.06 M.Lokbani IFT1169 - gcc9.3.0 08 - septembre -2014 v1.05 M.Lokbani IFT1169 - gcc6.1.1 20 - janvier -2014 v1.04 M.Lokbani IFT1169 - gcc4.8.1 17 - février -2013 v1.03 M.Lokbani IFT1169 - gcc4.7.0 26 - janvier -2010 v1.02 M.Lokbani IFT1169 - gcc4.3.0 30 - mai -2007 v1.01 M.Lokbani IFT1166 - nomalisation itoa + gcc4.0.2 16 - octobre -2005 v1.00 M.Lokbani IFT1166 - code + gcc3.4.2, +comments contact: lokbani@iro.umontreal.ca Copyright (C) 2005-2024 Universite de Montreal Departement d'informatique et de Recherche Operationnelle Mohamed Lokbani -- Tous Droits Reserves -- All Rights Reserved -- Remarques: Plusieurs commentaires ont ete extraits texto de: - Notes de cours de A. Dancel (Le Langage C) - Guide de reference de Borland Description: Ce fichier decrit l'utilisation de plusieurs fonctions permettant de manipuler des caracteres ou des chaines de caracteres. Nous avons defini ces fonctionnalites dans 5 fonctions: Traitement_de_chaines(): decrit les fonctions necessaires pour manipuler des chaines de caracteres. Test_de_caracteres(): decrit les fonctions necessaires pour tester la nature d'un caractere. Conversion_de_caracteres(): decrit les fonctions necessaires pour convertir un caractere. Conversion_de_chaines(): decrit les fonctions necessaires pour convertir une chaine de caracteres. Conversion_d1_entier(): decrit les fonctions necessaires pour convertir un entier. Chaque fonction contient le fichier d'en-tete qui va avec et qui contient les prototypes de fonctions utilisees dans les exemples. */ #include #include #include #include #include using namespace std; void Traitement_de_chaines(){ /* Pour pouvoir utiliser les differentes fonctions decrites dans la fonction "Traitement_de_chaines", il faudra penser à  inclure le fichier d'en-tete Il est important de ne pas confondre entre " string.h " et " string ". Le premier contient les prototypes des fonctions permettant de manipuler des chaines de caracteres declarees comme " char * " alors que le second pour des chaines de caracteres du type " string ". */ char Allemagne[100] = "Organisateur de la coupe du monde de football 2006"; char Bresil[100] = "Champion du monde de football"; char Tempo[100] = ""; /* Pour calculer la longueur d'une chaine size_t strlen(const char* str) 1- Valeur retournee est le nombre de caracteres de la chaine str. Le caractere nul de fin de chaine n'etant pas compte. */ cout << "La taille de la chaine Allemagne: " << strlen(Allemagne) < s2 */ cout << "Le resultat de la comparaison des chaines Allemagne et Bresil est: " << strcmp(Allemagne,Bresil) << endl; /* Pour comparer partiellement deux chaines de caracteres int strncmp(const char* s1, const char* s2, size_t maxlen) 1- Compare les chaines s1 et s2, en cherchant au plus maxlen caracteres 2- La comparaison debute avec le premier caractere de chaque chaine et continue avec les suivants, jusqu'à  ce que des caracteres de meme rang soient differents ou que maxlen soit atteint ou que l'une des chaines soit terminee. 3- Valeur retournee: - Valeur negative si s1 < s2 - Valeur nulle si les deux chaines sont egales - Valeur positive si s1 > s2 */ cout << "Le resultat de la comparaison des chaines Allemagne et Bresil est: " << strncmp(Allemagne,Bresil,2) << endl; /* Pour rechercher un caractere en particulier dans une chaine char* strchr(const char* s, int c) 1- Recherche la premiere occurence du caractere c dans la chaine de caracteres s. 2- Le caractere de fin de chaine est considere comme en faisant partie; ainsi l'expression strcchr(str,0) renvoie un pointeur vers celui ci. 3- Valeur retournee: - En cas de succes: un pointeur sur la premiere occurence du caractere c. - En cas d'echec: c ne figure pas dans la chaine s, la fonction retroune un pointeur NULL. 4- Il faudra tester contre un pointeur NULL pour eviter l'arret subit du programme (un plantage). */ char* ptr; if ( (ptr = strchr(Allemagne,'o')) != NULL){ cout << "Le (premier) caractere o est dans la chaine Allemagne?: " << ptr << endl; }else{ cout << "La chaine [" << Allemagne << "] ne contient pas le caractere [" << 'o' << endl; } /* Pour effectuer une recherche à  rebours d'un caractere en particulier dans une chaine char* strrchr(const char* s, int c) 1- Recherche la derniere occurence du caractere c dans la chaine de caracteres s. 2- Le caractere de fin de chaine est considere comme en faisant partie; ainsi l'expression strcchr(str,0) renvoie un pointeur vers celui ci. 3- Valeur retournee: - En cas de succes: un pointeur sur la derniere occurence du caractere c. - En cas d'echec: c ne figure pas dans la chaine s, la fonction retroune un pointeur NULL. 4- Il faudra tester contre un pointeur NULL pour eviter l'arret subit du programme (un plantage). */ if ( (ptr = strrchr(Allemagne,'o')) != NULL){ cout << "Le (dernier) caractere o est dans la chaine Allemagne?: " << ptr << endl; }else{ cout << "La chaine [" << Allemagne << "] ne contient pas le caractere [" << 'o' << endl; } /* Pour effectuer une recherche d'un caractere d'un ensemble char* strpbrk(const char* s1, const char* s2) 1- Recherche dans s1 la premiere occurence d'un caractere figurant dans la chaine s2. 2- Valeur retournee: - En cas de succes: un pointeur sur la premiere occurence dans s1 d'un caractere de s2. - En cas d'echec: si aucun caractere de s2 ne figure pas dans la chaine s1, la fonction retroune un pointeur NULL. 3- Il faudra tester contre un pointeur NULL pour eviter l'arret subit du programme (un plantage). */ if ( (ptr = strpbrk(Allemagne,"xy6")) != NULL){ cout << "Trouve le caractere [" << ptr << "] en position [" << ptr-Allemagne << "]" << endl; }else{ cout << "pas Trouve!" << endl; } /* Pour cloner une chaine char* strdup(const char* s) 1- Fait un double de la chaine s en allouant de la place. 2- L'espace allouea pour taille (strlen(s) + 1) octets. 3- Quand la memoire allouee n'est plus necessaire, il faudra la liberer par un appel à  la fonction free (et non pas delete) car la chaine a ete allouee par un appel de la fonction malloc (langage C) et non pas new (langage C++). 4- Valeur retournee: - En cas de succes: un pointeur sur l'emplacement de memoire contenant le clone de la chaine s. - En cas d'echec: la fonction retroune un pointeur NULL et l'espace necessaire pour contenir le clone n'a pas ete alloue. Il ne faut pas liberer un espace non alloue! */ if ( (ptr = strdup(Allemagne)) != NULL){ cout << "Clonage reussi et la copie de Allemagne se trouve a cette adresse:" << &ptr << endl; free(ptr); }else{ cout << "Echec lors du clonage!" << endl; } /* Pour rechercher une sous chaine -1- char* strstr(const char* s1, const char* s2) 1- Recherche la premiere occurence de la chaine s2 dans la chaine s1. 2- Valeur retournee: - En cas de succes: un pointeur sur l'element de s1 où commence s2. - En cas d'echec: s2 n'est pas dans s1, la fonction retroune un pointeur NULL! */ if ( (ptr = strstr(Allemagne,"foot")) != NULL){ cout << "La premiere occurence de la chaine [foot] dans la chaine Allemagne:" << ptr << endl; }else{ cout << "La chaine [foot] ne se trouve pas dans la chaine Allemagne!" << endl; } /* Pour rechercher une sous chaine -2- size_t strspn(const char* s1, const char* s2) 1- Cherche la premiere partie d'une chaine qui soit le sous-ensemble d'un ensemble donne de caracteres. 2- Recherche donc la premiere partie de s1 formee uniquement des caracteres figurant dans s2. 3- Renvoie la longueur du premier segment repondant à  la condition enoncee en -2-. size_t strcspn(const char* s1, const char* s2) 1- Isole la partie d'une chaine qui ne contient aucun caracteres d'un ensemble de caracteres donnees. 2- Renvoie la longueur de la partie s1 formee uniquement de caracteres ne figurant pas dans s2. */ cout << "La longueur du premier segment [nst]: " << strspn(Allemagne,"nst") << endl; cout << "La longueur du premier segment [nst]: " << strcspn(Allemagne,"nst") << endl; /* Pour rechercher un lexemes dans une chaine char* strtok(const char* s1, const char* s2) 1- Cette fonction decompose s1 en sous-chaines appeles lexemes (tokens). Ces lexemes sont delimites pas des caracteres (separateurs) figurant dans la chaine s2. 2- Le premier appel à  strtok: - retourne un pointeur sur le premier lexeme de s1 - ecrit un caractere nul dans sans s1 immediatement apres ce lexeme. 3- Les autres appels à  strtok avec NULL comme premier argument traitant de la meme maniere, et jusqu'à  epuisement, les autres lexemes de s1. 4- La chaine des separateurs, s2, peut-etre differente d'un appel à  l'autre. 5- Valeur de retour: - En cas de succes: un pointeur sur le lexeme trouve dans la chaine s1. - Quand il ne reste plus de lexeme dans s1, strtok retourne le pointeur NULL. 6- La chaine s1 sera transformee et donc perdue à  jamais. Il faudra donc penser à  faire une copie. */ char sep[] = " o"; strcpy(Tempo,Allemagne); ptr = strtok(Tempo,sep); while(ptr != NULL){ cout << "Token: " << ptr << endl; ptr = strtok(NULL,sep); } cout << "Allemagne apres traitement: " << Tempo < */ /* Un caractere alphanumerique? int isalnum(int c) 1- Cette fonction teste si le caractere c est un caractere alphanumerique. 2- Valeur de retour: - une valeur non nulle si c est une lettre (A-Z ou a-z) ou un chiffre (0-9) */ isalnum('W')? cout << "[W] est un caractere alphanumerique.\n": cout << "[W] n'est un caractere alphanumerique.\n"; /* Un caractere alphabetique? int isalpha(int c) 1- Cette fonction teste si le caractere c est un caractere alphabetique. 2- Valeur de retour: - une valeur non nulle si c est une lettre (A-Z ou a-z) */ isalpha(9)? cout << "[9] est un caractere alphabetique.\n":cout << "[9] n'est pas un caractere alphabetique.\n"; /* Un caractere ASCII? int isascii(int c) 1- Cette fonction teste si le caractere c est un caractere ASCII. 2- Valeur de retour: - une valeur non nulle si l'octet de poids faible de c est compris entre 0 et 127 (0x00 - 0x7F) */ isascii('e')? cout << "[e accent grave] est un caractere ascii (non etendu).\n":cout << "[e accent grave] n'est pas un caractere ascii (non etendu).\n"; /* Un caractere de contrôle int iscntrl(int c) 1- Cette fonction teste si le caractere c est un caractere de contrôle. 2- Valeur de retour: - une valeur non nulle si c est un caractere de contrôle ou le caractere "delete" (0x7F ou 0x00 - 0x1F) */ iscntrl('C')? cout << "[C] est un caractere de controle.\n":cout << "[C] n'est pas un caractere de controle.\n"; /* Un chiffre? int isdigit(int c) 1- Cette fonction teste si le caractere c est un chiffre. 2- Valeur de retour: - une valeur non nulle si c est un chiffre (0-9) */ isdigit(7)? cout << "[7] est un chiffre.\n": cout << "[7] n'est pas un chiffre.\n"; /* Affichable? -1- int isgraph(int c) 1- Cette fonction teste si le caractere c est affichable (sauf l'espace). 2- Valeur de retour: - une valeur non nulle si c est un caractere affichable (0x21 - 0x7E. Ne prend pas donc le ASCII etendu). */ isgraph('e')? cout << "[e accent grave] est un caractere affichable.\n":cout << "[e accent grave] n'est pas un caractere affichable.\n"; /* Affichable? -2- int isprint(int c) 1- Cette fonction teste si le caractere c est affichable. 2- Elle est identique à  isgraph sauf que ici on prend en consideration le caractere d'espacement. 3- Valeur de retour: - une valeur non nulle si c est un caractere affichable (0x20 - 0x7E. Ne prend pas donc le ASCII etendu). */ isprint(' ')? cout << "[ ] est un caractere affichable.\n":cout << "[ ] n'est pas un caractere affichable.\n"; /* Minuscule? int islower(int c) 1- Cette fonction teste si le caractere c est un caractere minuscule. 2- Valeur de retour: - une valeur non nulle si c est un caractere minuscule (a-z). */ islower('T')? cout << "[T] est une lettre minuscule.\n":cout << "[T] n'est pas une lettre minuscule.\n"; /* Majuscule? int isupper(int c) 1- Cette fonction teste si le caractere c est un caractere majuscule. 2- Valeur de retour: - une valeur non nulle si c est un caractere minuscule (A-Z). */ isupper('T')? cout << "[T] est une lettre majuscule.\n":cout << "[T] n'est pas une lettre majuscule.\n"; /* Ponctuation? int ispunct(int c) 1- Cette fonction teste si le caractere c est un caractere de ponctuation. 2- Valeur de retour: - une valeur non nulle si c est un caractere de ponctuation. */ ispunct('?')? cout << "[?] est un caractere de ponctuation.\n":cout << "[?] n'est pas un caractere de ponctuation.\n"; /* Espace? int isspace(int c) 1- Cette fonction teste si le caractere c est un caractere d'espacement. 2- Valeur de retour: - une valeur non nulle si c est un espace, une tabulation, un retour chariot, un passage à  la ligne, une tabulation verticale ou un saut de page (0x09-0x0D, 0x20). */ isspace('\t')? cout << "[\t] est une tabulation.\n":cout << "[\t] n'est pas une tabulation.\n"; /* Hexadecimal? int isxdigit(int c) 1- Cette fonction teste si le caractere c est un caractere hexadecimal. 2- Valeur de retour: - une valeur non nulle si c est un un chiffre (0-9, A-F, a-f). */ isxdigit('f')? cout << "[f] est un chiffre hexadecimal.\n":cout << "[f] n'est pas un chiffre hexadecimal.\n"; return; } void Conversion_de_caracteres(){ /* Pour pouvoir utiliser les differentes fonctions decrites dans la fonction "Conversion_de_caracteres", il faudra penser à  inclure le fichier d'en-tete */ /* Vers l'ASCII int toascii(int c) 1- Cette fonction convertit l'entier c vers l'ASCII. 2- Une valeur comprise entre 0 et 127. 3- Valeur de retour: - La valeur convertie de l'argument c. */ cout << "La valeur ASCII de [49] est: " << toascii(49) << endl; /* En minuscule int tolower(int c) 1- Cette fonction convertit le caractere c en minuscule. 3- Valeur de retour: - La valeur convertie de l'argument c si celui-ci est une lettre majuscule, autrement, elle renvoie la valeur inchangee. */ cout << "Minuscule de [G] est: " << (char) tolower('G') << endl; /* En majuscule int toupper(int c) 1- Cette fonction convertit le caractere c en majuscule. 2- Valeur de retour: - La valeur convertie de l'argument c si celui-ci est une lettre minuscule, autrement, elle renvoie la valeur inchangee. */ cout << "Majuscule de [g] est: " << (char) toupper('g') << endl; return; } void Conversion_de_chaines(){ /* Pour pouvoir utiliser les differentes fonctions decrites dans la fonction "Conversion_de_chaines", il faudra penser à  inclure le fichier d'en-tete et */ /* En virgule flottante double atof(const char* s) 1- Cette fonction convertit la chaine de caracteres s en un nombre de type double. 2- Valeur de retour: - Le resultat de la conversion de la chaine passee en argument. */ char* s = (char *) "Une drole de cuisine!"; cout << "Le resultat de la conversion de la chaine [Une drole de cuisine!] en virgule flottante est: " << atof(s) << endl; /* En un entier int atoi(const char* s) 1- Cette fonction convertit la chaine de caracteres s en un nombre de type int. 2- Valeur de retour: - Le resultat de la conversion de la chaine passee en argument. - Si la chaine ne peut pas etre convertie en un nombre de type correspondant (int), la valeur renvoyee est 0. */ cout << "Le resultat de la conversion de la chaine [Une drole de cuisine!] en int est: " << atoi(s) << endl; /* En un long long atol(const char* s) 1- Cette fonction convertit la chaine de caracteres s en un nombre de type long. 2- Valeur de retour: - Le resultat de la conversion de la chaine passee en argument. - Si la chaine ne peut pas etre convertie en un nombre de type correspondant (long), la valeur renvoyee est 0. */ cout << "Le resultat de la conversion de la chaine [Une drole de cuisine!] en long est: " << atol(s) << endl; cout << "Le resultat de la conversion de la chaine [67548] en long est: " << atol("67548") << endl; return; } /* ************** Debut de la cuisine interne *************************** */ /* Fonction permettant d'inverser une chaine void strreverse(char* debut, char* fin) 1- Cette fonction inverse les caracteres d'une chaine donnee 2- L'argument "debut" est un pointeur vers le debut de la chaine et l'argument "fin" pointe la fin de la chaine. */ void strreverse(char* debut, char* fin) { char aux; while(fin>debut) aux=*fin, *fin--=*debut, *debut++=aux; } /* Certains compilateurs fournissent la fonction [itoa] qui permet de convertir un nombre entier vers une chaine de caracteres. Parce que cette fonction ne fait pas parti de la norme, il se peut que certains compilateurs la rejettent. Pour cette raison, nous allons definir "notre" propre fonction "itoa" pour contourner cette limite. Le code de la fonction "intachaine" ci-dessous est base sur le livre de [Kernighan & Ritchie] dont le titre est [Le Langage C, norme Ansi] avec une legere modification apportee par Stuart Lowe & co. au niveau de l'optimisation. Fonction permettant de convertir un entier en chaine de caracteres. void intachaine(int valeur, char* s, int base); 1- Cette fonction convertit le nombre valeur de type int en une chaine de caracteres terminee par un caractere nul et place le resultat dans s. 2- L'argument base indique dans quelle la conversion doit etre effectuee. Un entier compris entre 2 et 36 inclus. 3- Il faudra allouer statiquement ou dynamiquement s. 4- La place allouee à  l'argument s doit etre suffisament importante pour contenir la chaine renvoyee ainsi que le caractere d'arret (\0). 5- Cette fonction peut envoyer jusqu'à  17 caracteres. 6- Valeur de retour: - Rien. - Dans la version fournie par certains compilateurs, la valeur retournee est un pointeur sur s. */ void intachaine(int value, char* str, int base) { static char num[] = "0123456789abcdefghijklmnopqrstuvwxyz"; char* wstr=str; int sign; div_t res; // On valide la base if (base<2 || base>35){ *wstr='\0'; return; } // On prend soin du signe if ((sign=value) < 0) value = -value; // CConversion. Le nombre est inverse. do { res = div(value,base); *wstr++ = num[res.rem]; }while((value=res.quot)); if(sign<0) *wstr++='-'; *wstr='\0'; // On inverse la chaine strreverse(str,wstr-1); } /* ************** Fin de la cuisine interne *************************** */ void Conversion_d1_entier(){ /* Pour pouvoir utiliser les differentes fonctions decrites dans la fonction "Conversion_d1_entier", il faudra penser à  inclure le fichier d'en-tete */ /* Vers une chaine de caracteres char* itoa(int valeur, char* s, int base); 1- Cette fonction convertit le nombre valeur de type int en une chaine de caracteres terminee par un caractere nul et place le resultat dans s. 2- L'argument base indique dans quelle la conversion doit etre effectuee. Un entier compris entre 2 et 36 inclus. 3- Il faudra allouer statiquement ou dynamiquement s. 4- La place allouee à  l'argument s doit etre suffisament importante pour contenir la chaine renvoyee ainsi que le caractere d'arret (\0). 5- Cette fonction peut envoyer jusqu'à  17 caracteres. 6- Valeur de retour: - Un pointeur sur s. */ int nombre = 12345; char unechaine[25]; intachaine(nombre,unechaine,10); cout << "La conversion de [12345] en chaine de caracteres, en base 10, est: " << unechaine << endl; return; } int main() { Traitement_de_chaines(); Test_de_caracteres(); Conversion_de_caracteres(); Conversion_de_chaines(); Conversion_d1_entier(); return 0; } /* >char911 La taille reelle de la chaine Allemagne: 100 Copie Bresil dans Tempo. La chaine resultante est: Champion du monde de football Reinitialisation de Tempo avec la chaine Allemagne. La chaine resultante est: Organisateur de la coupe du monde de football 2006 Copie partielle des 2 premiers caracteres de Bresil dans Tempo. La chaine resultante est:Ch Le resultat final de concatenation de chaines est: Organisateur de la coupe du monde de football 2006: Allemagne. Le resultat de la comparaison des chaines Allemagne et Bresil est: 1 Le resultat de la comparaison des chaines Allemagne et Bresil est: 1 Le (premier) caractere o est dans la chaine Allemagne?: oupe du monde de football 2006 Le (dernier) caractere o est dans la chaine Allemagne?: otball 2006 Trouve le caractere [6] en position [49] Clonage reussi et la copie de Allemagne se trouve a cette adresse:0x22fcc8 La premiere occurence de la chaine [foot] dans la chaine Allemagne:football 2006 La longueur du premier segment [nst]: 0 La longueur du premier segment [nst]: 4 Token: Organisateur Token: de Token: la Token: c Token: upe Token: du Token: m Token: nde Token: de Token: f Token: tball Token: 2006 Allemagne apres traitement: Organisateur [W] est un caractere alphanumerique. [9] n'est pas un caractere alphabetique. [e accent grave] est un caractere ascii (non etendu). [C] n'est pas un caractere de controle. [7] n'est pas un chiffre. [e accent grave] est un caractere affichable. [ ] est un caractere affichable. [T] n'est pas une lettre minuscule. [T] est une lettre majuscule. [?] est un caractere de ponctuation. [ ] est une tabulation. [f] est un chiffre hexadecimal. La valeur ASCII de [49] est: 49 Minuscule de [G] est: g Majuscule de [g] est: G Le resultat de la conversion de la chaine [Une drole de cuisine!] en virgule flottante est: 0 Le resultat de la conversion de la chaine [Une drole de cuisine!] en int est: 0 Le resultat de la conversion de la chaine [Une drole de cuisine!] en long est: 0 Le resultat de la conversion de la chaine [67548] en long est: 67548 La conversion de [12345] en chaine de caracteres, en base 10, est: 12345 >Exit code: 0 */