Aller au menu - Aller au contenu

Icône Les chaînes de caractères

Par Avatar Yno
Mise à jour : 09/07/2010
Difficulté : Facile Facile
170 visites depuis 7 jours, dont 15 sur ce chapitre classé 446/786
Nous allons étudier un nouveau type de données, les chaînes de caractères. Elles sont plus complexes que les types présentés précédemment, car ce sont en fait des ensembles de caractères indépendants (qui eux se comportent comme les nombres que nous savons déjà manipuler). Nous devons donc apprendre à quoi elles servent, comment on les utilise en tant qu'ensemble d'objets, mais aussi en tant qu'objets propres.
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Contenir du texte

Cela fait quelques temps déjà que nous les utilisons un petit peu : les chaînes de caractères servent à manipuler du texte. Un tel nom leur a été donné car ce sont des objets qui regroupent en mémoire plusieurs caractères à la suite. En Vala, ce sont des objets faciles à manier, supportant beaucoup d'opérations de base, qu'il faudra certes apprendre mais qui se révèleront pratiques. Il est plus facile de manipuler des chaînes en Vala qu'en C !

On déclare une chaîne avec le nom de type string . Une chaîne déclarée s'utilise ensuite à l'aide de ses méthodes (rappelez-vous que ce sont les opérations qu'un objet supporte), ou bien à l'aide d'indices : il est possible de désigner un caractère ou une sous-partie de la chaîne par un indice, pour la découper en tranche. Pourquoi feriez-vous une telle chose, me demanderez-vous ? Hé bien, cela dépend de ce que vous voulez faire avec vos chaînes.

Le type string est très utile. Dès que nous voulons représenter du texte dans un programme, nous sommes susceptibles de nous en servir. Mais plus généralement encore, nous pouvons utiliser des chaînes dès que nous voulons représenter des données sous forme brute. Pour envoyer des données sur le réseau, pour lire un fichier (y compris autre chose que du texte, comme une image), pour enregistrer des objets plus complexes sur le disque ou dans une base de données, bien souvent vous n'avez besoin que d'elles (ou de variantes, que nous découvrirons tôt ou tard).

Et dans ces cas-là, les opérations proposées par défaut ne sont pas suffisantes et il faut savoir implémenter (c'est à dire programmer de façon concrète) les vôtres. Mais assez parlé, apprenons à nous servir des chaînes ;) .

Lire et écrire

Nous savons déjà écrire une chaîne constante à l'écran, à l'aide de la méthode printf de l'objet stdout . Mais comment faire pour écrire le texte contenu dans une variable, ou en lire un saisi au clavier par l'utilisateur ?

Répondre à la première question est facile : nous pouvons réutiliser stdout.printf , que nous connaissons déjà, en lui passant notre variable pour qu'il en affiche le contenu. Cependant, cette méthode peut échouer si notre texte contient des caractères %, car printf essaierait de les interpréter ! Nous utiliserons donc également stdout.puts , qui affiche une chaîne et revient automatiquement à la ligne.

En revanche, nous n'avons pas appris à lire une chaîne de caractères avec stdin.scanf. C'est parce qu'il y a mieux : certaines méthodes de stdin sont en effet plus adaptées à la lecture de texte, comme l'est read_line. Comme son nom l'indique, cette dernière va lire une ligne saisie par l'utilisateur, et renvoyer la valeur lue. Très facile, donc, de mémoriser celle-ci :

Code : Vala
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class Main
{
  public static int main (string[] args)
  {
    stdout.puts("J'écoute ?\n");
    string s;
    s = stdin.read_line();
    stdout.printf("Vous avez entré %s", s);
   
    return 0;
  }
}


Vous pouvez également vous servir de cette méthode pour lire autre chose que des chaînes, en convertissant après coup la chaîne lue. Par exemple, pour lire un entier, écrivez s.to_int(). Mais plutôt que de passer par une variable intermédiaire, on peut même appliquer la méthode to_int à la chaîne lue par stdin.get_line, en écrivant stdin.get_line().to_int(). La chaîne sera alors lue et renvoyée, mais on la transformera immédiatement en entier, qui sera finalement la valeur de l'expression (que vous pouvez stocker dans une variable ou afficher directement).

Accéder aux caractères

La première chose que nous pouvons faire avec une chaîne est d'accéder à un caractère à partir de sa position (appelée indice). Ceci se fait en écrivant le nom de la chaîne suivit de deux crochets entourant l'indice : str[i] . Une telle expression renvoie un caractère Unicode, de type unichar . Attention, notez bien que le premier caractère est désigné par l'indice 0. C'est peu important pour l'instant mais c'est un détail qui aura son importance plus tard.

Les caractères Unicode peuvent être aussi bien des lettres "usuelles" (pour nous occidentaux) que des caractères "étrangers", par exemple "قكلمنهو". Cela veut dire que les chaînes Vala acceptent tous les caractères de toutes les langues ainsi que de très nombreux autres symboles sans ajouter en complexité pour le programmeur. Cela a aussi des désavantages, sur lesquels nous reviendrons.

Les trucs fantastiques qu'on peut faire avec des chaînes

Construire de nouvelles chaînes



Vala supporte un certain nombre d'opérations usuelles sur les chaînes. La première, appelée concaténation, permet d'acoller deux chaînes, et utilise l'opérateur + :

Code : Vala
1
2
3
4
string alpha = "Bonjour";
string beta = " les Zéros !";

stdout.puts(alpha + beta); // Affichera "Bonjour les Zéros !"


Les chaînes sont des objets comme les autres en Vala. Cela veut dire qu'elles possèdent des méthodes. Nous avons déjà vu ce mot plusieurs fois : il désigne du code possédé par un objet, qui permet bien souvent d'agir sur lui. Par exemple, stdout désigne la sortie standard, c'est à dire l'écran dans la plupart des cas, et printf permet d'écrire sur cette sortie.

Il existe également une méthode printf pour les chaînes ! Son rôle est à peu près le même que celle de stdout, sauf qu'elle renvoie une nouvelle chaîne à partir de la chaîne sur laquelle on l'applique plutôt que d'écrire à l'écran. Par exemple,

Code : Vala
1
2
3
4
5
string format = "Bonjour %s, tu as %d ans.";
string format2 = format.printf("Gérard", 4);

stdout.puts(format2);
stdout.puts(format); // La chaîne initiale n'est pas modifiée !


Notez bien que l'on a du stocker le résultat dans une chaîne. On aurait pu réutiliser la même, mais il faut en tout cas bien retenir qu'elle n'est pas modifiée sans réutiliser le symbole = de l'affectation.

Comparaison de chaînes



Il est possible de comparer facilement les chaînes en Vala. Par exemple, contrairement aux langages C ou Java, on peut utiliser l'opérateur == pour tester l'égalité !

Code : Vala
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
string mot_de_passe = "Chapter24";
string entree;

stdout.printf("Entrez le mot de passe :\n");
entree = stdin.read_line();

if (entree == mot_de_passe)
    stdout.printf("Vous avez deviné !");
else
    stdout.printf("Ah non, raté !");


De même, on peut utiliser la construction switch avec les chaînes. Essayez de réécrire l'exemple précédent avec celle-ci (n'hésitez pas à regarder à nouveau le chapitre précédent).

Enfin, il est possible de comparer les chaînes dans l'ordre lexicographique, qui n'est rien d'autre que l'ordre du dictionnaire. Par exemple, "abeille" < "balançoire" est vrai.

Sous-chaînes



À partir d'une chaîne, on peut extraire une sous-chaîne, qui est composée des caractères de la chaîne initiale compris entre deux positions. Autrement dit, de la chaîne "Bonjour les Zéros !" , on peut par exemple extraire la chaîne "Zéros" (ou n'importe quelle autre). Pour ce faire, on utilise la méthode substring.

