Section courante

A propos

Section administrative du site

Base de connaissances

Cette page contient une liste des principales questions ou Foire aux questions (FAQ) sur le Turbo Pascal :

Comment puis-je transmettre un code de niveau d'erreur (ERRORLEVEL) lorsque mon programme se termine ?

La procédure Halt prend un paramètre optionnel de type mot. Ainsi, :

  1. Halt(1);

termine le programme avec un niveau d'erreur de 1. Si Halt est utilisé sans paramètre, cela revient à la même chose que :

  1. Halt(0);

Remarque : Lorsqu'un programme est terminé à l'aide de la procédure Halt, toute procédure de sortie préalablement configurée est exécutée.

Comment vider la mémoire tampon du clavier ?

Il existe plusieurs méthodes pour y parvenir. Cependant, la plus sûre est :

  1. While Keypressed do Ch:=ReadKey;

Cela nécessite qu'une variable ch de type Char soit déclarée et que l'unité Crt soit utilisée. Pour le faire sans utiliser de variable :

  1. While Keypressed do While ReadKey=#0 do;

ou si vous utilisez Turbo Pascal 6 avec la syntaxe étendue activée :

  1. While KeyPressed do ReadKey;

Si vous ne souhaitez pas supporter les conséquences importants liés à l'utilisation de l'unité CRT et qu'il n'est pas nécessaire que le programme s'exécute sous un multitâche ou qu'il ne se compile dans d'autres marques de Pascal :

  1. Procedure ClearKeyboard;
  2. Var
  3.  Head:Byte Absolute $40:$1C;
  4.  Tail:Byte Absolute $40:$1E;
  5. Begin
  6.  Tail:=Head;
  7. End;

Lorsqu'on redirige la sortie d'écran de mes programmes vers un fichier, le fichier est vide et la sortie apparaît toujours à l'écran. Pourquoi se comportement étrange ?

Vous utilisez probablement l'unité CRT et sa méthode par défaut d'écriture sur stdout est l'écriture directe à l'écran. Pour permettre la redirection de la sortie, toutes les écritures doivent être effectuées par DOS. La définition de la variable DirectVideo sur False n'a aucun effet sur la redirection car elle ne fait qu'utiliser le BIOS pour les écritures à l'écran - pas le DOS.

Pour activer la redirection, vous ne devez pas utiliser l'unité CRT ou :

  1. Assign(Output,'');
  2. Rewrite(Output);

Cela fera passer toutes les sorties par DOS et pourra donc être redirigée si vous le souhaitez. Pour restaurer la situation par défaut :

  1. AssignCRT(Output); 
  2. Rewrite(Output);

Comment convertir une chaîne de caractères composée de minuscules ou d'une combinaison de majuscules en majuscules ?

Il existe plusieurs façons de convertir des caractères minuscules en majuscules.

En voici quelques-unes.

En tant que procédure (à l'exclusion du code ASM, c'est le moyen le plus rapide).

  1. Procedure StrUpper(Var St:String);                                   
  2. Var 
  3.  X:Byte;
  4. Begin                                                               
  5.  For X:=1 to Length(St) do St[X]:=UpCase(St[X]);
  6. End;

Une procédure n'est malheureusement pas très pratique, il est souvent préférable d'avoir la même routine mais écrit en fonction :

  1. Function StrUpper(S:String):String;
  2. Var
  3.  I:Byte;
  4. Begin
  5.  For I:=1 to Length(S)do S[I]:=UpCase(S[I]);
  6.  StrUpper:=S;
  7. End;

Si vous souhaitez utiliser cette même fonction sans avoir recours à la fonction prédéfinit UpCase, vous pouvez toujours la fonction suivante :

  1. Function StrToUpper(S:String):String;
  2. Var
  3.  I:Byte;
  4. Begin
  5.  For I:=1 to Length(S)do Begin
  6.   If S[I] in['a'..'z']Then S[I]:=Chr(Ord(S[I])-32);
  7.  End;
  8.  StrToUpper:=S;
  9. End;

