mardi 5 décembre 2017

Création d'un menu

Une astuce érgonomique très répondue est la création des menus. Elle souvent utilisée lorsque le programme fait plusieurs choses (plusieurs traitements).

Pour réaliser un menu, il nous faut the structures de contrôle :
  1. Une structure Case ... of (switch en Java) : cette structure permet d'exécuter le traitement adéquat au choix effectué par l'utilisateur.
  2. Une boucle Répéter ... Jusqu'à pour garantir que l'utilisateur fera un choix valide (principe par ici).
Ainsi, le code d'un menu simple sera en Pascal :


Program Menu;

Const
 MIN = 1;
 MAX = 6;
Var 
 option : Integer;

Begin

 WriteLn('Bienvenue dans ce menu inutil :');
 WriteLn('1 - Créer un nouveau fichier');
 WriteLn('2 - Ouvrir un fichier existant');
 WriteLn('3 - Supprimer un fichier existant');
 WriteLn('4 - Créer un nouveau dossier');
 WriteLn('5 - Ouvrir un dossier existant');
 WriteLn('6 - Supprimer un dossier existant');
 WriteLn();
 
 Repeat
  WriteLn('Votre choix ?');
  ReadLn(option);
  
  Case (option) of
   1 : WriteLn('Créer un nouveau fichier');
   2 : WriteLn('Ouvrir un fichier existant');
   3 : WriteLn('Supprimer un fichier existant');
   4 : WriteLn('Créer un nouveau dossier');
   5 : WriteLn('Ouvrir un dossier existant');
   6 : WriteLn('Supprimer un dossier existant');
  else 
   WriteLn('Option invalide');
  End;
 Until ((option >= MIN) And (option <= MAX));
  
End.

 L'exécution sera :






Note : l'édition et l'exécution sont faites sous Geany (site officiel), il garde la fenêtre ouverte et vous donnera des informations sur le déroulement de l'exécution.

Garantir l'appartenance de la valeur entrée à un intervalle donné

Un problème souvent rencontré est la validation d'une valeur entrée par l'utilisateur. La forme la plus simple est de garantir l'appartenance de la valeur saisie à un intervalle donné. Par exemple, si la valeur saisie désigne un mois alors elle doit être comprise entre 1 et 12.

La solution la plus simple (sans faire recours à des bibliothèques) est l'utilisation d'une boucle de type Répéter ... Jusqu'à (Repeat ... Until) et ce pour deux raisons :

  1. Cette boucle est exécutée au moins une fois; la première lecture sera effectuée à l'intérieur de la boucle.
  2. Cette boucle garde l'utilisateur à l'intérieur jusqu'à ce qu'il fournit une valeur correcte.
Ainsi, le code suivant sera suffisant :


Program ForcerEntree;

Const
 MIN = 10;
 MAX = 100;
 
var 
 valeur : Integer;

BEGIN
 
 Repeat
  WriteLn('Faites entrer une valeur entre ', MIN, ' et ', MAX);
  ReadLn(valeur);
 Until ((valeur >= MIN) And (valeur <= MAX));
 WriteLn('Succès, vous avez saisi ', valeur);
 
END.

L'exécution sera ainsi :


mardi 28 novembre 2017

La somme des nombres entiers de 1 à N

Enoncé

Ecrire un algorithme qui calcule la somme des nombres entiers de 1 à N.

Plusieurs énoncés proches de celle-ci sont proposées et l’objectif est toujours le même : donner un premier exemple sur l’utilisation des boucles.

Dans cet article, nous allons voir cet exemple en se concentrant sur trois points essentiels :
  1. L’utilité des boucles, qui est l’objectif principal de l’exercice.
  2. L’exercice cache deux problèmes en un; faisons la séparation.
  3. L’exercice nous “force” à choisir la solution informatique au lieu de la solution mathématique.
Les boucles font partie des structures de contrôle. C’est à dire, elles visent à modifier l’enchaînement d’exécution des instructions en forçant l’ordinateur à ré-exécuter les mêmes instructions plusieurs fois. La forme simple est-ce que nous appelons la boucle Pour. Cette forme est utilisée lorsque nous connaissons combien de fois le code sera exécuté. Sans ces boucles, nous serons obliger de copier/coller le code autant de fois que nécessaire et il sera impossible de créer modifier le nombre de fois à l'exécution. La puissance du calcul (des milliards d'opérations par seconde) sera vraiment difficile à exploiter.

