Strängtyp

Inom datavetenskap är en strängtyp ( engelsk  sträng "tråd, sträng") en datatyp vars värden är en godtycklig sekvens (sträng) av alfabettecken . Varje variabel av denna typ ( strängvariabel ) kan representeras av ett fast antal byte eller ha en godtycklig längd.

Minnesrepresentation

Vissa programmeringsspråk lägger begränsningar på den maximala längden på en sträng, men de flesta språk har inte sådana begränsningar. När du använder Unicode kan varje tecken av strängtypen kräva två eller till och med fyra byte för att representera det.

Huvudproblemen i maskinrepresentationen av strängtypen är:

Det finns två fundamentalt olika sätt att representera strängar i datorns minne.

Character array representation

I detta tillvägagångssätt representeras strängar av en rad tecken ; storleken på arrayen lagras i ett separat (service)område. Från namnet på Pascal- språket , där denna metod först implementerades, kallas denna metod för Pascal-strängar .

En något optimerad version av denna metod är den så kallade. c-addr u- format (från engelska  teckenjusterad adress + osignerat nummer ) som används i Forth . Till skillnad från Pascal-strängar, här lagras inte storleken på arrayen tillsammans med strängdata, utan är en del av pekaren till strängen.

Fördelar
  • programmet vid varje tidpunkt innehåller information om storleken på strängen, så operationerna med att lägga till tecken i slutet, kopiera strängen och faktiskt få strängstorleken utförs ganska snabbt;
  • strängen kan innehålla vilken data som helst;
  • det är möjligt på programnivå att övervaka utgången från linjegränserna under dess bearbetning;
  • det är möjligt att snabbt utföra en operation som att "ta det N:te tecknet från slutet av strängen".
Nackdelar
  • problem med att lagra och bearbeta tecken av godtycklig längd;
  • ökning av kostnaden för lagring av strängar - värdet av "stränglängd" tar också upp utrymme och, i fallet med ett stort antal strängar av liten storlek, kan det avsevärt öka algoritmens krav på RAM;
  • maximal linjestorlek. I moderna programmeringsspråk är denna begränsning mer teoretisk, eftersom storleken på en sträng vanligtvis lagras i ett 32-bitarsfält, vilket ger en maximal strängstorlek på 4 294 967 295 byte (4 gigabyte);
  • när du använder ett alfabet med variabel teckenstorlek (till exempel UTF-8 ) lagrar storleken inte antalet tecken, utan storleken på strängen i byte, så antalet tecken måste räknas separat.

Avslutande byte-metod

Den andra metoden är att använda "termineringsbyten" [1] [2] . Ett av de möjliga värdena för tecknen i alfabetet (vanligtvis ett tecken med kod 0) väljs som terminator för strängen, och strängen lagras som en sekvens av byte från början till slut. Det finns system där byten 0xFF (255) eller teckenkoden "$" används som ett tecken på slutet av raden, inte tecknet 0.

Metoden har tre namn - ASCIIZ (eller asciz, ASCII-tecken med en nollterminerande byte), C-strängar (metoden används mest i C -språket ) och nollterminerad strängmetod .

Fördelar
  • frånvaron av ytterligare serviceinformation om linjen (förutom den sista byten);
  • förmågan att representera en sträng utan att skapa en separat datatyp;
  • ingen gräns för den maximala radstorleken;
  • ekonomisk användning av minne;
  • lätt att få strängsuffixet;
  • lätt att skicka strängar till funktioner (en pekare till det första tecknet skickas);
Nackdelar
  • lång utförande av operationer för att erhålla längden och sammanlänkningen av strängar;
  • brist på medel för att kontrollera utgången från linjen, i händelse av skada på den slutliga byten, möjligheten att skada stora minnesområden, vilket kan leda till oförutsägbara konsekvenser - förlust av data, krasch av programmet och till och med hela systemet;
  • oförmågan att använda det avslutande bytetecknet som ett strängelement.
  • oförmågan att använda vissa kodningar med en teckenstorlek på flera byte (till exempel UTF-16), eftersom i många sådana tecken, till exempel  (0x0100), en av byten är noll (samtidigt UTF- 8-kodning är fri från denna nackdel).

Med båda metoderna

På språk som till exempel Oberon placeras en sträng i en rad tecken av en viss längd, och dess slut indikeras med ett nolltecken. Som standard är hela arrayen fylld med nolltecken. Denna metod låter dig kombinera många av fördelarna med båda tillvägagångssätten, samt undvika de flesta av deras nackdelar.

Listvy

Språken Erlang [3] , Haskell [4] , Prolog [5] använder en lista med tecken för strängtypen . Denna metod gör språket mer "teoretiskt elegant" genom att respektera ortogonalitet i typsystemet , men medför en betydande prestationsstraff.

