# Programmation D/Éléments de base du langage et programmation impérative

* Avant de commencer
* Votre premier programme
* Éléments de base du langage et programmation impérative
* Programmation orientée objet
* Éléments avancés du langage
* Outils
* Annexes
* Conclusion
* Avant de commencer
* Votre premier programme
* Éléments de base du langage et programmation impérative
* Programmation orientée objet
* Éléments avancés du langage
* Outils
* Annexes
* Conclusion
[ Modifier le sommaire ]

## Les commentaires

J'ai remarqué dans l'exemple précédent // j'imprime sur la sortie standard. Que cela veut-il dire ? Ceci est un commentaire. En effet, vous pouvez laisser dans votre code des explications (c'est d'ailleurs très fortement recommandé). Il existe plusieurs formes de commentaires :
Commentaire sur une ligne
Commentaires multi-lignes
Vous remarquerez qu'il est parfois écrit « documentation » au lieu de « commentaire ». En effet, on peut documenter son code. Ainsi, un programme externe va lire votre code source et générer automatiquement la documentation. Pour les connaisseurs, c'est le même principe que la javadoc ou doxygen. Nous y reviendrons plus loin dans ce chapitre.

## Les types primitifs

Note 1 : les valeurs suivantes ont été obtenues sur un système 64 bits.
Note 2 : vous pouvez générer ces résultats avec le programme D pour connaitre la taille des types.
| Type | Description | Min | Max |
| byte | Valeur entière sur 1 octet (8 bits) | -128 | 127 |
| ubyte | Valeur entière positive sur 1 octet (8 bits) | 0 | 255 |
| short | Valeur entière sur 2 octets (16 bits) | -32768 | 32767 |
| ushort | Valeur entière positive sur 2 octets (16 bits) | 0 | 65535 |
| int | Valeur entière sur 4 octets (32 bits) | -2147483648 | 2147483647 |
| uint | Valeur entière positive sur 4 octets (32 bits) | 0 | 4294967296 |
| long | Valeur entière sur 8 octets (64 bits) | -9223372036854775808 | 9223372036854775807 |
| ulong | Valeur entière positive sur 8 octets (64 bits) | 0 | 18446744073709551615 |
| float | Valeur numérique sur 4 octets (32 bits) | 1.18e-38 | 3.40e+38 |
| ifloat | Valeur numérique imaginaire pure sur 4 octets (32 bits) | 1.18e-38i | 3.40e+38i |
| double | Valeur numérique sur 8 octets (64 bits) | 2.23e-308 | 1.80e+308 |
| idouble | Valeur numérique imaginaire pure sur 8 octets (64 bits) | 2.23e-308i | 1.80e+308i |
| real | Le plus grand numérique supporté par le processeur soit 16 octets (128 bits) | 3.36e-4932 | 1.19e+4932 |
| ireal | Le plus grand numérique supporté par le processeur soit 16 octets (128 bits) | 3.36e-4932i | 1.19e+4932 |
| char | Un caractère imprimable encodé en UTF-8 sur 1 octet (8bits) | 0 | 255 |
| wchar | Un caractère imprimable encodé en UTF-16 sur 2 octets (16bits) | 0 | 65535 |
| dchar | Un caractère imprimable encodé en UTF-32 sur 4 octets (32bits) | 0 | 4294967293 |
| cfloat | Nombre complexe de 2 valeurs flottantes (float) | 1.18e-38 +1.18e-38i | -nan |
| cdouble | Nombre complexe de 2 doubles | 2.23e-308 +2.23e-308i | 1.19e+4932 |
| creal | Nombre complexe réel | 3.36e-4932 +3.36e-4932i | 1.19e+4932 |

## Les opérateurs arithmétiques

+ permet d'additionner deux variables numériques. - permet de soustraire deux variables numériques. * permet de multiplier deux variables numériques. / permet de diviser deux variables numériques. % permet de renvoyer le reste de la division euclidienne de deux variables de type numérique, cet opérateur s'appelle le modulo.
Par exemple :

### Une histoire d'incrémentation et décrémentation