Un point essentiel dans cette forme est le compteur. Si nous connaissons l'intervalle ou le nombre de répétitions, il nous faut un compteur pour se rappeler de combien de fois avons nous déjà exécuter le bloc de la boucle.

C'est comme lorsque je vous demande de compter le nombre de billes (par exemple) dans un sac. Vous allez être obligé de se rappeler du nombre de billes que vous avez déjà compter; si vous oubliez ce nombre, vous serez obligé de recommencer depuis le début.

Se rappeler en algorithmique est synonyme de "variable" : une zone mémoire où nous pouvons stocker une information. Ainsi, ce compteur doit être une variable déclarée de type entier (qui peut être incrémentée).

Ainsi, un premier exemple sera en Pascal :

Program ExempleBoucle;  
Var 
           i : Integer;  
Begin  
           For i:= 1 to 10 Do  
                     WriteLn('Bonjour'); 
End.



Si la boucle contient une seule instruction alors le "Begin" et "End" ne deviennent plus nécessaires. Dans le cas contraire, vous devez informer le compilateur des instructions à répéter et il faut les séparer d'autres instructions qui viennent après la boucle, ainsi, le "Begin" et "End" deviennent obligatoires.

L'objectif de cet premier exemple est de vous montrer le mot "Bonjour" affiché dix (10) fois comme prévu. A chaque fois, le compteur "i" est incrémenté par un, ainsi, le programme se rappelle du nombre de répétition et est-ce qu'il aterminé l'exécution ou pas. IL N'EST PAS OBLIGATOIRE D'UTILISER LE COMPTEUR "i" A L'INTERIEUR DE LA BOUCLE, son rôle principal est de compter le nombre de fois seulement.

Néanmoins, nous pouvons voir que ses valeurs consécutives sont intéressantes pour le problème que nous tentons de résoudre :


Program ExempleBoucle;  
Var 
              i : Integer;  
Begin  
              For i:= 1 to 10 Do  
                            WriteLn('Valeur actuelle de i : ', i); 
End.


En effet, notre objectif est de calculer la somme : 1 + 2 + 3 + ... + N.
Cela ressemble aux valeurs de i dans sa boucle. Mais, il faut se rappeler que "i" ne prend pas toutes ces valeurs à la fois; il ne peut prendre qu'une seule valeur à la fois. Ces valeurs sont prises par "i" à travers les différentes itérations dans la boucle. Ainsi, à chaque itération, nous devons ajouter la valeur à la somme et attendre la prochaine itération pour obtenir une autre valeur (la valeur suivante) et ainsi de suite jusqu'à la fin de la boucle. Ainsi, la solution de l'exercise sera tout simplement :

Program ExempleBoucle;
Var
 i, n, somme : Integer;
Begin
        ReadLn(n);
 somme := 0;
 For i:= 1 to n Do
  somme := somme + i;
 WriteLn(somme);
End.


P. S. : Vous pouvez voir que l'affiche de la somme n'est exécuté qu'une seule fois. Sans un Begin et End le compilateur ne prend qu'une seule instruction comme bloc de la boucle.

La chose à ne pas faire 

Certains étudiants propose la solution suivante :


Program ExempleBoucle;
Var
 i, n, s : Integer;
Begin
        ReadLn(n);
 s := ((1 + n) * n) div 2;
 WriteLn(s);
End.

Nous pouvons exécuter cette solution et voir qu'elle donne exactement les même valeur (15 pour 5 et 55 pour 10) :

 
Néanmoins, pour un informaticien, cette solution est tout simplement fausse : c'est une solution d'un mathématicien. En effet, vous avez fait le calcul à la place de l'ordinateur. Si cela est facile pour l'exemple traité, cela ne sera pas toujours le cas; vous allez faire des calculs ou essayer de prouver des théorèmes pour simplifier les calculs au lieu de laisser la main à l'ordinateur avec sa puissance pour faire les calculs à votre place.