Les deux méthodes ci-dessus sont uniquement adaptées à la langue anglaise. Cependant, à partir de la version 4.0, le DOS (Interruption 21h, Fonction 65h) a la possibilité de le faire d'une manière spécifique au pays (langue). Les appels DOS feraient de cette méthode la plus lente de toutes :

  1. Function StrUpper(S:String):String;
  2. Var
  3.  Regs:Registers;
  4.  X:Byte;
  5. Begin
  6.  If Lo(DosVersion)>=4 Then Begin
  7.   With Regs do Begin
  8.    AX:=$6521;
  9.    DS:=Seg(S); 
  10.    DX:=Ofs(S[1]);
  11.    CX:=Length(S);
  12.    MsDos(Regs);
  13.    If Not Odd(Flags)Then Begin
  14.     StrUpper:=S;
  15.     Exit;
  16.    End;
  17.   End;                                                       
  18.  End;
  19.  For X:=1 to Length(S) do S[X]:=UpCase(S[X]);
  20.  StrUpper:=S;
  21. End;

Lorsque on inclus des codes ANSI dans une chaîne de caractères et qu'on écrit cette chaîne de caractères à l'écran, les codes réels apparaissent à l'écran, plutôt que les résultats qu'ils sont censés produire ?

Pour que les codes ANSI soient interprétés, les écritures à l'écran doivent être dirigées via DOS et un pilote approprié doit avoir été chargé via le fichier CONFIG.SYS au moment du démarrage. Toutes les sorties peuvent être dirigées via DOS et le pilote en (sans utiliser l'unité Crt) ou :

  1. Assign(Output,'');
  2. Rewrite(Output);

auquel cas toutes les écritures d'écran sont «sensibles au code ANSI» ou vous pouvez configurer des procédures d'écriture étant «sensibles au code ANSI». Vous aurez besoin d'une procédure d'initialisation pour configurer cela :

  1. Var                                                                     
  2.  Ansi:Text;                                                          
  3.  
  4. Procedure AssignANSI(Var AnsiFile:Text);Begin
  5.  Assign(AnsiFile,'CON');
  6.  Rewrite(AnsiFile);
  7. End; 
  8.  
  9. Procedure WriteANSI(Var St:String);Begin                                                                 
  10.  Write(Ansi,St)
  11. End;
  12.  
  13. Procedure WriteLnANSI(Var St:String);Begin
  14.  WriteANSI(St);
  15.  WriteLn(Ansi);
  16. End;

De toute évidence, si le pilote ANSI.SYS (ou un équivalent) n'est pas installé, rien de ce qui précède ne peut fonctionner.

Définir la variable DirectVideo dans l'unité CRT sur False n'atteindra pas le résultat souhaité car cela désactive simplement les écritures directes sur l'écran et utilise le BIOS pour toutes les sorties d'écran.

Lorsque on essaie d'exécuter un interpréteur de commande sous DOS, rien ne se passe. Qu'elle étape n'a pas été respecté ?

Pour pouvoir exécuter un processus enfant, il doit y avoir suffisamment de mémoire disponible pour qu'il puisse se charger et s'exécuter. Sauf avis contraire de votre part au moment de la compilation, un programme Turbo Pascal récupère toute la mémoire disponible pour lui-même lorsqu'il est chargé. Pour réserver de la mémoire pour un processus enfant, utilisez la directive mémoire du compilateur :

  1. {$M 16384,0,0}

La valeur par défaut est :

  1. {$M 16384,0,655360}

Le premier chiffre - StackMin - est la quantité de mémoire à allouer à la pile :

Valeur minimum 1024
Valeur par défaut 16384
Valeur maximum 65520

Le chiffre suivant, HeapMin, représente la quantité minimale de mémoire à allouer à la mémoire de tas. Si la mémoire disponible est inférieure à ce chiffre, le programme ne se chargera pas.

Valeur minimum 0
Valeur par défaut 0
Valeur maximum 655360

En pratique, la valeur maximum indiquera la quantité de mémoire libre moins l'espace requis pour la pile, moins l'espace de code du programme. Vous devez définir cette valeur sur 0, sauf si votre programme utilise la mémoire de tas. Dans ce cas, définissez-la sur la valeur la plus basse possible pour éviter les erreurs d'allocation de mémoire de tas. Dans la plupart des cas, il est préférable de la laisser à zéro et de vérifier les erreurs dans le programme pour s'assurer qu'il y a suffisamment de mémoire au moment de l'allocation.