Code : Vala
1
2
3
4
5
string chaine = "Bonjour les Zéros !";
string extraction;

extraction = chaine.substring(12, 5);
stdout.printf("Vous êtes des " + extraction + ".");


Comme le montre cet exemple, substring prend en arguments la position initiale de la sous-chaîne, et la longueur que l'on veut extraire.

Il est également possible de tester la présence d'une chaîne dans une autre, à l'aide de la méthode contains ou de l'opérateur in :

Code : Vala
1
2
3
4
5
6
string chaine = "Cette leçon vaut bien un fromage sans doute";

if (chaine.contains("leçon"))
    stdout.printf("C'est vrai.\n");
if ("fromage" in chaine)
    stdout.printf("C'est vrai aussi.");


En vrac



Vala supporte en outre quelques autres opérations sur les chaînes. On peut les mettre en majuscule à l'aide de la méthode up, ou en minuscule à l'aide de la méthode down. On peut également les renverser (le premier caractère devient le dernier, et ainsi de suite) à l'aide de la méthode reverse. Et, pourquoi pas, éliminer les espaces placés au début et à la fin d'une chaîne à l'aide de la méthode strip. Essayez-les !

Il y en a d'autres encore, mais nous ne pouvons pas toutes les citer. À vous de les découvrir, au fur et à mesure de votre apprentissage de Vala.