Si vous arriverez à séparer entre l'approche mathématique et l'approche algorithmique, cela sera un premier pas vers une meilleure compréhension de plusieurs problèmes en algorithmique et une meilleure utilisation de la puissance de votre ordinateur.

jeudi 16 novembre 2017

Le signe du produit sans le calculer : apprendre les conditions (expressions booléennes) compliquées

Énonce

Écrire un programme (un algorithme) qui demande deux nombres à l'utilisateur et l'informe si leur produit est positif, négatif ou bien nul sans le calculer.

L'objectif de cet exercice est une variété d'un autre exercice dans lequel on vérifie est ce qu'un nombre est positif, négatif ou bien nul. La différence ici est qu'on essaie de compliquer les conditions. Le reste de l'algorithme (la structure conditionnelle imbriquée) reste la même parce qu'il s'agit des mêmes cas (trois cas, exactement le même problème). A partir de l'analyse donnée dans le cadre de l'exercice précédent, il suffit de reprendre la partie concernant es conditions à vérifier :
  1. Le produit de a et b est positif si les deux nombres sont du même signe, c'est à dire, le produit est positif si et seulement si a et positif et b est positif ou bien a est négatif et b est négatif.
  2. Le produit de a et b est négatif si les deux nombres sont de signes différents, c''est à dire, le produit est négatif si a est positif et b est négatif ou bien a est négatif et b est positif.
  3. Le produit de a et b est nul s'il est ni positif, ni négatif.
Comme vous voyez, les conditions sont un peu plus complexes. En effet, cet exercice est lié aux expressions logiques (booléennes). Nous pouvons reprendre les définitions données telles qu'elle le sont; il suffit d'utiliser les bons symboles pour les opérations booléennes.
Ainsi, le programme sera :

En Pascal :

Program PositifNegatifNul;
Var
 a, b : Integer;
Begin
 WriteLn('Donnez deux nombres :');
 ReadLn(a);
 ReadLn(b);
 If (((a > 0) And (b > 0))  Or ((a < 0) And (b < 0))) Then 
  WriteLn('Le produit est Positif')
 Else
  if (((a < 0) And (b > 0))  Or ((a > 0) And (b < 0))) Then
   WriteLn('Le produit est Negatif')
  Else
   WriteLn('Le produit est Nul');
End.

En Java :


import java.util.Scanner;

public class Exemple {
 public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);
  System.out.println("Donnez deux nombres :");
  int a = scanner.nextInt();
  int b = scanner.nextInt();
  if(a < 0 && b < 0 || a > 0 && b > 0)
   System.out.println("Le produit est Positif"); 
  else
   if (a < 0 && b > 0 || a > 0 && b < 0)
    System.out.println("Le produit est Negatif"); 
   else
    System.out.println("Le produit est Nul"); 
 }
}



Positif, Négatif, Nul : la structure conditionnelle un peu plus compliquée

Énoncé

Ecrire un algorithme qui lit un nombre entier et nous informe s'il est positif, négatif ou bien nul.

