Hvordan WriteLn () egentlig?

stemmer
11

Siden en alder av dinosaurer, Turbo Pascal og i dag Delphi har en Write () og WriteLn () prosedyre som stille gjøre noen pene ting.

  • Antallet parametere er variabel;

  • Hver variabel kan være av alle slags typer; du kan levere heltall, dobbeltrom, strenger, booleans, og bland dem opp i den rekkefølgen;

  • Du kan gi flere parametere for hvert argument:

Skriv ( 'Hei': 10, 'World!': 7); // justeringsparametere

  • Den viser selv opp på en spesiell måte i koden fullføring drowdown:
    • Skriv ([var F: Fil]; P1 [..., PN])
    • WriteLn ([var F: File]; [P1 [..., PN]])

Nå som jeg skriver dette har jeg lagt merke til at Skrive og WriteLn ikke har de samme parentes i kodefullføring nedtrekksmenyen. Derfor ser det ut som dette ikke ble automatisk generert, men det ble hardkodet etter noen.

Uansett, jeg er i stand til å skrive prosedyrer som disse selv, eller er alt dette litt magi hardkodet kompilatoren lureri?

Publisert på 06/03/2009 klokken 04:04
kilden bruker
På andre språk...                            


9 svar

stemmer
24

Writeln er det vi kaller en kompilator "magic" -funksjon. Hvis du ser i System.pas, vil du ikke finne en Writeln som er deklarert noe som det du forventer. Kompilatoren bryter bokstavelig talt det hele ned til individuelle samtaler til ulike spesial runtime bibliotekfunksjoner.

Kort sagt, er det ingen måte å implementere din egen versjon som gjør alle de samme tingene som den innebygde writeln uten å endre kompilatoren.

Svarte 06/03/2009 kl. 04:40
kilden bruker

stemmer
2

Så vidt jeg vet, Pascal standardene ikke inkluderer variable argumenter.

Når det er sagt, IIRC, GNU Pascal la oss du si noe sånt som: Procecdure Foo (a: Integer, b: Integer, ...);

Prøv å søke i kompilatoren språk docs på "Variable Argumentlister" eller "Conformant arrays". Her er et eksempel på det senere: http://www.gnu-pascal.de/demos/conformantdemo.pas .

Som forrige plakaten sa writeln () er magi. Jeg tror problemet har å gjøre med hvordan bunken er satt sammen i en pascal funksjon, men det har vært en reell lenge siden jeg har tenkt på hvor ting var på stakken :)

Men med mindre du skriver på "writeln" -funksjonen (som allerede er skrevet), har du sannsynligvis ikke trenger å gjennomføre en prosedyre med variabel argumenter. Prøv gjentakelse eller rekursjon i stedet :)

Svarte 06/03/2009 kl. 04:43
kilden bruker

stemmer
1

Ja, du kan gjøre det i Delphi og venner (f.eks gratis pascal, Kylix, etc.), men ikke i mer "standard" pascal. Slå opp variant åpen array-parametere, som brukes med en syntaks noe sånt som dette:

procedure MyProc(args : array of const);

(det har vært et par år, og jeg har ikke manualer hånd, så sjekk detaljene før du fortsetter). Dette gir deg en åpen rekke TVarData(eller noe sånt) som du kan trekke RTTI fra.

Et notat om: Jeg tror ikke du vil være i stand til å matche x: y syntaks (som er spesiell), og vil sannsynligvis måtte gå med en litt mer detaljert wrapper.

Svarte 06/03/2009 kl. 05:42
kilden bruker

stemmer
4

Som Allen sa at du ikke kan skrive din egen funksjon som gjør alle de samme tingene.

Du kan imidlertid skrive en tekstfil driver som gjør noe skikk og når bruk standard Write (ln) til å skrive til tekstfil driver. Vi gjorde det i dere gamle DOS dager :)

( "Driver" i sammenheng med den forrige setningen er bare et stykke Pascal kode som er koblet inn i systemet ved å bytte en peker i systemenheten IIRC. Vært en lang tid siden sist jeg brukte dette trikset.)

Svarte 06/03/2009 kl. 06:59
kilden bruker

stemmer
1

De fleste er allerede sagt, men jeg liker å legge til et par ting.

Først kan du bruke Format-funksjonen. Det er flott å konvertere nesten alle slags variabel streng og kontrollere sin størrelse. Selv om det har sine svakheter:

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

produserer:

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

Så størrelsen er den minimale størrelse (akkurat som: x: y konstruksjon).

