Variables et chaînes de caractères

Dans ce chapitre, nous allons aborder un concept important dans tous les langages : les variables.

Variables

Nous allons aborder le sujet des variables, mais il faut savoir que nous avons déjà déclaré deux variables dans le chapitre précédent : x et y.

Mais, c’est quoi une variable ?

Une variable est une donnée de notre programme qu’on pourra modifier, lire, etc. En fait, dans notre programme, ce sera juste un nom (on parle d’identifiant) auquel on associe une valeur, un mot… On peut donc avoir une variable qui s’appelle âge et qui représenter l’âge de l’utilisateur. Dans le chapitre précédent, nous avons utilisé x et y afin de faire des calculs. Plus loin dans le tutoriel, nous reviendrons sur la définition des variables et verront plus précisément comment elles se présentent. Pour le moment, nous nous contenterons de les utiliser.

Déclaration de variables et opérations

Comme nous avons pu le voir, la déclaration d’une variable est enfantine : un simple signe égal.
Nous pouvons ensuite effectuer les mêmes opérations avec vos variables qu’avec des nombres : additions, soustractions, multiplications et divisions.

> x = 3
=> 3
> y = 2
=> 2
> x + y
=> 5
> x - y
=> 1

On peut changer la valeur d’une variable au cours d’un programme. On dit qu’on lui assigne une valeur. Une variable a pour valeur la dernière valeur qui lui a été assignée. Par exemple, regardons ce code.

> x = 3
=> 3
x = 5
=> 5

Après cela, la variable x ne vaudra plus 3 mais vaudra bien 5.

Nous pouvons récupérer le résultat d’une opération entre variables dans une nouvelle variable (ou même dans l’une des variables avec laquelle nous faisons l’opération).

> a = 3
=> 3
> b = 2
=> 2
> c = a + b
=> 5

c vaut 5.

> a = 3
=> 3
> b = 2
=> 2
> a = a + b
=> 5

a vaut 5.

La valeur nil

Que se passe-t-il lorsque nous essayons d’utiliser une variable sans lui donner une valeur en la déclarant ? Voici ce que l’on obtient (pour déclarer la valeur sans l’initialiser, il suffit d’écrire variable = ).

> variable =
> variable
=> nil

Que signifie cette valeur nil ?

nil est une valeur particulière qui signifie l’absence de valeur, justement. Notre valeur n’a ici aucune valeur.

Pour le moment, savoir cela ne nous est pas très utile, mais gardons cette idée en tête : nil représente l’absence de valeur.

Constantes

Une constante est une variable dont la valeur ne peut pas être modifiée. Elle reste la même pendant tout le programme.

Pour déclarer une constante, il nous faut écrire ceci.

> PI = 3.14159265359
=> 3.14159265359

En fait, il suffit de commencer le nom d’une variable par une majuscule. C’est imposé par le langage. Ainsi, nous ne pouvons pas commencer le nom d’une variable normale par une majuscule, car nous aurons alors déclaré une constante. En essayant de modifier la valeur d’une constante nous aurons un avertissement (mais la valeur sera quand même changée). Ainsi si j’essaye de modifier la constante PI, j’obtiens ce message.

warning: already initialized constant PI
warning: previous definition of PI was here

Notons que nous avons écrit le nom de la constante tout en majuscules, entre autres parce que c’est la convention de nombreux langages, mais aussi pour pouvoir la repérer plus facilement.

Conventions de nommage

Nous avons commencé à parler de conventions de nommage pour les constantes. Continuons à en parler. Tout d’abord, nous devons préciser que tous les noms de variable ne sont pas possibles. Il y a des règles :

  • un nom de variable ne peut pas commencer par un chiffre ;
  • un nom de variable ne peut pas contenir de signe de ponctuation ;
  • un nom de variable ne peut pas contenir de symbole opératoire (+, -, *, /, %).

À cela, il faut ajouter qu’un certain nombre de mots ne peuvent pas être utilisés comme noms de variable. Ce sont des mots réservés pas Ruby. Ils font partie du langage et ont un sens propre qui fait qu’on ne peut pas les utiliser. Les voici.

