GENÈSE D'UN DICTIONNAIRE

Construction d'un lexique interactif avec Lazarus


précédentsommairesuivant

Liens multiples

Introduction

Les chapitres précédents ont donné accès à une liste considérable de mots français et permis de construire avec Lazarus un outil permettant :

  • de parcourir la liste à volonté ;
  • d'établir avec chaque mot un lien avec une information quelconque : texte, image, son, fichier.

Mais ce potentiel reste modeste. Il est limité en particulier par l'unicité du lien autorisé par les propriétés génériques Value ou Object du composant Liste.

Dans le présent chapitre, nous allons voir comment établir des liens multiples.

Environnement

Chapitre 6…

Créons un répertoire Lex6 et recopions dans ce nouveau répertoire tous les fichiers du répertoire Lex5 utilisé précédemment. Pour éviter toute difficulté ultérieure, suivez la check-list :

  • ouvrir pLex5.lpi dans Lex6 avec Lazarus ;
  • enregistrer uLex5.pas sous le nom uLex6.pas ;
  • accepter la suppression des références à uLex5.pas ;
  • enregistrer pLex5.pas sous le nom pLex6.pas ;
  • renommer la fenêtre Form1 : Lex5 devient Lex6 ;
  • dans le répertoire Lex6 supprimer les anciens fichiers contenant la mention Lex5.

Nous retrouvons le projet dans l'état où nous l'avions laissé, et les modifications que nous allons effectuer n'affecteront pas l'étape précédente consultable dans le répertoire Lex5.

Architecture

Chaque mot de la liste principale est affecté d'un numéro implicite qui correspond à sa place dans la liste. Au niveau du code, rappelons que connaissant le numéro, la fonction liste[numéro] donne accès à la chaîne de caractères, et inversement, la fonction liste.IndexOf(mot) explicite le numéro du mot ou retourne -1 si le mot n'existe pas.

Nous allons exploiter ces fonctions pour accéder à une table auxiliaire. Par exemple, le mot « a » possède le numéro 0 (zéro) en tant que premier de la liste.

Tableaux de liens

Nous créons un tableau de nombres entiers, de longueur variable, dont le premier élément, qui sera son identifiant, sera ce numéro. Si on décide, par exemple, de stocker les quatre valeurs 5555, 101, 100 et 6006 en liaison avec le mot « a », notre tableau aura une capacité (longueur) de cinq cases se présentant ainsi :

Numéro
identifiant
lien1 lien2 lien3 lien4
0 5555 101 100 6006

Le premier entier, nous savons qu'il correspond au premier élément de la liste principale, donc au mot « a ».

Mais les autres, que représentent-ils ? C'est à nous de décider. On peut imaginer une structure dans laquelle le second entier est un index qui pointe dans une liste de textes, le troisième dans une liste de pdf, les trois suivants à des images, etc.

Mais nous arrivons vite à une usine à gaz, ce qui est passionnant assurément, mais d'un usage d'autant plus contestable que des quantités d'applications ont déjà été développées sous forme de bases de données adaptées à toutes sortes de besoins.

Pour rester simple, nous prendrons une option radicale : chaque entier du tableau représentera la position d'un mot de la liste principale. Nous obtenons alors un système qui autorise à la fois :

  1. les liens multiples ;
  2. la réflexivité.

Nous avons opté pour un identifiant numérique. Pourquoi ne pas avoir conservé le mot comme identifiant ? Essentiellement pour économiser de l'espace de stockage : un entier occupe moins de place qu'un mot complet. Mais gardons en tête cette option : nous aurons l'occasion d'y revenir.

Nettoyage de l'interface et du code

Avant de construire la nouvelle architecture, nous allons élaguer sérieusement notre projet, tout en conservant l'onglet Info pour un usage ultérieur :

  1. dans l'onglet Info de l'interface, on supprime les deux boutons ;
  2. dans l'éditeur de source, on supprime les deux procédures Button3Click et Button4Click correspondantes ;
  3. dans la procédure Balayage, on supprime les quatre dernières lignes ;
  4. dans l'onglet Balayage, on supprime les deux Memos ;
  5. dans le code, on supprime les procédures MAJObj, MAJInfo, regObj, la fonction chercheValue ;
  6. les référencements dans la classe Tform, au-dessus du mot-clé implementation, sont nettoyés.