Cet exercice est parmi les premiers exercices que les enseignants donnent comme pratique à la structure conditionnelle Si...Sinon. Cela peut être déduit facilement parce que le programme (ou l'algorithme) va classifier le nombre; il va le mettre avec les nombres positifs, avec les nombres négatifs ou bien avec les nombres nuls. Pour pouvoir le classifier, il doit tester des conditions. Et lorsqu'on dit "test", on dit "conditionnel" (Si...Sinon).

Contrairement au problème de Pair/Impair, nus avons deux grandes différences :
  1. Il n'y a aucune confusion lors du choix de la définition pour les notions "nombre positif", "nombre négatif" et "nombre nul".
  2. Nous avons trois possibilités pas seulement deux, sachant qu'une structure "Si...Sinon" permet de choisir entre deux possibilités seulement.

Ainsi, il suffit de détailler ces deux points pour atteindre l'objectif de cet exercice sachant que l'étudiant à bien compris le cas le plus simple où nous avons deux possibilités seulement (Si...Sinon simple).

Premièrement les conditions à vérifier :
Pour qu'un nombre n soit dit "positif", il doit satisfaire la condition n > 0.
Pour qu'un nombre n soit dit "négatif", il doit satisfaire la condition n < 0.
Un nombre est nul s'il est ni positif, ni négatif.

Pour ce dernier point, il est préférable de définir l'une des conditions en fonction des autres, plus précisément, la négation des autres. Cela facilite l'utilisation de Si...Sinon qui exécute un bloc si la condition est vraie et l'autre bloc dans le cas contraire (si la négation de la condition est correcte).

Deuxièmement, la structure conditionnelle doit être définie. Si nous avons plus de deux cas alors il est certain que nous allons utiliser plusieurs Si...Sinon ou bien des Si...Sinon imbriqués (l'objectif pédagogique de cet exercice).

Un Si...Sinon imbriqué, c'est à dire un Si...Sinon à l'intérieur d'un autre Si...Sinon, permet de créer plus de deux branches que nous pouvons obtenir par un simple Si...Sinon. Cette structure est utilisée si nos condition ne présentent pas de chevauchement : il est impossible d'avoir deux conditions vérifiées au même temps. Dans le cas de notre exercice, ce principe est respecté parce qu'un nombre ne peut pas être, à titre d'exemple, positif et nul au même temps.

Regroupons tout cela dans le programme suivant :

En Pascal :

Program PositifNegatifNul;
Var
 n : Integer;
Begin
 WriteLn('Donnez le nombre à tester :');
 ReadLn(n);
 If (n > 0) Then 
  WriteLn('Positif') {Positif s'il est supérieur à 0}
 Else
  if (n < 0) Then
   WriteLn('Negatif') {Négatif s'il est inférieur à 0}
  Else
   WriteLn('Nul'); {Nul s'il est ni positif, ni négatif}
End.

En Java :

import java.util.Scanner;

public class Exemple {
 public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);
  System.out.println("Donnez le nombre à tester :");
  int n = scanner.nextInt();
  if(n > 0)
   System.out.println("Positif"); // Positif s'il est supérieur à 0
  else
   if (n < 0)
    System.out.println("Negatif"); // Négatif s'il est infénrieur à 0
   else
    System.out.println("Nul"); // Nul s'il est ni positif, ni négatif
 }
}



Une mauvaise écriture

Il est aussi possible d'écrire le programme autrement. Je peux voir les trois conditions comme des conditions indépendante et donner à chacune d'elle une structure Si...FSi simple. Cela donnera un programme te que le suivant :

En Pascal :

Program PositifNegatifNul;
Var
 n : Integer;
Begin
 WriteLn('Donnez le nombre à tester :');
 ReadLn(n);
 If (n > 0) Then 
  WriteLn('Positif');

 If (n < 0) Then 
  WriteLn('Négatif');

 If (n = 0) Then 
  WriteLn('Nul'); 
End.

En Java :


import java.util.Scanner;

public class Exemple {
 public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);
  System.out.println("Donnez le nombre à tester :");
  int n = scanner.nextInt();
  if(n ... 0)
   System.out.println("Positif"); 
  
  if(n ... 0)
   System.out.println("Négatif"); 
  
  if(n == 0)
   System.out.println("Nul"); 
 }
}

Malgré que ce code fonctionne parfaitement, mais, il est considéré dans le contexte de cet exercice comme faux. N'oublions pas que l'objectif de cet exercice de pratiquer les Si...Sinon; chose qui n'est pas atteinte dans ce dernier code. En effet, quelque soit la valeur de n, le programme va le tester pour les trois cas. C'est à dire, si le nombre n est positif, le programme affiche le message "Positif", mais, il fera comme même les deux autres testes (négatif et nul).

dimanche 12 novembre 2017

Prendre la bonne définition du problème

Énoncé

Écrire un programme qui lit un entier et vous dit par la suite est ce que cet entier est pair ou bien impair.

Cet exercice est donné, généralement, comme pratique sur la structure conditionnelle. Le programme doit "tester si" l'entier saisi est pair ou bien impair. La présence de Si, tester, ou de "est ce que" est un indicateur sur la structure conditionnelle. Nous avons deux possibilités seulement, alors, la forme la plus simple d'un conditionnel, c'est à dire, "Si...Alors...Sinon..." peut suffire.
Mais, le problème que cet exercice pose aux nouveaux étudiants ne réside pas dans son objectif ou bien dans la forme de sa solution. Le problème est l'écriture de la condition; les mathématiciens tendent souvent à choisir la mauvaise définition.

Mauvaise solution

Un nombre entier n est dit pair si il existe un autre nombre entier k tel que :
n = 2k
Il est dit impair dans le cas contraire.

En essayant de résoudre le problème posé en exploitant cette définition, la chance de tomber dans l'erreur augmente. En effet, cette définition invoque deux entiers; n et k. Ainsi, il est logique de déclarer les deux entiers. Par la suite, nous devons vérifier la condition donnée, ce qui donne à peu près :

En Pascal :

Program PairImpair;
Var
 n, k : Integer;
Begin
 WriteLn('Donnez le nombre à vérifier :');
 ReadLn(n);
 If(n = 2 * k)Then 
  WriteLn('Pair')
 Else
  WriteLn('Impair');
End.

En Java :

import java.util.Scanner;

public class Exemple {

 public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);
  int n, k;

  System.out.println("Donnez le nombre à vérifier :");
  n = scanner.nextInt();

  if(n == 2 * k)
   System.out.println("Pair");
  else
   System.out.println("Impair");
 
 }
}