=begin

break

elsif

module

retry

unless

=end

case

end

next

return

until

BEGIN

class

ensure

nil

self

when

END

def

false

not

super

while

alias

defined?

for

or

then

yield

and

do

if

redo

true

__FILE__

begin

else

in

rescue

undef

__LINE__

De plus, il est conseillé d’écrire ses variables en « snake_case ». Cela signifie que toutes vos variables seront écrites en minuscules et que les changements de mot seront signalés par un tiret bas.

Les constantes, elles, doivent être écrites en « SCREAMING_SNAKE_CASE ». Elles doivent donc être écrites en majuscule, les changements de mot signalés par un tiret bas.

ma_super_variable
MA_SUPER_CONSTANTE

Finalement, et là il ne s’agit que de logique simple, il faut donner à nos variables des noms clairs et explicites. Il faut par exemple préférer nom à n. Évitons également de mélanger les noms en anglais et en français.

Dans ce tutoriel, nous allons suivre les bonnes pratiques de Ruby. Elles demandent des noms de variables en anglais et nos noms de variables seront donc en anglais. Mais pas d’inquiétude, ce n’est pas de l’anglais compliqué et les codes seront bien sûr expliquées. De plus, c’est une bonne manière de travailler un peu son anglais, langue qui sera indispensable dans l’informatique.

Chaînes de caractères

Pour afficher une chaîne de caractères (soit un mot ou une phrase), il faut l’entourer de guillemets simples ou doubles.

> "Bonjour"
=> "Bonjour"
> 'Bonjour'
=> "Bonjour"

Pour déclarer une variable contenant une chaîne de caractères, nous devons toujours utiliser le signe « = ». Il faut cependant faire attention à ne pas oublier les guillemets. De la même manière que pour les nombres, nous devons choisir un identifiant et lui assigner une valeur. De plus, nous pouvons également déclarer des chaînes de caractères constantes, toujours en écrivant la première lettre de l’identifiant en majuscule.

> word = 'zeste'
=> "zeste"
> Constant = 'vrai'
=> "vrai"

Ici, la variable word a alors pour valeur la chaîne de caractères zeste.

Nous pouvons également utiliser les syntaxes %(), %q() et %Q() pour déclarer une chaîne de caractères.

> word = %(zeste)
=> "zeste"
> word = %q(zeste)
=> "zeste"
> word = %Q(zeste)
=> "zeste"

Nous pouvons remplacer les parenthèses par des crochets, des accolades, ou encore des chevrons. En fait, nous pouvons utiliser plusieurs caractères non alphanumériques comme %, |, ^, *, etc. On a alors équivalence entre %(), %|| et %[].

Opérations sur les chaînes de caractères

Nous pouvons effectuer quelques opérations sur les chaînes de caractères.

> 'Bonjour ' + 'tout le monde'
=> "Bonjour tout le monde"

Cette opération s’appelle la concaténation (on dit qu’on concatène les deux chaînes). Elle permet de mettre deux chaînes bout à bout. Nous pouvons aussi insérer une variable dans une chaîne de caractères grâce à la concaténation.

> word = 'zeste'
=> "zeste"
> 'Faites un ' + word + ' envers votre prochain.'
=> "Faites un zeste envers votre prochain."

Ici, nous avons concaténé trois chaînes de caractères.

La concaténation se fait avec l’opérateur +. Si nous voulons obtenir plusieurs fois la même chaîne, nous pouvons utiliser l’opérateur *.

> word = 'zeste '
=> "zeste "
> word * 3
=> "zeste zeste zeste "

La même chaîne a été concaténée trois fois.

Une autre opération utile permet de rajouter une chaîne à la fin d’une chaîne de caractères. On peut aussi dire que c’est une concaténation. Cependant, le résultat de cette concaténation est directement affecté à la variable de départ.

> mot = 'zeste'
=> "zeste "
> mot << ' de savoir'
=> "zeste de savoir"