Un essai d'exécution pour vérification.

Quelques scories subsistent… Nous y reviendrons.

Écriture de liens

Chaque mot de la liste principale est susceptible de posséder son propre tableau de liens.

Appelons Liens le tableau de tableaux d'entiers qui, avec son identifiant, reçoit les index des liens. Combien de tableaux d'entiers faut-il créer ? Pour fixer les idées, disons que 10 % des mots recevront des liens, soit en gros 34 000 tableaux. Cette approche superficielle montre qu'en fait il est illusoire de se fixer une limite, et la solution est d'adopter un tableau de longueur variable.

Méthode

La désignation Liens[0] correspond au premier tableau(16).

La désignation Liens[0, 0] correspond au premier entier du premier tableau(17).

Les tableaux à taille variable ont un inconvénient : avant d'affecter une valeur à un tableau, il est nécessaire de donner au tableau la taille requise. Cette taille est nulle à l'origine.

Donc pour affecter la valeur 0 à la première case du premier tableau, on écrira successivement :

 
Sélectionnez

SetLength(Liens, 1) ;
    //le tableau de tableaux peut recevoir son premier tableau
SetLength(Liens[0], 1) ;
    //le premier tableau a une longueur fixée à 1
Liens[0, 0]:= 0 ;
    //la première case du premier tableau reçoit la valeur numérique 0

La procédure est un peu lourde mais autorise une grande souplesse dans l'édition des liens.

Premier essai

Dans l'interface graphique, nous allons ajouter un onglet appelé Édition. Pour cela, clic droit sur la ligne grisée, à droite de l'onglet Info. Dans le menu contextuel, choisissez Ajouter une page. Dans l'Inspecteur d'objets, onglet Propriétés, remplacez TabSheet3 par le mot « Édition » à la ligne Caption.

Image non disponible

Dans ce nouvel onglet, nous plaçons un bouton et un label (propriété Font/Size portée à 14).

Double-clic sur le bouton, et dans la procédure ainsi créée dans l'Éditeur de source, nous plaçons le code suivant :

 
Sélectionnez

procedure TForm1.Button3Click(Sender: TObject);
begin
  SetLength(Liens, 1);
  SetLength(Liens[0], 1);
  Liens[0, 0] := 0;
  Label4.Caption := IntToStr(Liens[0, 0])+ ' -> ' + listeMots[Liens[0, 0]];
end;

Les trois premières instructions ont été commentées plus haut. La dernière a une ambition modeste : elle se contente d'afficher le numéro stocké dans le nouveau tableau, et le mot correspondant.

La variable globale Liens doit être déclarée avant implementation :

 
Sélectionnez

var
  Form1: TForm1; 
  listeMots, listeInfo : TStringList;
  iMot, nMots : integer;
  AffListe : TListBox;
  Liens : Array of Array of integer;
implementation
{ TForm1 }    

Clic sur le petit triangle vert pour notre premier essai…

Clic sur le nouveau bouton…

Voici le résultat pour l'indice 0 ; essayez avec différentes valeurs : 100, 1000, 100000…

Image non disponible

Nous n'avons pas construit de lien, mais seulement initié le tableau susceptible d'en recevoir !

Création d'un lien

Sous le label de l'onglet Édition, nous ajoutons une zone de saisie sous forme d'un TEdit.

Nous ajoutons à droite un TListBox qui recevra les mots éventuellement liés.

Nous remplaçons le titre (caption) du bouton par « Lier ».

Image non disponible

La démarche suivante :

  1. recopier dans le Label4 le mot-titre affiché dans l'onglet Balayage ; son index est iMot ;
  2. dans l'onglet Édition, saisie d'un mot Mot1 dans le TEdit, son index est iLien ;
  3. cliquer sur le bouton Lier pour créer le lien ;
  4. si Mot1 existe, le lien est créé, il est affiché dans la ListBox et la zone d'édition est nettoyée ; sinon un message d'erreur invite à saisir un autre mot.

La création du lien passe par plusieurs étapes :

  1. chercher le tableau de liens correspondant à chacun des mots à lier ;
  2. s'il n'existe pas, créer le tableau et inscrire le numéro du mot à lier dans la première case ;
  3. ensuite, ajouter le numéro du mot à lier dans une nouvelle case.