Dans la même catégorie, il existe l'incrémentation et la décrémentation :
* l'incrémentation consiste à augmenter de 1 la valeur de la variable.
* la décrémentation consiste à diminuer de 1 la valeur de la variable.
Pour cela, il y a plusieurs façons de le faire. Prenons le cas de l'incrémentation : int a = 2; a = a + 1; a += 1; a++; ++a Vous remarquez que les 2 dernières formes sont plus rapides à écrire (oui, le programmeur est un fainéant).
Y a t-il une différence entre ++a et a++ ?
Oui, il y en a une et elle est subtile :
* a++ : utilise la valeur de a, puis l'incrémente
* ++a: incrémente la valeur de a, puis l'utilise
Par exemple :

#### Autres raccourcis

On peut également utiliser les raccourcis pour la multiplication, la division et le reste de la division euclidienne. un court exemple :

##### Attention

Je vous mets en garde sur le type utilisé. Ce dernier peut avoir des conséquences graves ! En effet, jusqu'ici on a utilisé le type uint et nos résultats étaient des entiers. Mais ceci n'est pas systématiquement vrai. Par exemple, diviser 1 par 3 donne un résultat décimal ne pouvant pas correspondre à un entier positif (uint). Par conséquent, vous devez utiliser un autre type plus approprié, comme le type float ou double :

## Les opérateurs de comparaison

Il est fréquent dans un programme que l'on ai de besoin de comparer. Pour cela, en D il est possible de tester différents cas :
* tester une égalité
* tester une différence
* comparer a ou b
* comparer a et b

### Test d'identité

Les comparateurs d'identités sont particuliers et méritent plus d'explications. Si l'on compare :
* des types entre eux (par exemple int)
Lorsque l'on compare des types avec ce comparateur, il agit comme si c'était le comparateur ==
* des objets
Lorsque l'on compare des objets entre eux, ce comparateur va dire si oui ou non c'est le même objet qui est référencé. On reviendra plus tard sur les références, gardez les à l'esprit et n'hésitez pas à revenir dessus.
Le comparateur !== est la négation du comparateur === donc

## Les conditions

Nous avons vu les opérateurs de comparaison : maintenant, nous allons les utiliser avec les conditions. Rien de plus simple ! Commençons de suite.

### Avec les mots clés if et else

C'était un exemple pour vous dégourdir les méninges. Complexifions légèrement avec divers exemples d'utilisation :

### Avec les mots clés switch et case

Vous avez vu précédemment la possibilité d'imbriquer des si - sinon de la manière suivante :
Sachez qu'il existe une manière plus élégante d'écrire cela à l'aide des mots clés switch et case :
Pourquoi retrouve-t-on break à chaque fois ? Admettons, pour imager, 2 choses :
* que la variable a vaut 3
* que le mot clé break soit absent
D'après l'exemple précédent, on entrerait dans le bloc à partir du cas 3 et on effectuerait tous les cas suivants, c'est à dire ici le cas 4 et le cas par défaut. Dans la majeure partie des cas, on n'a pas besoin d'exécuter 2 règles, c'est pour cela que l'on met l'instruction break afin qu'il quitte après avoir effectué son traitement. Un dernier exemple du même type pour la route :
Ici, on va rentrer dans le cas 1, 2 et 3 puis sortir.
Ce comportement est similaire en C et en C++. Mais en D, on peut également utiliser des chaînes de caractères :

## Les tableaux
### Déclaration

Il y a 5 façons de déclarer un tableau :
| Code | Description |
| int* p; | Pointeur vers les données |
| int[3] s; | Tableau statique |
| int a; | Tableau dynamique |
| int[char] x; | Tableau associatif |
| int m; | Matrice |

#### Les pointeurs

Ceci est un simple pointeur vers des données., il représente la même chose qu'en C.
Attention cependant, contrairement au C, le code suivant
déclare deux pointeurs vers des entiers, alors qu'en C, il déclare un pointeur et un entier ! Pour cette raison, il est d'usage de toujours rattacher l'astérisque au type de données plutôt qu'au nom de la variable.

#### Les tableaux statiques

Un tableau statique est un tableau dont on spécifie la taille lors de sa déclaration, taille qui ne changera plus. Ici, on crée un tableau dans lequel on peut stocker 3 entiers. La taille d'un tableau statique est fixée au moment de la compilation.
Par exemple :