For å få en minimal mengde av variable argumenter, kan du arbeide med standard parametere og overbelastet funksjoner:

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

eller

procedure WriteSome(const A1: string); overload;
procedure WriteSome(const A1: Integer); overload;
Svarte 06/03/2009 kl. 08:02
kilden bruker

stemmer
1

Du kan ikke skrive din egen skrive- / writeln i gamle Pascal. De er generert av kompilatoren, formatering, begrunnelse, etc. Det er derfor noen programmerere som C-språk, selv den fleksible standardfunksjoner for eksempel printf, scanf, kan implementeres av noen kompetente programmerere.

Du kan også lage en identisk printf funksjon for C hvis du er tilbøyelig til å lage noe mer performant enn en implementert av C leverandøren. Det er ingen magi lureri i dem, koden din trenger bare å "gå" de variable argumenter.

PS

Men som MarkusQ har påpekt, kan noen varianter av Pascal (Free Pascal, Kylix, etc) lette variable argumenter. Sist jeg tinker med Pascal, siden DOS dager, Turbo Pascal 7.

Svarte 06/03/2009 kl. 08:56
kilden bruker

stemmer
1

Writeln er ikke "rekke konst", basert, men brytes ned av kompilatoren i ulike samtaler som konverterer argumentene til strengen og deretter kaller primitive writestring. Den "LN" er bare en funksjon som skriver lineending som en streng. (OS avhengig). Prosedyren variablene (funksjon pekere) for primitivene er en del av filtype (Textrec / filerec), noe som er grunnen til at de kan tilpasses. (F.eks AssignCrt i TP)

Hvis {$ I +} modus er på, etter hvert element, er en samtale til den iocheck funksjon laget.

GPC-konstruksjon som er angitt ovenfor er afaik det uendelige C åpne matrise. FPC (og AFAIK Delphi også) støtter dette også, men med ulik syntaks.

Fremgangsmåten somehting (en: rekke const); cdecl;

vil bli konvertert til å være ABI kompatibel med C, printf stil. Dette betyr at den aktuelle funksjonen (somehting i dette tilfellet) ikke kan få antall argumenter, men må stole på format parsing. Så dette er noe annet enn rekke konst, som er trygt.

Svarte 02/05/2009 kl. 12:32
kilden bruker

stemmer
2

Det er magi kompilatoren atferd snarere enn vanlig prosedyre. Og nei, det er ikke mulig å skrive slike subrutiner (dessverre!). Kodegenerering løser telling av aktuelle parametere og deres typer og oversettes til passende RTL samtaler (f.eks. Str () ) ved kompilering. Dette står i kontrast ofte foreslått rekke const (enkel variant matrise formell parameter, faktisk) som fører til å gjøre det samme under kjøring. Jeg er å finne senere nærmer klønete, svekker det kode lesbarhet noe, og Bugland (Borland / Inprise / Codegear / Embarcadero / navn den) brøt Kode Insight for varianten åpen matrise konstruktører (ja, jeg bryr meg, jeg bruker OutputDebugString (PChar (Format ( '...', [...])))) og kodefullføring ikke fungerer optimalt (eller i det hele tatt) der. Så, nærmest mulig måte å simulere magi atferd er å erklære mye belastet subrutiner (egentlig mange av dem, en per bestemt formell parameter type i bestemt posisjon). Man kan kalle dette en kludge også, men dette er den eneste måten å få fleksibilitet variable parameterlisten, og kan være skjult i egen modul.

PS: jeg utelatt format bransjen til side med vilje, fordi syntaks ikke tillater å semikolon bruke hvor Str () , Skriv () og Writeln () er imot dem.

Svarte 08/01/2010 kl. 02:10
kilden bruker

stemmer
1

Selv om ikke et direkte svar til deg spørsmålet, vil jeg gjerne legge til følgende kommentar: Jeg har nylig skrevet om noen kode ved hjelp Writeln (...) syntaks til å bruke en StringList, fylle den 'linjer' med Format (...) og bare ren IntToStr (...), FloatToStr (...) funksjoner og lignende.

Hovedårsaken til denne endringen var fart forbedring. Ved hjelp av en StringList og SaveFileTo er mye, mye mer raskere enn WriteLn, Skriv kombinasjonen.

Hvis du skriver et program som skaper en masse tekstfiler (jeg jobbet på et nettsted etableringen program), gjør dette til en stor forskjell.

Svarte 09/01/2010 kl. 10:18
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more