La variable word vaut alors zeste de savoir. Notons que cette concaténation ne s’utilise pas qu’avec des variables. Il est possible d’écrire 'zeste' << ' de savoir'.

Tout comme pour les autres variables, nous pouvons récupérer le résultat de l’opération dans une variable.

Ainsi…

> mot = 'zeste '
=> "zeste "
> repeated = mot * 3
=> "zeste zeste zeste "

La variable repeated vaut zeste zeste zeste.

Et vérifions que nous pouvons bien écrire 'zeste' << ' de savoir'.

> word = 'zeste' << ' de savoir'
=> "zeste de savoir"

On obtient alors la valeur "zeste de savoir" pour la variable mot sans étape intermédiaire. Il est conseillé d’utiliser << plutôt que +. En effet, << est plus rapide, car il modifie la chaîne de caractères directement.

Après la concaténation, parlons de l’interpolation de chaînes de caractères. Elle permet tout comme la concaténation de « rajouter des données dans une chaîne », mais s’avère parfois plus efficace. L’interpolation s’effectue de cette manière : on utilise # suivi de la variable entre accolades à l’endroit de la chaîne où nous voulons l’ajouter. Un exemple.

> variable = 'de savoir'
=> "de savoir"
> word = "zeste #{variable}"
=> "zeste de savoir"

L’interpolation marche avec tous les types de variables que nous avons vus, pas seulement avec les chaînes de caractères. On peut même effectuer des calculs. Notons qu’il est conseillé de ne pas mettre d’espaces autour du code interpolé.

> variable = 123 
=> 123
> "123 * 2 = #{variable * 2}"
=> "123 * 2 = 246"
> "123 + 2 = #{123 + 2}"
=> 123 + 2 = 125"

L’interpolation ne s’utilise qu’avec les guillemets doubles. Avec les guillemets simples, nous obtiendrons « #{variable} ».

Il faut privilégier l’interpolation et ne pas trop utiliser la concaténation.

Conversion de variables

En Ruby, nous pouvons convertir des variables (changer le type de la variable) en utilisant une méthode.
Nous verrons ce qu’est une méthode dans un autre chapitre. Pour le moment, nous pouvons considérer qu’une méthode nous permet d’effectuer une action. Ici nous devrons juste mettre à la fin de notre variable l’une de ces expressions.

Code Action
.to_s Convertir en chaîne de caractères (string).
.to_i Convertir en entier (int).
.to_f Convertir en flottant (float).

Exemple.

> x = 3
=> 3
> x.to_s
=> "3"

Si nous essayons de convertir une chaîne de caractères qui n’est pas un nombre en entier (int) ou en flottant (float), nous obtiendrons 0 pour la conversion en entier, et 0.0 pour la conversion en flottant.

> x = 'Bonjour'
=> "Bonjour"
> x.to_i
=> 0
> y = 'zeste'
=> "zeste"
> y.to_f
=> 0.0

Alors que…

> x = '3'
=> "3"
> x.to_i
=> 3
> x.to_f
=> 3.0

Cette conversion peut s’avérer très utile lorsque nous voulons par exemple concaténer un nombre à une chaîne de caractères.

Cependant, cette conversion ne modifie pas la variable. Elle nous donne une nouvelle valeur que nous pouvons récupérer dans une variable, mais la variable initiale garde son ancienne valeur.

Saisir et afficher des informations

À partir de maintenant, nos programmes seront plus conséquents et le nombre de lignes sera donc plus important. Le chapitre « Écrire le code dans des fichiers » nous apprendra à écrire notre code dans des fichiers.

Dès à présent dans nos exemples, nous utiliserons des commentaires. Les commentaires sont des messages qui sont ignorés par l’interpréteur et qui permettent de donner des indications sur le code (car relire ses programmes après plusieurs semaines d’abandon, sans commentaires, peut parfois être plus qu’ardu).