Voyons cela pas à pas.

Recherche du tableau de liens

Nous avons deux mots, connus par leurs index iMot et iLien. Pour savoir si un mot possède son propre tableau de liens, nous créons la fonction chercheTab qui renvoie la position du tableau(18). Rappelons que le tableau de liens commence (à la case 0) par un entier qui est précisément l'index du mot. Si le renvoi est négatif, c'est que le mot ne possède pas encore son tableau.

 
Sélectionnez

function TForm1.chercheTab(iMot: integer): integer;
var i : integer;
begin
 chercheTab := -1;
 i := 0;
 while (i<Length(Liens)) and (Liens[i, 0]<>iMot) do inc(i);
 if i<Length(Liens) then chercheTab := i;
end;

Création du lien

Pour lier le mot titre, d'index iMot, à un autre mot d'index iLien, nous créons la procédure Lier qui comprend deux parties :

  1. si iMot ne possède pas son tableau de liens (chercheTab(iMot) négatif), il faut créer ce tableau à la suite des autres. Par exemple, si aucun tableau n'existe (Length(Liens)=0), on augmente la taille de Liens d'une unité ; le tableau secondaire aura une taille égale à 1 et la première case du tableau secondaire sera remplie avec la valeur iMot ;
  2. la taille du tableau secondaire est augmentée d'une unité et la nouvelle case reçoit la valeur iLien.

Le code peut s'écrire ainsi :

 
Sélectionnez

procedure TForm1.Lier(iMot, iLien: integer);
var k : integer;
begin
  k := chercheTab(iMot);
  if k < 0 then
  begin
     SetLength(Liens, Length(Liens)+1); //extension du tableau principal
     k := Length(Liens)-1;  //indice du nouveau tableau
     SetLength(Liens[k], 1);
     Liens[k, 0] := iMot; //identifiant
  end;
  SetLength(Liens[k], Length(Liens[k])+1);  //extension du tableau secondaire
  Liens[k, Length(Liens[k])-1] := iLien;  // lien
end;

Comme le lien est réciproque, la procédure sera répétée en inversant les deux paramètres.

Exécution

Double-clic sur le bouton Lier pour retrouver la procédure Button3 qui sera modifiée ainsi :

 
Sélectionnez

procedure TForm1.Button3Click(Sender: TObject);
var iLien, k : integer;
begin
   iLien := listeMots.IndexOf(UTF8ToAnsi(Edit3.Caption));
   if iLien<0 then
      ShowMessage('Ce mot n''existe pas, recommencez')
   else
   begin
     Lier(iMot, iLien);
     Lier(iLien, iMot);
     AffLiens;
   end;
   Edit3.Clear;
end;

Le mot titre est issu de la liste principale, puisqu'il est obtenu à partir le l'onglet Balayage. Par contre, le mot entré dans la zone d'édition n'existe peut-être pas : un signal d'erreur invite à recommencer la saisie.

Ensuite, la construction du lien se fait dans un sens, puis dans l'autre.

La zone de saisie est effacée, prête à recevoir un nouveau mot à lier.

Mais avant, le ou les liens sont affichés dans le composant ListBox par les soins de la procédure AffLiens :

 
Sélectionnez

procedure TForm1.AffLiens;
var i, k : integer;
begin
   ListBox1.Clear;
   k := chercheTab(iMot);
   if k>=0 then
     for i :=1 to Length(Liens[k]) -1 do
       ListBox1.Items.Add(AnsiToUTF8(listeMots[Liens[k, i]])); 
end;

Enfin, nous ajoutons dans la procédure MAJBalayage des instructions nécessaires pour afficher le mot titre dans l'onglet Édition, nettoyer la zone de saisie et afficher les liens éventuels :

 
Sélectionnez

procedure TForm1.MAJBalayage;
var i : integer;
begin
   Label2.Caption:=AnsiToUTF8(listeMots[iMot]);
   Label3.Caption:= Label2.Caption;
   Label4.Caption:= Label2.Caption;
   Edit3.Clear;
   TrackBar1.Position:= Round(iMot*1000/nMots);
   AffListe.Clear;
   for i := 0 to 10 do
       AffListe.Items.Add(AnsiToUTF8(listeMots[(iMot-delta + i
                         + nMots) mod nMots]));
   AffListe.Selected[delta] := True;
   AffLiens ;