J'ai lu cette solution des dizaines de fois. Elle semble bien réfléchie, néanmoins, elle est fausse. En effet, l'expression booléenne :
        x = 2 * k
N'est pas équivalente à l'énoncé :
il existe un k tel que x = 2 * k; 
La première compare la valeur actuelle de "x" au double de la valeur actuelle de "k". Comme vous n'avez donné aucune valeur à "k", la comparaison ne donner pas la bonne réponse. En Java, ce code ne peut même pas être compilé; le compilateur se rend compte que vous n'avez pas donné de valeur à la variable "k". En Pascal, il vous donne juste un avertissement.



Une traduction plus fiable de l'énnoncé : s'il existe un k tel que x = 2 * k sera probablement :

En Pascal :

Program PairImpair;
Var
 n, k : Integer;
 trouve : Boolean;
Begin
 WriteLn('Donnez le nombre à vérifier :');
 ReadLn(n);
 trouve := false;
 k := 0;
 While ((k <= n) and not(trouve)) Do
 Begin
  If(n = 2 * k)Then 
   trouve := true
  Else
   k := k + 1;
 End;
 If(trouve)Then
  WriteLn('Pair')
 Else
  WriteLn('Impair');
End.

En Java :

import java.util.Scanner;

public class Exemple {

 public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);
  int n, k;
  boolean trouve = false;
  System.out.println("Donnez le nombre à vérifier :");
  n = scanner.nextInt();
  k = 0;
  while(k <= n && !trouve) {
   if(n == 2 * k)
    trouve = true;
   else
    k++;
  }
  if(trouve)
   System.out.println("Pair");
  else
   System.out.println("Impair");
 }
}

Effectivement, si vous voulez que le programme vérifie est ce qu'il existe une valeur de k ou non, alors il faut le faire explicitement. Dans ce code, il faut ajouter toute une boucle pour vérifier les valeurs de 0 à n pour voir s'il existe un entier k qui vérifie l'égalité n == 2 * k. Le résultat de la vérification est mis dans une variable booléenne.

Meilleure solution

C'était un long code pour un problème assez simple. Peut être il fallait prendre la définition la plus simple. Par exemple, un nombre pair est un nombre divisible par 2; autrement dit, le reste de sa division sur 2 est nul. En prenant cette deuxième définition, il nous suffit de :
  1. Calculer le reste de division,
  2. Le comparer avec 0 : s'il l'égale alors le nombre est pair, sinon, il est impair.

En Pascal :

Program PairEtImpair;
Var
 n : Integer;
Begin
 WriteLn('Donnez le nombre à tester :');
 ReadLn(n);
 If (n mod 2 = 0) Then
  WriteLn('Pair')
 Else
  WriteLn('Impair');
End.

En Java :

import java.util.Scanner;

public class Exemple {

