Question

Depuis l'âge des dinosaures, Turbo Pascal et, aujourd'hui, Delphi ont une procédure Write () et WriteLn () qui effectue discrètement des tâches intéressantes.

  • Le nombre de paramètres est variable;

  • Chaque variable peut être de toutes sortes; vous pouvez fournir des nombres entiers, des doublons, des chaînes de caractères, des booléens et les mélanger dans n'importe quel ordre;

  • Vous pouvez fournir des paramètres supplémentaires pour chaque argument:

  

Write ('Hello': 10, 'World!': 7); // paramètres d'alignement

  • Cela apparaît même de manière spéciale dans le rapport final de code:
    • Écrire ([var F: Fichier]; P1; [..., PN])
    • WriteLn ([var F: Fichier]; [P1; [..., PN]])

Maintenant que je tapais ceci, j'ai remarqué que Write et WriteLn n'avaient pas les mêmes crochets dans la liste déroulante de complétion de code. Par conséquent, il semble que cela n'ait pas été généré automatiquement, mais que quelqu'un l'a codé en dur.

Quoi qu'il en soit, suis-je capable d'écrire moi-même des procédures comme celles-ci, ou est-ce que tout cela est une supercherie de compilateur codé en dur?

Était-ce utile?

La solution

Writeln est ce que nous appelons un compilateur "magique". une fonction. Si vous regardez dans System.pas, vous ne trouverez pas un Writeln déclaré comme ce que vous attendez. Le compilateur décompose littéralement le tout en appels individuels à diverses fonctions spéciales de la bibliothèque d'exécution.

En bref, il n’existe aucun moyen d’implémenter votre propre version qui réponde aux mêmes exigences que le script Writeln intégré sans modifier le compilateur.

Autres conseils

Comme l'a dit Allen, vous ne pouvez pas écrire votre propre fonction qui fait toutes les mêmes choses.

Vous pouvez cependant écrire un pilote de fichier texte qui fait quelque chose de personnalisé et lorsque vous utilisez l'écriture standard (ln) pour écrire sur votre pilote de fichier texte. Nous l’avons fait à votre époque DOS:)

("Pilote" dans le contexte de la déclaration précédente est simplement un morceau de code Pascal qui est connecté au système en commutant un pointeur dans l'unité système IIRC. Il y a longtemps que j'ai utilisé cette astuce pour la dernière fois.)

Autant que je sache, les normes pascal n'incluent pas d'arguments variables.

Ceci étant dit, IIRC, GNU Pascal vous permettent de dire quelque chose comme:   Procecdure Foo (a: entier; b: entier; ...);

Essayez de rechercher dans la documentation de votre compilateur des "Listes d'arguments variables". ou "matrices conformes". En voici un exemple: http://www.gnu-pascal.de/demos /conformantdemo.pas .

Comme l'a dit l'affiche précédente, Writeln () est magique. Je pense que le problème est lié à la manière dont la pile est assemblée dans une fonction pascal, mais cela fait très longtemps que je n’ai pas déterminé où en étaient les choses:)

Cependant, à moins d'écrire le texte "Writeln". fonction (qui est déjà écrite), vous n'avez probablement pas besoin d'implémenter une procédure avec des arguments variables. Essayez plutôt l'itération ou la récursion:)

