Qualifier les caractères

Il arrive souvent qu'on souhaite qualifier les caractères dans un programme C++, par exemple dans le but d'identifier si un caractère est un blanc (espace, tabulation, changement de ligne, etc.), une ponctuation (virgule, parenthèse ouvrante, apostrophe, etc.), une lettre, un chiffre et ainsi de suite.

La tradition C est d'utiliser les fonctions suivantes, définies dans <ctype.h> (ou, en C++, dans <cctype>) :

Nom Rôle Exemple
std::isalnum()

Retourne true si et seulement si le char passé en paramètre est alphanumérique

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c; && std::isalnum(c))
{
   // c est alphanumérique
}
std::isalpha()

Retourne true si et seulement si le char passé en paramètre est alphabétique

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c; && std::isalpha(c))
{
   // c est alphabétique
}
std::iscntrl()

Retourne true si et seulement si le char passé en paramètre est un caractère de contrôle

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c; && std::iscntrl(c))
{
   // c est un caractère de contrôle
}
std::isgraph()

Retourne true si et seulement si le char passé en paramètre est une caractère graphique

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c; && std::isgraph(c))
{
   // c est un caractère graphique
}
std::islower()

Retourne true si et seulement si le char passé en paramètre est une lettre minuscule

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c; && std::islower(c))
{
   // c est une lettre minuscule
}
std::isprint()

Retourne true si et seulement si le char passé en paramètre est affichable

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c; && std::isprint(c))
{
   // c est affichable
}
std::ispunct()

Retourne true si et seulement si le char passé en paramètre est un symbole de ponctuation

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c; && std::ispunct(c))
{
   // c est une ponctuation
}
std::isspace()

Retourne true si et seulement si le char passé en paramètre est un caractère d'espacement (un blanc)

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c; && std::isspace(c))
{
   // c est un blanc
}
std::isupper()

Retourne true si et seulement si le char passé en paramètre est une lettre majuscule

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c; && std::isupper(c))
{
   // c est une lettre majuscule
}
std::isxdigit()

Retourne true si et seulement si le char passé en paramètre est un chiffre hexadécimal

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c; && std::isxdigit(c))
{
   // c est un chiffre hexadécimal
}
std::tolower()

Retourne l'équivalent minuscule de son paramètre (s'il y a lieu)

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c)
{
   std::cout << std::tolower(c);
}
std::toupper()

Retourne l'équivalent majuscule de son paramètre (s'il y a lieu)

// inclure <cctype> et <iostream>
char c;
if (std::cin >> c)
{
   std::cout << std::toupper(c);
}

Toutes les fonctions de <cctype> n'ont de sens qu'avec les caractères américains standard. Pour des raisons d'implémentation, elle planteront si on leur passe, par exemple, un caractère accentué.

Pour en savoir plus sur les questions culturelles en C++, voir cet article.

Pour cette raison, on leur préférera en C++ des versions plus sophistiquées provenant du fichier d'en-tête <locale> qui, lui, permet de gérer le concept de caractère associé à une culture, américaine ou autre.

Ces versions que je qualifierais de plus modernes des fonctions de <cctype> ressemblent beaucoup à leurs prédécesseures à ceci près qu'elles prennent deux paramètres plutôt qu'un seul. Le premier paramètre est (dans chaque cas) le caractère sur lequel la fonction doit opérer et le second paramètre est une référence à la culture courante.

En C++, la culture d'un lieu est décrite par une instance de std::locale. Instancier un std::locale peut se faire comme suit :

Les exemples ci-dessous s'appliquent aux versions de <locale>. La colonne Rôle n'a pas été répétée; référez-vous à la table précédente pour des détails.

Il est nettement préférable de privilégier la version à deux paramètres de <locale> à celle à un seul paramètre de <cctype>, la première faisant tout ce que fait la seconde... et même plus.

Nom Exemple
std::isalnum()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c; && std::isalnum(c, std::locale{}))
{
   // c est alphanumérique
}
std::isalpha()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c; && std::isalpha(c, std::locale{}))
{
   // c est alphabétique
}
std::iscntrl()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c; && std::iscntrl(c, std::locale{}))
{
   // c est un caractère de contrôle
}
std::isgraph()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c; && std::isgraph(c, std::locale{}))
{
   // c est un caractère graphique
}
std::islower()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c; && std::islower(c, std::locale{}))
{
   // c est une lettre minuscule
}
std::isprint()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c; && std::isprint(c, std::locale{}))
{
   // c est affichable
}
std::ispunct()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c; && std::ispunct(c, std::locale{}))
{
   // c est une ponctuation
}
std::isspace()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c; && std::isspace(c, std::locale{}))
{
   // c est un blanc
}
std::isupper()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c; && std::isupper(c, std::locale{}))
{
   // c est une lettre majuscule
}
std::isxdigit()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c; && std::isxdigit(c, std::locale{}))
{
   // c est un chiffre hexadécimal
}
std::tolower()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c)
{
   std::cout << std::tolower(c, std::locale{});
}
std::toupper()
// inclure <locale> et <iostream>
char c;
if (std::cin >> c)
{
   std::cout << std::toupper(c, std::locale{});
}

Pour en savoir plus sur les diverses sortes de caractères en C++, voir cet article et cet article. Notez que le problème de l'affichage des caractères accentués est d'un autre ordre.

La version de <locale> fonctionne à la fois avec des caractères codés sur un octet (des char) et avec les caractères étendus, codés sur deux octets (des wchar_t).

Si vous souhaitez manipuler des caractères accentués, par exemple, il est nettement préférable de procéder à l'aide de caractères étendus pour lesquels ces caractères ont une représentation standard (sur un char, le sens de 'é' peut varier et, en général, les fonctions de <locale> et de <cctype> vont planter... demandez à votre professeur de vous expliquer pourquoi).

Utiliser les fonctions de <locale> avec des caractères étendus (donc incluant entre autres les accents) va comme suit.

Nom Exemple
std::isalnum()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c; && std::isalnum(c, std::locale{}))
{
   // c est alphanumérique
}
std::isalpha()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c; && std::isalpha(c, std::locale{}))
{
   // c est alphabétique
}
std::iscntrl()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c; && std::iscntrl(c, std::locale{}))
{
   // c est un caractère de contrôle
}
std::isgraph()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c; && std::isgraph(c, std::locale{}))
{
   // c est un caractère graphique
}
std::islower()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c; && std::islower(c, std::locale{}))
{
   // c est une lettre minuscule
}
std::isprint()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c; && std::isprint(c, std::locale{}))
{
   // c est affichable
}
std::ispunct()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c; && std::ispunct(c, std::locale{}))
{
   // c est une ponctuation
}
std::isspace()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c; && std::isspace(c, std::locale{}))
{
   // c est un blanc
}
std::isupper()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c; && std::isupper(c, std::locale{}))
{
   // c est une lettre majuscule
}
std::isxdigit()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c; && std::isxdigit(c, std::locale{}))
{
   // c est un chiffre hexadécimal
}
std::tolower()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c)
{
   std::wcout << std::tolower(c, std::locale{});
}
std::toupper()
// inclure <locale> et <iostream>
wchar_t c;
if (std::wcin >> c)
{
   std::wcout << std::toupper(c, std::locale{});
}

Valid XHTML 1.0 Transitional

CSS Valide !