Il nous reste encore à parler de la longueur et de la taille d'une chaîne. La première se définit comme le nombre de caractères de la chaîne. La seconde est la taille que la chaîne prend en mémoire. Attention, ces deux grandeur ne sont pas souvent égales ! C'est du au fait que certains caractères Unicode, notamment les caractères accentués, prennent plusieurs octets en mémoire.

La documentation officielle de Vala donne l'exemple suivant :

Code : Vala
1
2
3
4
string dessert = "crème brûlée";

stdout.printf ("La chaîne '%s' comporte %d caractères, et prend %d octets en mémoire.\n",
                dessert, (int) dessert.length, (int) dessert.size ())


En l'essayant, vous constaterez que la longueur et la taille diffèrent. Notez que la première est donnée par dessert.length, alors que la seconde est donnée par dessert.size() : dans le second cas, on trouve des parenthèses parce que size est une méthode tout ce qu'il y a de plus classique. Au contraire, length est une propriété : c'est une caractéristique d'un objet qui n'est pas exécutable, contrairement à une méthode. C'est juste une donnée appartenant à l'objet, et on l'utilise avec son nom, sans parenthèses.

Dernière remarque, dessert.length est de type long : pour l'afficher ici, nous avons du le convertir en int . Encore plus fou, dessert.size() est d'un type qui ne nous intéresse pas trop pour l'instant, à savoir le type size_t , et nous avons du lui aussi le convertir.

Sans faire de conversion, il est possible d'afficher des données de type long et size_t en remplaçant %d par respectivement %ld et %Zd.

Ceci aura son importance quand nous manipulerons de très grands nombres, que le type int ne peut pas accueillir. Essayez donc de retenir %ld, car si au pire vous oubliez l'autre vous pourrez toujours convertir la donnée en long .

Deux autres façons de créer des chaînes

Afin de faciliter la création de chaînes, Vala propose deux syntaxes particulières pour les définir. On pourrait très bien se passer des deux, mais elles s'avèrent parfois pratiques.

Chaînes verbatim



Nous avons vu que, dans une chaîne Vala, la suite de caractères \n est interprétée comme un retour à la ligne. De même, \t est remplacé à l'affichage par une tabulation. Ainsi, avec les chaînes que nous avons utilisées jusqu'à présent, il n'est pas possible de revenir à la ligne dans le code source, le compilateur ne comprenant pas ce changement de ligne inopiné.

La mise en forme à l'aide des caractères spéciaux peut pourtant s'avérer pénible, et on aimerait pouvoir écrire directement les blocs de texte dans le code. Pour cela, Vala propose les chaînes verbatim, qui sont stockées en mémoire exactement comme elles sont écrites (avec les retours à la ligne, les tabulations, et sans transformer les caractères spéciaux). Ce sont des chaînes comme les autres, on les définit juste en les entourant de trois " au lieu d'un :

Code : Vala
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class Main
{
  public static int main (string[] args)
  {
    string foo = """Cette chaîne verbatim peut surprendre.
En effet, elle ne comprend pas nos caractères spéciaux \n ou \t, et 
   elle accepte
      les retours
         à la ligne""";
         
    stdout.printf("Voyez : %s", foo);

    return 0;
  }
}


Chaînes templates



Plus pratiques que les chaînes dites de format que l'on passe à stdout.printf, les chaînes templates permettent de remplacer un nom de variable par sa valeur directement dans la chaîne, ou d'évaluer des expressions. Pour cela, on précède les noms et les expressions par un dollar $ :

Code : Vala
1
2
int a = 6, b = 7;
string s = @"$a * $b = $(a * b)";  // s vaut "6 * 7 = 42"


Vous trouverez sans doute une utilité à cette fonctionnalité.
Chapitre précédent Sommaire Chapitre suivant

Partager

Il n'y a pas encore de commentaire pour ce tuto.