Implementering i programmeringsspråk

  • De första programmeringsspråken hade ingen strängtyp alls; programmeraren var tvungen att bygga funktioner för att arbeta med strängar av en eller annan typ.
  • C använder noll -terminerade strängar med full manuell kontroll av programmeraren.
  • I standard Pascal ser en sträng ut som en array på 256 byte; den första byten lagrade strängens längd, resten lagrade dess kropp. Stränglängden får alltså inte överstiga 255 tecken. Borland Pascal 7.0 introducerade också "a la C "-linjer, uppenbarligen på grund av att Windows ingick bland de stödda plattformarna .
  • I Object Pascal och C++ STL är en sträng en "svart låda" där minnesallokering/deallokering sker automatiskt - utan medverkan av programmeraren . När en sträng skapas tilldelas minne automatiskt; så snart det inte finns någon referens kvar till strängen, returneras minnet till systemet. Fördelen med denna metod är att programmeraren inte behöver tänka på hur strängar fungerar. Å andra sidan har programmeraren otillräcklig kontroll över programmets funktion i hastighetskritiska områden; det är också svårt att skicka sådana strängar som en parameter till en DLL . Objekt Pascal ser också automatiskt till att det finns ett tecken med kod 0 i slutet av strängen. Därför, om funktionen kräver en nollterminerad sträng som indata behöver du bara skriva eller (för Pascal), (för Builder ) /STL) för att konvertera.PAnsiChar(строковая_переменная)PWideChar(строковая_переменная)переменная.c_str()
  • I C# och andra skräpsamlade språk är en sträng ett oföränderligt objekt; om strängen behöver ändras skapas ett annat objekt. Denna metod är långsam och slösar bort mycket tillfälligt minne, men passar bra med konceptet med sophämtning. Fördelen med denna metod är att tilldelningen är snabb och utan dubbletter av rader. Det finns också en viss manuell kontroll över konstruktionen av strängar (i Java , till exempel genom klasser StringBuffer и StringBuilder) - detta gör att du kan minska antalet minnestilldelningar och releaser och följaktligen öka hastigheten.
    • På vissa språk (till exempel Standard ML ) finns det dessutom en extra modul för att ge ännu större effektivitet - "substring" (SubString). Dess användning låter dig utföra operationer på strängar utan att kopiera deras kroppar genom att manipulera indexen för början och slutet av delsträngen; fysisk kopiering sker endast när det är nödvändigt att konvertera delsträngar till strängar.

Operationer

Grundläggande strängoperationer
  • få ett tecken efter positionsnummer (index) - på de flesta språk är detta en trivial operation;
  • sammanlänkning (anslutning) av strängar.
Derivatverksamhet Operationer när strängar behandlas som listor
  • faltning ;
  • kartläggning från en lista till en annan;
  • filtrera listan efter kriterier.
Mer komplexa operationer
  • hitta den minsta supersträngen som innehåller alla de specificerade strängarna;
  • sök i två uppsättningar av strängar efter matchande sekvenser ( plagiatproblem ) .
Möjliga uppgifter för naturliga språksträngar

Teckenrepresentation av en sträng

Tills nyligen var ett tecken alltid kodat som en byte (8 binära bitar; kodningar med 7 bitar per tecken användes också), vilket gjorde det möjligt att representera 256 (128 med en sju-bitars kodning) möjliga värden. Men för en fullständig representation av tecknen i alfabeten på flera språk (flerspråkiga dokument, typografiska tecken - flera typer av citat , bindestreck , flera typer av mellanslag och för att skriva texter på hieroglyfiska språk - kinesiska , japanska och koreanska ) 256 tecken räcker inte. Det finns flera metoder för att lösa detta problem:

  • Språkväxling med kontrollkoder. Metoden är inte standardiserad och berövar texten oberoende (det vill säga en sekvens av tecken utan en kontrollkod i början förlorar sin betydelse); användes i vissa tidiga förryskningar av ZX-Spectrum och BK .
  • Använda två eller fler byte för att representera varje tecken ( UTF-16 , UTF-32 ). Den största nackdelen med denna metod är förlusten av kompatibilitet med tidigare textbibliotek när en sträng representeras som ASCIIZ. Till exempel bör slutet av en sträng inte längre betraktas som en byte med värdet 0, utan två eller fyra på varandra följande nollbyte, medan en enda byte "0" kan förekomma i mitten av en sträng, vilket förvirrar biblioteket.
  • Använder en kodning med variabel teckenstorlek. Till exempel, i UTF-8 representeras vissa tecken av en byte, vissa av två, tre eller fyra. Denna metod låter dig behålla delvis kompatibilitet med gamla bibliotek (det finns inga 0-tecken inuti strängen och därför kan 0 användas som ett tecken på slutet av strängen), men leder till omöjligheten att direkt adressera ett tecken i minnet genom att dess positionsnummer i strängen.

Lexikal analys

För att kontrollera överensstämmelsen för alla ordformer under lexikal (semantisk) analys används symboliska likhetsmått:

Se även

Anteckningar

  1. Det dyraste One-byte-misstaget - ACM-kö . Hämtad 17 september 2016. Arkiverad från originalet 19 september 2016.
  2. Joel om programvara - Tillbaka till grunderna . Hämtad 17 september 2016. Arkiverad från originalet 16 september 2016.
  3. Simon St. Laurent. Vi presenterar Erlang . - O'Reilly Media, Inc., 2013. - S.  62 . — 185 sid. - ISBN 978-1-449-33176-4 .
  4. Bryan O'Sullivan, Don Stewart, John Goerzen, Real World Haskell. Bilaga B. Tecken, strängar och escape-regler Arkiverad 26 januari 2012 på Wayback Machine
  5. SWI-Prolog Manual: 5.2.2 Representerande text: strängar, atomer och kodlistor Arkiverad 17 juli 2014 på Wayback Machine