#### Les tableaux dynamiques

Un tableau dynamique est un tableau dont la taille peut varier. Lors de sa déclaration, on ne spécifie pas sa taille. En fait, c'est le ramasse-miette (garbage collector) qui gère ce tableau au moyen d'un pointeur.
Exemple :
Il est conseillé de faire le minimum de redimensionnements de tableau possibles afin de garder de bonnes performances. Ainsi, on évitera :
On utilisera de préférence :

#### Les tableaux associatifs

Un tableau associatif est un tableau où l'on associe 2 valeurs ensemble. Ici, on associe une chaîne de caractères à un entier.
Astuce: pour comprendre ce que que représente un tableau associatif, je vous conseille de le lire de la droite vers la gauche. Soit :
Le tableau associatif x contient des chaînes de caractères qui sont associées à un entier
Exemple :
Dans l'exemple ci-dessus, on associe un fruit à un nombre (pratique pour connaitre la quantité restante de chaque fruit).

### Les propriétés

Propriétés des tableaux statiques :
| Propriétés | Descriptions |
| .sizeof | Retourne la taille du tableau multipliée par le nombres d'octets pour chaque élément du tableau |
| .length | Retourne le nombre d'éléments dans le tableau. Cette valeur ne peut pas être modifiée pour les tableaux statiques |
| .ptr | Retourne un pointeur sur le premier élément du tableau |
| .reverse | Inverse l'ordre des élements (le premier devient le dernier) et renvoie le tableau inversé |
| .sort | Trie les éléments du tableau et renvoie le tableau trié |
| .dup | Crée un tableau dynamique de la même taille et copie tous les éléments dans ce tableau puis renvoie ce tableau |
Propriétés des tableaux dynamiques :
| Propriétés | Descriptions |
| .sizeof | Retourne la taille de la réference du tableau dynamique, qui est de 8 sur un ordinateur 32 bits |
| .length | Permet d'obtenir ou de changer la taille du tableau |
| .ptr | Retourne un pointeur sur le premier élément du tableau |
| .reverse | Inverse l'ordre des élements (le premier devient le dernier) et retourne le tableau inversé |
| .sort | Trie les éléments du tableau et renvoie le tableau trié |
| .dup | Crée un tableau dynamique de la même taille, et copie tous les éléments dans ce tableau puis retourne ce tableau |

### Le slicing

Le slicing est une technique particulière qui permet de copier une série d'éléments d'un tableau dans un autre. Voici un exemple de cette technique :

### Concaténation de tableaux

On peut combiner le slicing et la concaténation :

### Les matrices

Peu de langages supportent nativement les matrices, mais le langage D en fait partie.
Qu'est-ce qu'une matrice ?
Mieux qu'un long discours voici un exemple :
Ceci est une matrice de 3 colonnes par 4 lignes :

## Les chaînes de caractères

Les langages de programmation doivent bien gérer les chaînes de caractères. Le C et le C++ ne sont pas très bons pour cela. La première difficulté est de gérer la mémoire, les traitements temporaires, de constamment scanner les chaînes de caractères pour rechercher la terminaison par "\0" et de fixer la taille.
Les tableaux dynamiques en D suggèrent la solution la plus évidente. Une chaîne est simplement un tableau dynamique de caractères. Les chaînes littérales sont juste un moyen facile d'écrire des tableaux de caractères.
Par défaut les chaînes de caractère sont encodées en utf8. Il existe également les types:
* wchar
* wchar
* dchar
* dchar
Si une chaîne est ambigüe et peut correspondre à plusieurs types, il faut préciser.
Si on veut de l'UTF-16, on peut faire un cast (voir « Le transtypage (cast) ») :
Ou si on veut de l'UTF-32 :

### Les tableaux associatifs

à déplacer ?
Le langage D intègre nativement les tableaux associatifs. Précédemment, vous avez eu un court exemple de leur utilisation. Voici quelques autres exemples :
Propriété :
| Propriétés | Descriptions |
| .sizeof | Renvoie la taille de la référence vers le tableau associatif |
| .length | Renvoie le nombre de valeurs dans le tableau associatif. À la différence des tableaux dynamiques, on ne peut pas changer sa valeur. |
| .keys | Renvoie un tableau dynamique contenant les clés du tableau associatif |
| .values | Renvoie un tableau dynamique contenant les valeurs du tableau associatif |
| .rehash | Réorganise le tableau associatif pour gagner en performance. Retourne une référence du tableau réorganisé. |