 public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);
  System.out.println("Donnez le nombre à tester :");
  int n = scanner.nextInt();
  if(n % 2 == 0)
   System.out.println("Pair");
  else
   System.out.println("Impair");
 }
}

On peut aller un peu plus loin et écrire en Java :


import java.util.Scanner;

public class Exemple {

 public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);
  System.out.println("Donnez le nombre à tester :");
  System.out.println(scanner.nextInt() % 2 == 0 ? "Pair" : "Impair");
 }
}

A la fin 

Dans cet article, je voulais mettre le doigt sur un fait courant pendant la programmation; des fois le problème réside dans l'angle avec lequel nous voyons le problème. Il n'y a pas une méthode que vous garantit que vous avez choisi la bonne approche, la bonne méthode ou la bonne définition. Seule l'expérience vous donnera la réponse. Néanmoins, si vous arrivez à traduire parfaitement la modélisation mathématique en un algorithme, il sera correct même s'il n'est pas le plus optimal.

samedi 11 novembre 2017

Entre Donnée et Information, des WriteLn peuvent suffire

Ennoncé :

Ecrire un algorithme (programme) qui lit le nom et le prénom et les affiche.

Un exercice très simple pour expliquer l'utilité d'afficher des message additionnels pour améliorer l'interactivité des programmes.

Une première solution correcte et suffisante sera :

En Pascal :

Program LireEtAfficher;
Var
    nom, prenom : String[100];
Begin
    ReadLn(nom);
    ReadLn(prenom);
    WriteLn(nom);
    WriteLn(prenom);
End.

En Java :

import java.util.Scanner;

public class Exemple {
   public static void main(String[] args) {
      String nom, prenom;
      Scanner entree = new Scanner(System.in);
      nom = entree.nextLine();
      prenom = entree.nextLine();
      System.out.println(nom);
      System.out.println(prenom);
   }
}

Après la compilation et l'exécution de l'un de ces deux codes (identiques!), nous obtenons :



Le programme réalise parfaitement le travail demandé, néanmoins, si un utilisateur revoit l'exécution après un certain moment, nous pouvons douter qu'il comprendra la signification de l'exécution. Même s'il relance l'exécution, nous pouvons douter qu'il saura quoi saisir. En effet, il aura un programme qui l'attend pour saisir quelque chose sans aucune indication.

Pour cela, un rtel exercice est parmi les premiers exercices à présenter aux étudiants. La solution réside dans l'affichage de quelques messages supplémentaires pour clarifier la situation à l'utilisateur. Ces messages n'auront aucun impact sur le déroulement du programme et ne vont rien changer aux traitements qu'il effectue. Mais, ils serviront à rendre le programme plus interactif. Ainsi le code devient :

En Pascal :

Program LireEtAfficher;
Var
    nom, prenom : String[100];
Begin
    WrileLn('Donnez votre Nom : ');
    ReadLn(nom);
    WrileLn('Donnez votre Prénom : ');
    ReadLn(prenom);
    WriteLn('************************');
    WriteLn('Nom : ', nom);
    WriteLn('Prénom : ', prenom);
    WriteLn('************************');
End.

En Java :


import java.util.Scanner;

public class Exemple {
   public static void main(String[] args) {
      String nom, prenom;
      Scanner entree = new Scanner(System.in);
      System.out.println("Donnez votre nom : ");
      nom = entree.nextLine();
      System.out.println("Donnez votre prénom : ");
      prenom = entree.nextLine();
      System.out.println("*********************");
      System.out.println("Nom : " + nom);
      System.out.println("Prénom : " + prenom);
      System.out.println("*********************");
   }
}

La nouvelle exécution sera :


Une analyse plus profonde peut être donnée. Ce que nous faisons en ajoutant des messages supplémentaire est de donner un "sens" auc données du programme; ainsi, on parle d'information. La différence entre ces deux notions est cruciale :
  • L'ordinateur ignore la signification des données qu'il traite. Pour l'ordinateur, il s'agit de deux chaîne de caractères à lire et ensuite à afficher sans aucune signification.
  • L'humain ne peut comprendre une donnée que si elle a un "sens" pour lui, si elle a un contexte. Ainsi, "5" comme donnée n'a aucun sens et on ne peut rien tirer d'elle, mais, "5°C" est clairement une information qui a du sens; une température. 