end;

Un clic sur le petit triangle vert pour nos essais.

Dans l'onglet Balayage, faites défiler les mots pour afficher le mot « couleur ».

Dans l'onglet Édition, écrivez le mot « vert »et cliquez sur le bouton Lier. Immédiatement, le mot « couleur » est lié au mot « vert », qui apparaît maintenant dans la zone des liens à droite.

Recommencez avec « blanc », « rouge »… Les liens s'ajoutent sans problème…

Image non disponible

Le mot titre est « couleur ». Il possède trois liens qui sont affichés à droite.

Réciprocité

Le mot « couleur » est lié au mot « vert ». Mais comment vérifier que la réciproque est vraie ?

Il suffirait de cliquer sur le mot « vert » pour le faire basculer en titre, et la zone des liens présenterait alors les liens existants.

Pour coder cet événement, revenez en mode édition, cliquez sur le composant ListBox1, et dans l'onglet Événements, ligne OnClick, cliquez sur les trois points. La procédure s'écrit ainsi :

 
Sélectionnez

procedure TForm1.ListBox1Click(Sender: TObject);
 if ListBox1.ItemIndex >= 0 then
 begin
   iMot := Liens[chercheTab(iMot), ListBox1.ItemIndex+1];
   Label4.Caption := AnsiToUTF8(listeMots[iMot]);
   AffLiens;
 end;
end; 

La première ligne vérifie la présence d'un lien (index supérieur ou égal à zéro).

Relancez l'exécution. Onglet Édition, le mot titre est « a ». Créez un lien avec « avoir », avec « voyelle », avec « lettre »… Cliquez sur le mot « avoir », créez un lien avec « bien », avec « verbe »… Cliquez sur le mot « bien », qui passe en titre ; liez avec « mal », etc. C'est simple et… magique !

Enregistrement des liens

Inutile d'ajouter davantage de liens puisque la fonction d'enregistrement n'existe pas encore.

Nous allons créer un fichier de nombres entiers qui recevra un par un les tableaux secondaires.

Dans l'unité uDisque, nous écrivons avant implementation, sous la ligne procedure LireFichier, l'instruction procedure regLiens ;

Après appui sur les touches Ctrl+Maj+C, nous complétons le corps de la procédure par les instructions suivantes :

 
Sélectionnez

procedure regLiens;
var i, j, k : integer;
    fLiens : file of integer;
 
begin
  AssignFile(fLiens, 'fichLiens.bin');
  ReWrite(fLiens);
  for i := 0 to Length(Liens)-1 do
  begin
    j := Length(Liens[i]);
    Write(fLiens, j);
    for k:=0 to j-1 do
      Write(fLiens, Liens[i, k]);
  end;
  CloseFile(fLiens);
end;    

Le premier nombre écrit dans le fichier est la taille du premier tableau secondaire : Write(fLiens, j). Ensuite sont écrits tous les nombres situés dans le tableau depuis la case 0 (identifiant du tableau) jusqu'à la dernière case. L'opération est répétée autant de fois qu'il y a de tableaux secondaires.

L'unité utilise la variable Liens créée par l'unité uLex6 ; pour que le compilateur s'y retrouve, dans l'unité uDisque, sous le mot-clé implementation, nous ajoutons l'instruction

uses uLex6 ;

Pour automatiser la sauvegarde de nos liens, nous ajoutons l'instruction regLiens dans la procédure Button1Click qui provoque la fin de l'application :

 
Sélectionnez

procedure TForm1.Button1Click(Sender: TObject);
begin
 regLiens;
 listeMots.Free;
 Application.Terminate;
end;

Lecture des liens

Pour récupérer l'ensemble de nos liens au démarrage du programme, nous ajoutons la ligne lireLiens dans la procédure FormCreate.

Dans l'unité uDisque, nous ajoutons la ligne procedure lireLiens ; avant implementation, et après appui sur les touches Ctrl+Maj+C, nous complétons le code comme suit :

 
Sélectionnez

procedure lireLiens;
var
  j, m : integer;
  fLiens : file of integer;