#### Dépassement de la taille du tableau

Le dépassement de la taille limite du tableau constitue une erreur fréquemment rencontrée. Le compilateur vous annoncera « Array index out of bounds ». Vous apprendrez plus loin comment attraper et gérer les exceptions.

#### Important

En D 1.x comme dans d'autres langages tels que le Python, les tableaux et les objets sont passés par référence et non par copie.
Qu'est-ce que cela veut dire ?
Pour faire simple, une référence est une entité qui pointe vers son original. Si l'on modifie la référence, cela modifie l'original. C'est un comportement qui permet d'éviter de recopier un tableau (ce qui peut être long) mais qui, si l'on ne fait pas attention, peut générer des erreurs. Gardez bien cela à l'esprit, c'est capital !
Si le besoin d'une copie et non d'une référence se fait sentir, ils vous suffit de la demander avec la propriété dup :

##### Exemple

Vous voyez votre tableau a été modifié à votre insu, vous avez sur le terminal :
Vous vous retrouvez avec le tableau modifié par la fonction ajoute, si vous ne voulez pas ce comportement vous devez envoyer une copie du tableau, voici en exemple:
Ce qui donne :
Si le besoin d'une copie et non d'une référence se fait sentir, ils vous suffit de la demander avec la propriété dup :

#### Attention

À partir de la version 2 du langage, les tableaux statiques sont passés par valeur ! Ce changement permet une meilleure vectorisation du code (notamment pour l'utilisation par le compilateur d'instructions comme les SSE) et facilite la programmation concurrente. Pour porter du code D1 vers D2 et revenir à l'ancien comportement, il suffira de passer un slice complet du tableau en paramètre, les slices, comme les tableaux dynamiques, étant toujours passés par référence :

## Les boucles
### Tant que (while)

Tant que i est plus petit que 10, on boucle et on imprime sur la sortie standard la valeur courante de i.

### Faire tant que (do … while)

Cette boucle est semblable à la précédente, seulement ici on garantit au moins une fois le passage dans la boucle.

### Pour (for)

On peut effectuer la déclaration d'une variable, définir les conditions de la boucle et définir une action exécutée à chaque début de boucle (généralement l'incrémentation de cette variable) dans la déclaration de la boucle for :

### Pour chaque (foreach)

Pour chaque élément de a, on imprime sa valeur sur la sortie standard.
On peut également connaître le nombre d'itérations dans la boucle foreach. Par exemple, connaître le numéro de ligne ou l'indice du tableau en cours de traitement.

#### Aller à (goto)

Le goto n'est à utiliser que dans des cas précis. Il ne faut surtout pas en abuser et la plupart du temps les autres types de boucles suffisent. Depuis le temps que je programme je n'ai eu à l'utiliser qu'une seule fois. Le goto permet d'aller directement à un endroit du code défini par une étiquette :

## Le transtypage (cast)

En langage D, il existe 2 manières d'effectuer une conversion de type :
* avec le mot clé cast
* avec le module tango.util.Convert
La première façon de faire est générique et permet de caster (convertir) tout et n'importe quoi. C'est l'équivalent du dynamic_cast pour les connaisseurs du C++. La seconde manière est restreinte au type cité dans un chapitre précédent mais est plus sûre. Exemples :
On utilise le module Convert uniquement pour utiliser le template "to" (le mot clé cast n'a besoin d'aucun module).

## Lire les entrées clavier

Demander le nom et l'âge :
On doit convertir ce qui a été saisie par l'utilisateur (char) en uint.

## Parser les arguments de la ligne de commande

La bibliothèque tango propose un module très pratique pour parser les arguments de la ligne de commande. Il existe un tutoriel en anglais ici. Je vais vous présenter la manière dont je l'utilise :
* ↑ Si vous n'êtes pas familier avec les pointeurs, vous pourrez en apprendre plus dans La mémoire, une question d'adresse sur le site du zéro