C’est le comportement du compilateur magique plutôt que la procédure habituelle. Et non, il n'y a aucun moyen d'écrire de tels sous-programmes (malheureusement!). La génération de code résout le nombre de paramètres réels et leurs types et se traduit en appels RTL appropriés (par exemple, Str () ) au moment de la compilation. Cela va à l’encontre du tableau de const souvent suggéré (paramètre formel d’un tableau variant unique, en fait), ce qui conduit à faire de même au moment de l’exécution. Je trouve l'approche plus tardive maladroite, cela nuit quelque peu à la lisibilité du code, et Bugland (Borland / Inprise / Codegear / Embarcadero / nommez-le) a cassé l'inspection de code pour les constructeurs de tableaux à variantes ouvertes (oui, je me soucie, j'utilise OutputDebugString (PChar ('...', [...])))) et la complétion de code ne fonctionne pas correctement (ou pas du tout) là-bas. Ainsi, le moyen le plus proche de simuler un comportement magique consiste à déclarer un grand nombre de sous-programmes surchargés (en réalité un grand nombre, un par type de paramètre formel spécifique dans la position spécifique). On pourrait aussi appeler cela un kludge, mais c’est le seul moyen d’obtenir de la souplesse dans la liste des paramètres variables et peut être masqué dans un module séparé.

PS: j’ai volontairement laissé de côté les spécificateurs de format, car la syntaxe n’autorise pas les points-virgules à utiliser Str () , Write () et Writeln ( ) les acceptent.

Oui, vous pouvez le faire dans Delphi et ses amis (par exemple, Free Pascal, Kylix, etc.), mais pas dans la catégorie "Standard". pascals. Recherchez les paramètres de tableau ouvert variantes, qui sont utilisés avec une syntaxe semblable à ceci:

procedure MyProc(args : array of const);

(Cela fait quelques années et je n'ai pas de manuel, alors vérifiez les détails avant de continuer). Cela vous donne un tableau ouvert de TVarData (ou quelque chose du genre) à partir duquel vous pouvez extraire RTTI.

Une remarque cependant: je ne pense pas que vous serez en mesure de respecter la syntaxe de formatage x: y (ce qui est spécial), et vous devrez probablement utiliser un wrapper légèrement plus détaillé.

La plupart est déjà dit, mais j'aime bien ajouter quelques petites choses.

D'abord, vous pouvez utiliser la fonction Format. Il est bon de convertir presque n'importe quel type de variable en chaîne et de contrôler sa taille. Bien qu'il ait ses défauts:

myvar := 1;
while myvar<10000 do begin
  Memo.Lines.Add(Format('(%3d)', [myVar]));
  myvar := myvar * 10;
end;

Produit:

(  1)
( 10)
(100)
(1000)

Donc, la taille est la taille minimale (tout comme la construction: x: y).

Pour obtenir un nombre minimal d'arguments variables, vous pouvez utiliser des paramètres par défaut et des fonctions surchargées:

procedure WriteSome(const A1: string; const A2: string = ''; const A3: string = '');

ou

procedure WriteSome(const A1: string); overload;
procedure WriteSome(const A1: Integer); overload;

Vous ne pouvez pas écrire votre propre écriture / écriture dans le vieux Pascal. Ils sont générés par le compilateur, le formatage, la justification, etc. C'est pourquoi certains programmeurs aiment le langage C, même les fonctions standard flexibles, par exemple. printf, scanf, peut être implémenté par tout programmeur compétent.

Vous pouvez même créer une fonction printf identique pour C si vous souhaitez créer quelque chose de plus performant que celui mis en œuvre par le fournisseur C. Ils ne contiennent aucune astuce magique, votre code doit simplement "marcher". les arguments variables.

P.S.

Mais, comme MarkusQ l’a souligné, certaines variantes de Pascal (Free Pascal, Kylix, etc.) peuvent faciliter les arguments variables. Pour la dernière fois, j'ai bricolé Pascal, depuis DOS jours, Turbo Pascal 7.

Writeln n’est pas un "tableau de const" basé, mais décomposé par le compilateur en divers appels qui convertissent les arguments en chaîne, puis appellent la primitive Writestring. Le " LN " est juste une fonction qui écrit le lineending sous forme de chaîne. (Dépend du système d'exploitation). Les variables de procédure (pointeurs de fonction) des primitives font partie du type de fichier (Textrec / filerec), raison pour laquelle elles peuvent être personnalisées. (par exemple, AssignCrt dans TP)

Si le mode {$ I +} est activé, après chaque élément, un appel à la fonction iocheck est effectué.

La construction GPC faite ci-dessus est toujours la matrice ouverte illimitée en C. FPC (et après tout Delphi aussi) supporte cela aussi, mais avec une syntaxe différente.

procedure somehting (a: tableau de const); cdecl;

sera converti pour être compatible ABI en C, style printf. Cela signifie que la fonction pertinente (quelquefois dans ce cas) ne peut pas obtenir le nombre d'arguments, mais doit s'appuyer sur l'analyse de formatstring. C’est donc quelque chose de différent du tableau de const, qui est sûr.

Bien que ce ne soit pas une réponse directe à votre question, j'aimerais ajouter le commentaire suivant: J'ai récemment réécrit du code en utilisant la syntaxe Writeln (...) en utilisant une StringList, en remplissant les 'lignes' avec Format (...) et simplement les fonctions IntToStr (...), FloatToStr (...) et les comme.

La principale raison de ce changement est l’amélioration de la vitesse. L'utilisation d'une StringList et de SaveFileTo est beaucoup plus rapide que la combinaison WriteLn, Write.

Si vous écrivez un programme qui crée beaucoup de fichiers texte (je travaillais sur un programme de création de site Web), cela fait toute la différence.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top