begin
  nLiens := 0;   //nombre de mots liés
  AssignFile(fLiens, 'fichLiens.bin');
  {$I-}
  Reset(fLiens);
  {$I+}
  if IOResult<>0 then
    ShowMessage('Fichier liens inexistant')
  else
  while not EOF(fLiens) do
  begin
    SetLength(Liens, nLiens+1);      //taille du tableau principal
    Read(fLiens, m);
    SetLength(Liens[nLiens], m);     //taille du tableau secondaire
    for j := 0 to m-1 do
      Read(fLiens, Liens[nLiens, j]); //remplissage de tableau secondaire
    inc(nLiens);                      //nombre de mots liés
  end;
  CloseFile(fLiens);
end;  

Cette procédure utilise une fenêtre pour signaler l'absence du fichier : il faut déclarer l'unité Dialogs après SysUtils.

Le premier nombre lu, m, est la taille du premier tableau secondaire. Les lectures suivantes permettront de remplir toutes les cases de ce tableau. Puis on passe au tableau suivant avec inc(nLiens) jusqu'à la fin du fichier (détectée par EOF).

Nous avons ici introduit la variable nLiens qui totalise le nombre de mots liés. Mais il faudra la déclarer dans l'unité uLex6, à la suite des autres variables globales. L'affichage du nombre de liens sera intégré dans le titre de la fenêtre (propriété Caption) et actualisé lors de la création de liens.

Dans la procédure MAJBalayage, nous ajoutons l'instruction

Caption := IntToStr(nMots)+ ' mots dont '+IntToStr(nLiens)+' liés';

Image non disponible

Pour essayer la nouvelle configuration, clic sur le petit triangle vert.

Balayage jusqu'au mot « couleur » ; dans l'onglet Édition, liez avec « vert », « blanc », « rouge »…

Pour quitter, passez par le bouton Arrêt (onglet Page1), de façon à provoquer l'enregistrement. Au redémarrage, vous retrouverez tous vos liens.

Filtre

La navigation reste laborieuse, et un filtrage permettrait de passer directement d'un mot lié au suivant. Pour cela, il suffit de reprendre la définition du filtrage en introduisant la valeur retournée par la fonction chercheTab : si elle est négative, la recherche continue.

 
Sélectionnez

procedure TForm1.UpDown2Click(Sender: TObject; Button: TUDBtnType);
begin
   if CheckBox1.Checked then
      repeat
        inc(iMot);
      until (iMot=nMots) or (chercheTab(iMot)>=0)
   else
      if Button=btNext then Inc(iMot, UpDown2.Increment)
                         else Dec(iMot, UpDown2.Increment);
   iMot := (iMot + nMots) mod  nMots;
   MAJBalayage;
end; 

Relancez l'exécution ; onglet Balayage, cliquez sur le filtre puis sur les flèches : tous les mots liés défilent instantanément. Un contrôle sur l'onglet Édition permet de vérifier que les liens sont correctement détectés et affichés.

Conclusion

Ouf ! Il a fallu mettre un peu les mains dans le cambouis des indices multiples, mais nous disposons maintenant des moyens nécessaires pour créer et sauvegarder facilement tous les liens que l'on souhaite.

Dans le prochain chapitre, nous verrons comment effectuer le tri des tableaux, la modification ou la suppression de liens, et nous aborderons le concept de mots « proches » du mot titre, fondamental dans la construction des mots croisés.

Mais la création de liens restera limitée aux mots de la liste principale : ce n'est qu'ensuite que nous envisagerons sa modification, problème que nous avons soigneusement éludé jusqu'à présent.

An : un élément du fardeau du vieillard.
Tristan Bernard.

Pour l'instant, les unités uLex6 et uDisque se présentent ainsi :

 
Sélectionnez