En Ruby, un commentaire débute par un croisillon (#) et se termine par un saut de ligne. Tout ce qui est compris entre ce # et ce saut de ligne est ignoré. Un commentaire peut donc occuper la totalité d’une ligne (on place le # en début de ligne) ou une partie seulement, après une instruction (on place le # après la ligne de code pour la commenter plus spécifiquement).

Nous pouvons également faire des commentaires multi-lignes. Pour cela, il faut placer notre commentaire entre =begin et =end. Mais nous n’allons pas les utiliser et allons plutôt utiliser plusieurs lignes commençant par # pour écrire un commentaire sur plusieurs lignes.

Afficher des informations

Depuis le début, nous utilisons IRB pour programmer en Ruby. Cependant, maintenant, lorsque nous n’utiliserons pas IRB et mettrons nos programmes dans des fichiers, il nous faudra un moyen d’afficher les résultats obtenus et le contenu de nos variables. Pour cela, nous allons encore une fois utiliser une méthode.

Nous avons deux méthodes pour afficher des informations, puts et print. Elles ont un fonctionnement similaire (les deux affichent ce qui est demandé sur la sortie standard qui est par défaut la console) à la différence près que contrairement à print, puts va à la ligne après avoir effectué l’affichage. Leur utilisation est par contre parfaitement similaire. Nous allons donc voir l’exemple de puts.

Pour afficher une chaîne de caractères ou un nombre voici le code à utiliser.

puts "Chaîne"
puts 2
puts 3.5

Ces lignes de codes vont afficher « Chaîne », aller à la ligne, afficher 2, aller à la ligne et finalement afficher 3.5 et… aller à la ligne.

Nous pouvons également afficher le contenu d’une variable de la même manière.

a = 3
puts a

Ce programme nous affichera 3 et un saut de ligne.

Notons finalement qu’en utilisant la virgule pour séparer des éléments, la méthode est appelée plusieurs fois et affiche chacun des éléments. Le code print 'Bonjour', 2, 45.8 équivaut à ce code.

print 'Bonjour'
print 2
print 45.8 

Ceci nous sera très utile. Cependant, lorsque nous voulons afficher une chaîne de caractères et des variables, il vaut mieux utiliser l’interpolation de chaînes de caractères. Ainsi, nous écrirons…

print "Bonjour #{variable1} #{variable2}"

… plutôt que…

print 'Bonjour'
print variable1
print variable2

Les méthodes puts et print ne sont pas très compliquées. Nous allons maintenant voir comment demander des informations à l’utilisateur.

La méthode gets

Si nous voulons demander des informations à l’utilisateur, la méthode gets est toute désignée. Voici comment l’utiliser.

print 'Entrez votre nom : '
name = gets.chomp
print "Bonjour #{name}"

Le mieux est d’essayer. Après avoir affiché « Entrez votre nom : », le programme se stoppe. Là, nous saisissons quelque chose avant de valider en appuyant sur la touche Entrée. Nous devrions obtenir une sortie ressemblant à ceci (ici, nous avons saisi « Zesteur »).

Entrez votre prénom : Zesteur
Bonjour Zesteur 

Pourquoi rajouter .chomp après le gets ?

En fait, c’est la méthode gets qui permet de demander une saisie à l’utilisateur. Elle nous renvoie une chaîne de caractères. Essayons donc name = gets. Affichons maintenant name. Et là, nous voyons le souci : gets nous laisse un \n. Nous ne voulons pas nous embarrasser d’un caractère gênant. Autant le supprimer tout de suite. chomp s’applique à une chaîne de caractères (ici la chaîne renvoyée par gets) et supprime ce \n. Ainsi, nous aurions également pu faire ceci.

name = gets
name = name.chomp

Ici, on récupère d’abord la saisie de l’utilisateur et seulement à la ligne d’après on supprime le \n.

gets.chomp renvoie une chaîne de caractères. Si on veut par exemple faire des calculs, il faudra faire une conversion.

Les caractères spéciaux

Ce \n, que nous venons de croiser, qu’est-ce que c’est ? En fait, \n est un caractère spécial qui représente un retour à la ligne. On parle de séquences d’échappement (les caractères sont échappés par le caractère \). Nous pouvons même l’utiliser pour aller à la ligne dans nos affichages. Par exemple…

print "zeste\n"        # Affiche « zeste » et va à la ligne.
print "zeste\n savoir" # Affiche « zeste », va à la ligne et affiche « savoir » .

Les séquences d’échappement peuvent être très utiles. Voyons quelques autres séquences d’échappement.

Nom

Description

Code de test

\a

Fait un bip.

print "\a"

\b

Efface le caractère précédent.

print "x\b"

\n

Va à la ligne.

print "x\nz"

\r

Retourne en début de ligne.

print "xxx \rzzz"

\s

Affiche un espace.

print "x \s z"

\t

Affiche une tabulation horizontale.

print "x \t z"

Puisque \ permet d’échapper des caractères pour obtenir des caractères spéciaux, si nous voulons afficher un antislash, il nous faudra utiliser \\.

Notons que les caractères spéciaux ne sont compris qu’avec les guillemets doubles (on dit qu’ils sont échappés). print 'Bonjour\nzz' affichera Bonjour\nzz. Le seul caractère qui est échappé avec les guillemets simples est \' qui permet d’afficher des guillemets simples. De même, \" permet d’afficher des guillemets doubles lorsqu’on les utilise pour délimiter la chaîne de caractère.

Les bonnes pratiques de Ruby veulent que l’on garde un style de guillemets constant. Voici deux styles que l’on peut utiliser.

  1. Préférer les chaînes à guillemets simples lorsqu’il n’y a pas d’interpolation, de caractères spéciaux ou de guillemets simples.
  2. Préférer les chaînes à guillemets doubles lorsque la chaîne ne contient pas de caractères à échapper ou de guillemets doubles.

L’important est de choisir une règle et de la respecter.

Certaines bonnes pratiques sont également posées sur l’utilisation des syntaxes %. Les syntaxes % et %Q sont équivalentes (% est un raccourci) et correspondent à des guillemets doubles, la syntaxe %q à des guillemets simples. On a alors ces règles :

  • il faut utiliser % pour les chaînes de caractères qui contiennent le caractère " et de l’interpolation ;
  • il ne faut pas utiliser %q à moins que notre chaîne ne contienne les caractères " et ' ;
  • il faut préférer () comme délimiteur (on écrira %(une chaîne avec écrit "#{variable}") plutôt que %{une chaîne avec écrit "#{variable}"}).

Exercices

C’est l’heure de pratiquer. Nous allons donc faire quelques petits exercices.

Exercice 1

Commençons par un petit exercice : demandons à l’utilisateur son nom et son prénom et affichons « Bonjour nom prénom » suivi d’un retour à la ligne.

Correction.

Nous allons utiliser deux variables nom et prénom et demander leur valeur à l’utilisateur, puis les afficher grâce à une interpolation.

print 'Entrez votre nom : '   
last_name = gets.chomp
print 'Entrez votre prénom : '
first_nom = gets.chomp
puts "Bonjour #{las_name} #{first_name}."

Notons que nous avons utilisé print quand nous ne voulions pas aller à la ligne et puts quand nous voulions aller à la ligne.

Exercice 2

Nous devons maintenant demander à l’utilisateur d’entrer deux nombres x et y, échanger leurs valeurs, et afficher leur nouvelle valeur. Voici ce que nous devons obtenir.

Entrez x : 23
Entrez y : 12
L’échange a été effectué : x vaut 12 et y vaut 23.

Le but est de vraiment échanger les valeurs des deux variables, pas juste d’afficher la valeur de l’une pour l’autre.

Correction.

La difficulté est l’échange des deux variables. Pour ce faire, nous allons utiliser une variable temporaire que nous appellerons tmp. Nous stockerons la valeur de x dans tmp, puis nous affecterons à x la valeur de y et enfin y prendra la valeur de tmp.

print 'Entrez x : '
x = gets.chomp.to_i
print 'Entrez y : '
y = gets.chomp.to_i

tmp = x
x = y
y = tmp
print "L’échange a été effectué : x vaut #{x} et y vaut #{y}."
Exercice 3

Cette fois, nous devons demander à l’utilisateur son âge en années (un entier) et afficher sur différentes lignes :

  • son âge en années ;
  • son âge en jours (on va considérer que toutes les années ont 365 jours) ;
  • son âge en heures ;
  • son âge en minutes ;
  • son âge en secondes.

Oui, ça va demander plusieurs calculs. Mais c’est bien ça le but.

Correction.

Nous pouvons effectuer les calculs de plusieurs manières. Mais, le but est de ne pas faire de calculs inutiles. Ainsi, nous pouvons soit créer plusieurs variables pour contenir l’âge dans les différentes unités, soit avoir une seule variable et afficher l’âge dans une unité puis la convertir dans l’unité suivante et afficher et ce jusqu’à avoir tout affiché.

Dans tous les cas, pour ne pas faire de calculs inutiles, il vaut mieux utiliser le résultat du calcul précédent pour faire le calcul suivant. Il faut donc utiliser l’âge en années pour calculer celui en jours, celui en jours pour calculer celui en heures…

Voici le programme, fait des deux manières que nous avons évoquées.

print 'Entrez votre âge : '
age = gets.chomp.to_i # On convertit la saisie en entier.
puts age
age = age * 365       # On passe aux jours.
puts âge
age = age * 24        # On passe aux heures.
puts age
age = age * 60        # On passe aux minutes.
puts age
age = age * 60        # On passe aux secondes.
puts age

Dans celui-ci on affiche la variable age avant de passer à l’unité suivante et ainsi de suite.

Voici le deuxième, dans lequel on va créer des variables pour les jours, les heures, les minutes et les secondes.

print 'Entrez votre âge : '
age = gets.chomp.to_i # On convertit la saisie en entier.
days = age * 365
hours = days * 24
minutes = heures * 60
seconds = minutes * 60
puts age
puts days
puts hours
puts minutes
puts seconds
Exercice 4

Finissons avec un exercice pour bien travailler les conversions : demandons à l’utilisateur deux nombres, puis affichons sur des lignes différentes le résultat de l’addition, de la soustraction, de la multiplication et de la division du premier nombre par le deuxième. Si l’utilisateur rentre 6 et 4, le résultat attendu est celui-ci.

6.0 + 4.0 = 10.0
6.0 - 4.0 = 2.0
6.0 * 4.0 = 24.0
6.0 / 4.0 = 1.5 

L’affichage nous donne déjà un indice : nous devrons utiliser des flottants.

Correction.

Nous demandons les deux nombres et les convertissons en flottants, puis nous affichons toutes les données.

print 'Entrez le premier nombre : '
number1 = gets.chomp.to_f # On demande le nombre 1 et on le convertit en flottant.
print 'Entrez le deuxième nombre : '
number2 = gets.chomp.to_f # On demande le nombre 2 et on le convertit en flottant.

puts "#{number1} + #{number2} = #{number1 + number2}"
puts "#{number1} - #{number2} = #{number1 - number2}" 
puts "#{number1} * #{number2} = #{number1 * number2}"
puts "#{number1} / #{number2} = #{number1 / number2}" 

Maintenant que nous maîtrisons les variables, nous allons passer au chapitre sur les conditions et les boucles.

  • Ruby nous permet de déclarer des variables et des constantes, mais certains noms sont interdits. Ces variables peuvent être des nombres, mais aussi des chaînes de caractères.
  • Plusieurs opérations sont possibles sur les chaînes de caractères  (concaténation, interpolation) et il y a plusieurs manières de les déclarer (en fonction des situations, nous allons en privilégier certaines).
  • Les méthodes print et puts permettent d’afficher quelque chose sur la sortie standard (par défaut la console). Certains caractères sont spéciaux et doivent être échappés pour être affichés. Les guillemets simples et doubles ne se comportent pas de la même manière face aux caractères spéciaux et à l’interpolation.
  • La méthode gets permet de demander à l’utilisateur de rentrer une chaîne de caractères. Nous pouvons ensuite la convertir en nombre si besoin en utilisant une méthode comme to_i.