Le dernier chiffre est crucial pour les processus enfants. Il doit toujours être suffisamment bas pour laisser de la mémoire pour un processus enfant et suffisamment haut pour ne pas causer de problèmes au programme lors de l'allocation de la mémoire de tas.

Valeur minimum HeapMin
Valeur par défaut 655360
Valeur maximum 655360

Si la quantité disponible est inférieure à la quantité demandée, aucune erreur n'est signalée. Au lieu de cela, toute la mémoire disponible est allouée à l'utilisation de la mémoire de tas.

Comment peut-on lancer un interpréteur de commande sous DOS ?

Vous devez inclure les lignes de code suivante :

  1. SwapVectors;
  2. Exec(GetEnv('COMSPEC','');
  3. SwapVectors;

Lisez la section précédente sur l'allocation de mémoire.

Il peut être avantageux d'écrire sa propre fonction Exec faisant tout ce qui est nécessaire dans le code source d'un même programme. On peut renvoyer une valeur entière étant le code DOSERROR :

  1. Function Exec(p1,p2:String);Begin                                                                 
  2.  SwapVectors;
  3.  Dos.Exec(p1,p2);
  4.  SwapVectors;
  5.  Exec:=DosError;
  6. End;

Ensuite, on peut d'avoir une déclaration telle que :

  1. ReportError(Exec(GetEnv('COMPSEC'),''));                                

Ainsi, vous pouvez disposer d'une procédure ReportError vide ou la faire signaler l'erreur, selon ce qui convient à votre application.

Lorsque on exécute un processus enfant, la redirection ne fonctionne pas. Pourquoi ?

La redirection de la sortie d'un processus enfant ne fonctionne que si elle est exécutée sous une autre copie du processeur de commandes. Donc :

Ne fonctionne pas :

  1. Exec('YourProg.exe',' > nul');

Fonctionne :

  1. Exec(GetEnv('COMSPEC'),'/c YourProg > nul');

Comment lire un niveau d'erreur (ERRORLEVEL) d'un processus enfant ?

Après l'exécution d'un processus enfant, le niveau d'erreur renvoyé peut être lu en appelant la fonction DosExitCode renvoyant un mot. L'octet de poids faible est le niveau d'erreur (ERRORLEVEL).

Si l'interpréteur de commandes est le processus enfant et qu'il exécute à son tour un processus enfant, le niveau d'erreur du deuxième processus enfant ne peut pas être lu sans recourir à une astuce.

Lorsque je lis un fichier texte dont les lignes dépassent 255 caractères, je perds tous ces caractères à partir du 256e à chaque fois qu'une ligne dépasse cette longueur. Comment peut-on éviter cela ?

La procédure ReadLn de Turbo Pascal lit une ligne jusqu'au 255e caractère puis passe à la ligne suivante. Pour contourner ce problème, vous devez déclarer un tampon au moins aussi grand que la ligne la plus longue possible, puis utiliser la procédure Read. La meilleure taille pour le tampon est un multiple de 2048 octets.

  1. Const
  2.  BufferSize=2048;
  3.  LineLength=78;
  4.  
  5. Type
  6.  TextBuffer=Array[1..BufferSize] of Char;
  7.  
  8. Var
  9.  St:String;
  10.  F:Text;
  11.  Buffer:Textbuffer;
  12.  
  13. { Lit une chaîne d'une longueur maximale à partir d'un fichier texte: }
  14. Function ReadTxtLn(Var TF:Text;Var S:String;Max:Byte):Integer;
  15. Var
  16.  Len:Byte absolute S;
  17. Begin
  18.  Len:=0;
  19.  {$I-}
  20.  While(Len<Max)and Not Eoln(TF)do Begin
  21.   Inc(len);
  22.   Read(tf);
  23.  End;
  24.  If Eoln(Tf)Then ReadLn(Tf);
  25.  ReadTxtLn:=IOResult;
  26.  {$I+}
  27. End; 
  28.  
  29. BEGIN
  30.  Assign(F,FileName);
  31.  Reset(F);
  32.  SetTextBuf(F,Buffer);
  33.  While Not Eof(F)and(ReadTxtLn(F,St,LineLength)=0)do WriteLn(ST);
  34.  Close(F);
  35. END.


Dernière mise à jour : Jeudi, le 8 juillet 2024