unit uLex6;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls,
  Graphics, Dialogs, StdCtrls, ComCtrls, uDisque;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    CheckBox1: TCheckBox;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Label3: TLabel;
    Label4: TLabel;
    ListBox1: TListBox;
    Memo2: TMemo;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    RadioButton3: TRadioButton;
    RadioButton4: TRadioButton;
    TabSheet2: TTabSheet;
    TabSheet3: TTabSheet;
    Zoom: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    AffListe: TListBox;
    Memo1: TMemo;
    PageControl1: TPageControl;
    Page1: TTabSheet;
    TabSheet1: TTabSheet;
    TrackBar1: TTrackBar;
    UpDown1: TUpDown;
    UpDown2: TUpDown;
    procedure AffListeClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure CheckBox1Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
    procedure Recherche(rechMot: string);
    procedure TrackBar1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure UpDown1Click(Sender: TObject; Button: TUDBtnType);
    procedure MAJAffichage;
    procedure MAJBalayage;
    procedure UpDown2Click(Sender: TObject; Button: TUDBtnType);
    procedure ZoomMouseLeave(Sender: TObject);
    function chercheTab(iMot : integer) : integer;
    procedure Lier(iMot, iLien: integer);
    procedure AffLiens;
 
  private
    { private declarations }
  public
    { public declarations }
  end;
 
const delta=5;
 
var
  Form1: TForm1;
  listeMots, listeInfo, listeObj : TstringList;
  iMot, nMots, nLiens : integer;
  Liens : Array of Array of integer;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
begin
   regLiens;
   listeMots.Free;
   Application.Terminate;
end;
 
procedure TForm1.AffListeClick(Sender: TObject);
begin
   iMot := (iMot -delta + AffListe.ItemIndex + nMots) mod nMots;
   MAJBalayage;
end;
 
procedure TForm1.Button2Click(Sender: TObject);
begin
  Recherche(Edit2.Caption);
end;
 
procedure TForm1.Button3Click(Sender: TObject);
var iLien, k : integer;
begin
   iLien := listeMots.IndexOf(UTF8ToAnsi(Edit3.Caption));
   if iLien<0 then
      ShowMessage('Ce mot n''existe pas, recommencez')
   else
   begin
     Lier(iMot, iLien);
     Lier(iLien, iMot);
     AffLiens;
   end;
   Edit3.Clear;
end;
 
 
procedure TForm1.CheckBox1Change(Sender: TObject);
begin
   if CheckBox1.Checked then CheckBox1.Caption := 'Avec filtre'
   else CheckBox1.Caption := 'Sans filtre';
end;
 
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  listeMots := TStringList.Create;
  LireFichier(listeMots);
  nMots:= listeMots.Count;
  lireLiens;
  Memo1.Append('Premier mot : '+listeMots[0]);
  Memo1.Append('Dernier mot : '+listeMots[nMots-1]);
  iMot := 0;
  MAJAffichage;
  MAJBalayage;
end;
 
procedure TForm1.ListBox1Click(Sender: TObject);
begin
   if ListBox1.ItemIndex >= 0 then
   begin
     iMot := Liens[chercheTab(iMot), ListBox1.ItemIndex+1];
     Label4.Caption := AnsiToUTF8(listeMots[iMot]);
     AffLiens;
   end;
end;
 
procedure TForm1.MAJBalayage;
var i : integer;
begin
   Label2.Caption:=AnsiToUTF8(listeMots[iMot]);
   Label3.Caption:= Label2.Caption;
   Label4.Caption:= Label2.Caption;
   Edit3.Clear;
   TrackBar1.Position:= Round(iMot*1000/nMots);
   AffListe.Clear;
   for i := 0 to 10 do
       AffListe.Items.Add(AnsiToUTF8(listeMots[(iMot-delta + i
                         + nMots) mod nMots]));
   AffListe.Selected[delta] := True;
   AffLiens;
   Caption := IntToStr(nMots)+ ' mots dont '+IntToStr(nLiens)+' liés';
end;
 
procedure TForm1.UpDown2Click(Sender: TObject; Button: TUDBtnType);
begin
   if CheckBox1.Checked then
      repeat
        inc(iMot);
      until (iMot=nMots) or (chercheTab(iMot)>=0)
   else
      if Button=btNext then Inc(iMot, UpDown2.Increment)
                         else Dec(iMot, UpDown2.Increment);
   iMot := (iMot + nMots) mod  nMots;
   MAJBalayage;
end;
 
procedure TForm1.ZoomMouseLeave(Sender: TObject);
begin
   if RadioButton1.Checked then UpDown2.Increment := 1
   else if RadioButton2.Checked then UpDown2.Increment := 10
   else if RadioButton3.Checked then UpDown2.Increment := 100
   else if RadioButton4.Checked then UpDown2.Increment := 1000;
end;
 