Entre donnée et information, il fallait ajouter la partie "°C"; autrement dit, deux caractères.

vendredi 10 novembre 2017

Entrée/Sorties, un mécanisme de base pour tous les systèmes

Chaque algorithme (ou programme) est un système. L'ordinateur est, comme toute autre machine, un système. Par cela, nous voulons dire qu'il prend des éléments en entrée et nous donne des éléments en sortie; ces derniers sont obtenus à partir des premiers qui subissent un traitement.


Les traitements appliqués dépendent directement des objectifs du système. Ainsi, la majorité des algorithmes (ou programmes) attend quelque chose en entrée, applique les différents traitements et donne quelque chose en sortie. Ces notions feront partie du quotidien de développement.

L'exemple le plus simple est un programme qui calcul la somme de deux entiers. Essayons de l'écrire sans Entrées/Sorties. Le programme sera de la forme :

En Pascal :

Program Somme;
Var
    a, b, c : Integer;
Begin
    a := 10;
    b := 20;
    c := a + b;
End.

En Java :

public class Exemple {
   public static void main(String[] args) {
      int a, b, c;
      a = 10;
      b = 20;
      c = a + b;
   }
}

Les deux codes sont corrects. Mais, après compilation et exécution, on n'obtient rien. Les deux programmes définissent les variables, donnent des valeurs et calculent la somme, néanmoins, sans aucune interaction avec l'utilisateur.


On se demande sur l'utilité d'un tel programme.
Pour améliorer le programme, nous allons lui demander d'afficher le résultat, c'est à dire, de nous donner une sortie pour voir qu'est ce qu'il a fait. Le programme deviendra :

En Pascal :

Program Somme;
Var
    a, b, c : Integer;
Begin
    a := 10;
    b := 20;
    c := a + b;
    WriteLn(c);
End.

En Java :

public class Exemple {
   public static void main(String[] args) {
      int a, b, c;
      a = 10;
      b = 20;
      c = a + b;
      System.out.println(c);
   }
}

Maintenant, l'exécution du programme ne passe pas inaperçue. Nous avons quelque chose qui s'affiche; c'est la sortie du programme. Chaque langage possède sa propre méthode pour donner la sortie. Dans nos deux cas, on "imprime" quelques chose sur l'écran, cette surface qui est le périphérique de sortie principal.



Maintenant, le programme nous dit "30". Nous pouvons dire qu'il fonctionne, contrairement à la première fois où on n'avez aucune idée.
Une deuxième exécution du programme ? Bien, il nous donne aussi 30.
Une troisième? Il nous donne une autre 30. Mais...nous voulons autre chose, nous avons appris que la somme de 10 et 20 est belle et bien 30; et pour les autres nombres ?
Dans son état actuel, le programme nous donnera toujours le même résultat. Il nous faut un moyen pour lui parler, pour lui donner des nouvelles valeurs pour le calcul. Il faut lui permettre de récupérer des Entrées.

En Pascal :

Program Somme;
Var
    a, b, c : Integer;
Begin
    ReadLn(a);
    ReadLn(b);
    c := a + b;
    WriteLn(c);
End.

En Java :


import java.util.Scanner;

public class Exemple {
   public static void main(String[] args) {
      int a, b, c;
      Scanner entree = new Scanner(System.in);
      a = entree.nextInt();
      b = entree.nextInt();
      c = a + b;
      System.out.println(c);
   }
}

Essayons ce dernier code :


Rien ne se passe ! Le programme ne rend même pas la main au système ! On dirai que le programme est bloqué !
Vous avez raison; il est bloqué. En réalité, il vous attend ! Vous l'avez ordonné de récupérer l'entrée, de lire à partir du clavier, alors, il vous attend. En lui donnant les valeurs 25  et 60, l'une après l'autre, on obtient :


Si on exécute le programme une deuxième fois, nous aurons la possibilité de donner deux nouvelles valeurs en entrée et d'obtenir leur somme en sortie. A ce stade, notre programme est interactif; il nous entend et il nous parle.