function TForm1.chercheTab(iMot: integer): integer;
var i : integer;
begin
 chercheTab := -1;
 i := 0;
 while (i<Length(Liens)) and (Liens[i, 0]<>iMot) do inc(i);
 if i<Length(Liens) then chercheTab := i;
end;
 
procedure TForm1.Lier(iMot, iLien: integer);
var k : integer;
begin
  k := chercheTab(iMot);
  if k < 0 then
  begin
     SetLength(Liens, Length(Liens)+1); //extension du tableau principal
     k := Length(Liens)-1;  //indice du nouveau tableau
     SetLength(Liens[k], 1);
     Liens[k, 0] := iMot; //identifiant
  end;
  SetLength(Liens[k], Length(Liens[k])+1);  //extension du tableau secondaire
  Liens[k, Length(Liens[k])-1] := iLien;  // lien
end;
 
procedure TForm1.AffLiens;
var i, k : integer;
begin
   ListBox1.Clear;
   k := chercheTab(iMot);
   if k>=0 then
     for i :=1 to Length(Liens[k]) -1 do
       ListBox1.Items.Add(AnsiToUTF8(listeMots[Liens[k, i]]));
end;
 
 
procedure TForm1.TrackBar1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   iMot := Round(TrackBar1.Position*nMots/1000);
   iMot := (iMot + nMots) mod  nMots;
   MAJBalayage;
end;
 
 
procedure TForm1.Recherche(rechMot: string);
var iMot : integer;
begin
   iMot := listeMots.IndexOf(rechMot);
   if iMot >= 0 then Label1.Caption:= listeMots[iMot]
                else Label1.Caption:= 'échec';
   Memo1.Append('Index '+IntToStr(iMot));
end;
 
 
 
procedure TForm1.UpDown1Click(Sender: TObject; Button: TUDBtnType);
begin
   if Button=btNext then Inc(iMot)
                       else Dec(iMot);
   iMot := iMot + nMots   mod  nMots;
   MAJAffichage;
end;
 
procedure TForm1.MAJAffichage;
begin
   Label1.Caption:=listeMots[iMot];
   Edit2.Caption:= '';
   Memo1.Append('Index '+IntToStr(iMot));
end;
 
end.

Et pour l'unité uDisque :

 
Sélectionnez

unit uDisque;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, Dialogs;
 
procedure LireFichier(listeMots : TStringList);
procedure regLiens;
procedure lireLiens;
 
implementation
 
uses uLex6;
 
procedure LireFichier(listeMots: TStringList);
begin
  listeMots.LoadFromFile('liste.de.mots.francais.frgut.txt');
end;
 
procedure regLiens;
var i, j, k : integer;
    fLiens : file of integer;
 
begin
  AssignFile(fLiens, 'fichLiens.bin');
  ReWrite(fLiens);
  for i := 0 to Length(Liens)-1 do
  begin
    j := Length(Liens[i]);
    Write(fLiens, j);
    for k:=0 to j-1 do
      Write(fLiens, Liens[i, k]);
  end;
  CloseFile(fLiens);
end;
 
procedure lireLiens;
var
  j, m : integer;
  fLiens : file of integer;
begin
  nLiens := 0;   //nombre de mots liés
  AssignFile(fLiens, 'fichLiens.bin');
  {$I-}
  Reset(fLiens);
  {$I+}
  if IOResult<>0 then
    ShowMessage('Fichier liens inexistant')
  else
  while not EOF(fLiens) do
  begin
    SetLength(Liens, nLiens+1);      //taille du tableau principal
    Read(fLiens, m);
    SetLength(Liens[nLiens], m);     //taille du tableau secondaire
    for j := 0 to m-1 do
      Read(fLiens, Liens[nLiens, j]); //remplissage de tableau secondaire
    inc(nLiens);                      //nombre de mots liés
  end;
  CloseFile(fLiens);
end;
 
end.

précédentsommairesuivant
Le premier élément de la liste possède l'index 0.
On peut faire plus compliqué en écrivant Liens[0][0] : les deux notations sont acceptées par le compilateur. Notez que la désignation indique une case dont le contenu est un entier encore inconnu.
N'oubliez pas de commencer par la déclaration de la fonction avant implémentation et de poursuivre dans le code après appui des touches Ctrl+Maj+C en recopiant les instructions

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2014 dimanche2003. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.