String

I datateknikk, en tegnstreng , tegnsekvens , tegnstreng eller en streng (fra engelsk) er en endelig sekvens av tegn (for eksempel bokstaver, tall, spesielle tegn og kontrolltegn ) fra et definert tegnsett . Tegn kan gjentas i en tegnstreng, rekkefølgen på tegnene er definert. En tegnstreng kan også være tom , dvs. ikke inneholde tegn og ha lengden 0. Karakterstrenger er altså sekvenser av symboler med en endelig lengde.

I programmering er en tegnstreng en datatype som inneholder en streng med tegn med fast eller variabel lengde. Dette lagrer hovedsakelig ord, setninger og hele tekster. Nesten hvert programmeringsspråk har en slik datatype, og noen programmeringsspråk fungerer bare med denne datatypen. Eksempler er sed , awk og bash . I kildeteksten til et dataprogram representerer tegnstrenger tekst som ikke tolkes som en programmeringskommando , men som inneholder informasjon. For eksempel kan feilmeldinger eller andre utganger til brukeren registreres som en tegnstreng i kildeteksten, eller brukerinngangene kan lagres som tegnstrenger i variabler.

Grunnleggende om programmeringsspråk blir undersøkt i teoretisk informatikk . Der kalles det gitte tegnsettet alfabetet og tegnstrenger kalles " ord ". Teorien om slike ord er et emne for formelle språk . I forbindelse med programmeringsspråk er det derimot spørsmål om representasjon, lagring og håndtering av tegnstrenger.

representasjon

Strenger kan være representert på forskjellige nivåer. En av dem er kildeteksten til et program som blir lest og tolket av oversetteren. En annen er hvordan en streng med tegn lagres i minnet når programmet kjører.

Syntaks for bokstavelige

I nesten alle programmerings- og markeringsspråk som støtter bokstaver for tegnstrenger, representeres en bokstavstreng ved å bare knytte tegn mellom enkle eller doble anførselstegn:

  • "Wikipedia"
  • 'Wikipedia.'
  • "123"(i de aller fleste språk som er forskjellige fra antallet 123).
  • ""(en tom streng , tom streng )

Enden av strengen er merket med det første anførselstegnet (ikke det siste på linjen). Så spørsmålet oppstår om hvordan et anførselstegn kan være en del av strengen hvis det er det som ønskes.

Hvis et språk tilbyr to eller flere avgrensere, kan andre avgrensere brukes:

  • "Das ist's"
  • 'Er sagte "nie und nimmer" und ging'

Hvis alle avgrensere forekommer, kan en avgrenser vanligvis spesifiseres i tegnstrengen ved hjelp av en rømningssekvens eller ved å doble den som en del av tegnstrengen.

  • "Escape-Sequenz, um das Anführungszeichen \" als Teil der Zeichenkette aufzunehmen."
    (hovedsakelig på C- lignende og mange andre moderne språk)
  • "Dopplung, um ein "" aufzunehmen"
    (Dobling av avgrenseren, f.eks. I Excel , Pascal , BASIC dialekter, CSV eller Rexx )

De to tilnærmingene er inkompatible: På språk som bruker dobling av skilletegnet, blir ikke sekvenser for flukt anerkjent som sådan og avslutter tegnsekvensen, noe som vanligvis fører til syntaksfeil. På språk som bruker escape-sekvenser, avslutter en doblet skillelinje strengen og begynner en ny.

For visse språk er det mulig at forskjellene bare fører til forskjellige resultater, men ikke til syntaksfeil. Brukes for eksempel "\"'"av C til å representere "'. I BASIC betyr denne oppføringen tegnstrengen \etterfulgt av en kommentar. Omvendt, i C, grupperes tilstøtende strenglitteraturer automatisk sammen, noe som får det til å virke som om et dobbelt anførselstegn forsvinner i en streng; i sannhet slutter strengen, en ny begynner, og de to slås sammen.

I Algol 60 startes og avsluttes tegnstrenger med forskjellige symboler; dette betyr at strenger også kan nestes. Eksempler:

  • ʿEr sagte: ʿSo ist's recht!ʾʾ
  • '('Bei beschränktem Zeichenvorrat werden die '('Stringklammern')' durch '('Trigraphen')' dargestellt.')'

På mange eldre språk må strenglitteraturer skrives på en enkelt linje, med escape-sekvenser eller andre løsninger tilgjengelig for linjeskift. Moderne programmeringsspråk tilbyr vanligvis muligheter for å legge inn tegnstrenger med flere linjer som sådan i koden.

Turnuskandidat

Det er flere metoder for effektiv lagring av tegnstrenger. For eksempel kan et tegn fra tegnsettet som brukes defineres som en terminator. En tegnstreng avsluttes før den første forekomsten av denne karakteren. En annen mulighet er å lagre lengden på tegnstrengen separat.

Representasjon med terminator

I programmeringsspråk, slik som C, blir tegnstrengene kontinuerlig lagret i hukommelsen og avsluttet med null-tegn (NUL i ASCII ). Nulltegnet er tegnet hvis binære representasjon har den numeriske verdien 0. (Tallet 0 som tegn har en annen binær representasjon enn 0.) Følgende eksempel viser hvordan en tegnstreng med 5 tegn kan lagres i en buffer på 10 byte:

karakter F. R. EN. N K NUL k 0 f w
Numeriske verdier 46 52 41 4E 4B 00 6B 30. 66 77

Lengden på strengen over er 5; det krever imidlertid 6 byte i minnet. Bokstaver etter NUL-tegnet teller ikke lenger i tegnstrengen; de kan tilhøre en ny streng eller bare være ubrukt. En tegnstreng i C er en matrise av typen char , hvor tegnstrengen inneholder et nulltegn som sluttidentifikator. Det er grunnen til at slike tegnstrenger også kalles null- terminert , et eldre begrep er ASCIIZ-streng eller C-streng . Siden selve nulltegnet også krever lagringsplass som tegnstrengen opptar, er minnekravet til en tegnstreng alltid minst 1 tegn større enn den brukbare lengden på tegnstrengen. Lengden på tegnstrengen er antall tegn før sluttidentifikatoren. Det bestemmes av C-funksjonen strlen().

Fordelen med denne metoden er at lengden på en streng bare er begrenset av tilgjengelig minne og ikke i tillegg av kapasiteten til lengdefeltet ; en ulempe er at den ikke kan inneholde null tegn, og at den er relativt vanskelig og ineffektiv å bruke; for eksempel kan lengden på en slik streng bare bestemmes ved å telle tegnene.

Representasjon med en egen lengdespesifikasjon

Lengden kan også lagres separat foran innholdet i tegnstrengen. På denne måten brukes ingen tegn som en avgrenser som da ikke lenger kan være en del av en tegnstreng.

tolkning lengde F. R. EN. N K k 0 f w
Numeriske verdier 00 00 00 05 46 52 41 4E 4B 6B 30. 66 77

Strenger som lagres på denne måten, kan ikke overstige en viss lengde. De fleste moderne programmeringsspråk som bruker en lengdespesifikasjon, gir minst 32 bits for lengden; ofte er lengdefeltet så stort som en peker . Avhengig av detaljene kan tegnstrenger være mellom 2 og 4 GiB på 32-biters systemer og  så betydelig mer på 64-biters systemer at den teoretiske grensen aldri blir oppbrukt.

Oppbevaring i bassenget

Lagring av strenger tar mye lagringsplass og er en veldig vanlig oppgave. Derfor bruker mange programmeringsspråk på høyt nivå et spesielt styringssystem for å kunne designe dette så effektivt som mulig. Dette er imidlertid ikke tilgjengelig for programmereren av en applikasjon; Som regel er det ingen måte å få tilgang til denne administrasjonen direkte eller til og med å avgjøre om den er aktiv.

Alle tegnstrenger er lagret i et sentralt "basseng". Målet er at hver ønsket tegnstreng bare blir lagret en gang. Variabelen i applikasjonsprogrammet får bare et identifikasjonsnummer for å kunne få tilgang til tegnstrengen om nødvendig.

Administrasjonen bruker raskere og mer effektive metoder (vanligvis en hash-tabell ) for organisasjonen . Hver gang en tegnstreng skal lagres, kontrolleres det om en streng med samme innhold allerede er kjent. Hvis dette er tilfelle, returneres identifikasjonsnummeret til den eksisterende tegnstrengen; ellers må den opprettes igjen.

Hver gang en streng lagres, økes referansetelleren med en. Hvis det ikke lenger er behov for en tegnstreng på et punkt i programmet (fordi en underrutine er avsluttet og bokstavene den inneholder blir meningsløs, eller fordi en variabel mottar en annen verdi), rapporteres dette til administrasjonen og referansetelleren reduseres av en. Dette gjør det mulig å bestemme hvilke av de lagrede tegnstrengene som for øyeblikket brukes - hvis referansetelleren har verdien null, brukes den for øyeblikket ikke. Dette vil gjøre det mulig å omorganisere administrasjonen og slette unødvendige tegnstrenger ( søppelinnsamling ) hvis det er mangel på lagringsplass . Imidlertid unngås dette så langt som mulig fordi det kan skje at hver gang en subrutine kalles, blir de samme karakterstrengene omplassert igjen og igjen; Avansert administrasjon registrerer også lagringsfrekvensen og sletter bare lange strenger som sjelden brukes.

Hvis det er et programmeringsspråk der en kildetekst kompileres og resultatet lagres i en objektfil , blir de resulterende statiske tegnstrengene vanligvis gitt en lignende tabelladministrasjon i deres dataseksjon etter at alle forprosessoroperasjoner er løst. Imidlertid er det verken en sletting eller en referanseteller her. Disse bokstavene er heller ikke tilgjengelige for den sentrale tegnstrengadministrasjonen, siden det med dynamisk integrering ikke er sikret at denne dataseksjonen alltid er lastet.

Multibyte-tegn

Tradisjonelt ble 8 bits brukt til å representere et enkelt tegn, som tillater opptil 256 forskjellige tegn. Dette er ikke nok til å kunne behandle tegn fra mange fremmedspråk og fremfor alt ikke-latinske skrifter som gresk samtidig .

I mellomtiden tilbyr mange programmeringsspråk muligheten til å lagre et enkelt tegn i 2 byte eller 4 byte; følgelig unngår man ordbyte i denne sammenhengen i dag og snakker generelt om tegn .

Under Microsoft Windows er alle systemfunksjoner som bruker tegnstrenger tilgjengelig i en versjon med et suffiks A(for ANSI , betyr 1 byte i henhold til ISO 8859 ) og med et suffiks W(for bred , multibyte). Det er imidlertid lettere å ikke spesifisere dette eksplisitt: Hvis du kompilerer et program med det tilsvarende alternativet, byttes alle nøytrale funksjonsanrop automatisk til 1 byte / tegn eller til multibyte. Det er også forhåndsbehandlingsmakroer for programmeringsspråkene C ++ og C , ved hjelp av hvilke alle standardfunksjoner og bokstaver kan noteres i en ubestemt versjon i kildeteksten; Den aktuelle funksjonen blir deretter brukt under kompilering. Per definisjon behandler de historiske standardfunksjonene i C alltid nøyaktig 1 byte / tegn.

I mellomtiden koder mange programmeringsspråk tegnstrenger i UTF-16 , så bruk i utgangspunktet flere byte for ett tegn (vanligvis 2, men 4 byte for sjeldne tegn). For å spare plass og overføringstid i filer og under ekstern dataoverføring lagres eller overføres tegnstrenger i UTF-8 . Når du leser / skriver eller sender / mottar, foregår omkoding vanligvis.

En proprietær mellomform var i bruk på Microsoft- systemer på 1990-tallet under navnet Multibyte Character Set . Ulike formater og kodinger / dekoder ble brukt for å avhjelpe problemet med å måtte dekke asiatiske skript med 1 byte / tegn.

Grunnleggende operasjoner med strenger

De grunnleggende operasjonene med tegnstrenger, som forekommer i nesten alle programmeringsspråk, er lengde, kopiering, sammenligning, sammenkobling , dannelse av strenger, mønstergjenkjenning , søking etter understreng eller individuelle tegn.

I mange programmeringsspråk på høyt nivå brukes oppgaveoperatøren (for det meste =eller :=) til å kopiere tegnstrenger . I C utføres kopiering med standardfunksjonen strcpy()eller memcpy(). Hvor tidkrevende kopiering er, avhenger sterkt av representasjonen av karakterstrengene. I en metode med referanseteller består kopiering bare av å øke referansetelleren. I andre prosedyrer må tegnstrengen tilordnes og kopieres fullstendig.

Sammenligningen av strenger for like og ulik støttes av mange programmeringsspråk på høyt nivå med operatørene =eller <>eller !=. På noen språk, for eksempel Pascal, kan det også utføres en leksikografisk sammenligning med <og >. Hvis disse operatørene ikke er tilgjengelige, brukes funksjoner. Standardfunksjonen strcmp()i C har tre resultater: lik, større eller mindre. Det første tegnet har den høyeste verdien. Men det er også mer kompliserte sammenligningsfunksjoner som tar hensyn til store / små bokstaver, klassifisering av umlauts osv. Dette spiller en rolle når du søker i ordbøker og telefonbøker.

For sammenkobling er det operatører på mange programmeringsspråk som +( BASIC , Pascal , Python , Java , C ++ ), &( Ada , BASIC), .( Perl , PHP ), ..( Lua ) eller ||( REXX ). I C der for funksjonen strcat().

For å legge til en annen i en allerede eksisterende tegnstreng, gir noen språk sin egen operatør ( +=i Java og Python, ..i Perl og PHP). Vanligvis blir ikke operanden bare lagt til på slutten, men uttrykket gammelt + nytt blir evaluert og tildelt variabelen gammel , siden strenger vanligvis betraktes som uforanderlige; så det er bare en forkortet form. Imidlertid er det i mange moderne programmeringsspråk som Java , C-Sharp eller Visual Basic .NET såkalte strengbyggerklasser som representerer foranderlige strenger. Imidlertid kan strengen og strengbyggeren som regel ikke byttes ut, men må konverteres til hverandre.

Strenger som er notert direkte etter hverandre (med eller uten mellomrom ) sammenkobles implisitt på noen språk (C, C ++, Python, REXX).

Det er flere måter å få en delvis kjede på. En delstreng kan defineres tydelig ved å spesifisere ( tegnstreng , startindeks , sluttindeks ) eller ( tegnstreng , startindeks , lengde ). Denne operasjonen kalles hyppig substr(). Noen programmeringsspråk, for eksempel Python, tilbyr syntaktisk sukker for denne operasjonen (se eksempler).

PL / SQL

I Oracle er følgende grunnleggende operasjoner mulig i lagrede prosedyrer, funksjoner og PL / SQL-blokker:

DECLARE
 Text1 varchar2(30);
 Text2 varchar2(30);
 Text3 varchar2(61);
BEGIN
 Text1 := 'Frank';
 Text2 := 'Meier';
 Text3 := Text1 || ' ' || Text2
END;
/

GRUNNLEGGENDE

 text$ = "FRANK"
 text2$ = text$

Det etterfølgende dollartegnet indikerer at det er en strengvariabel. Siden en streng er avgrenset med anførselstegn, kan de bare integreres i strengen ved hjelp av Chr(34)eller CHR$(34)-funksjonen, 34 er ASCII-koden for anførselstegnet.

Flere strenger kan (avhengig av BASIC-dialekten) kobles til en ("sammenkoblet") med pluss tegnet eller med bokstavet "&":

 text2$ = "***" + text$ + "***"
 text2$ = "***" & text$ & "***"

C.

Dette C- programmet definerer to tegnstrengvariabler, som hver kan inneholde 5 tegn "nyttelast". Siden strengene avsluttes med et nulltegn, må matrisen ha seks tegn. Deretter kopieres teksten "FRANK" til begge variablene.

#include <string.h>

int main(void)
{
  char text1[6];
  char text2[6];

  strcpy(text1, "FRANK");
  strcpy(text2, text1);

  return 0;
}

Standardfunksjonen brukes til å feste to strenger til hverandre strcat(). Dette tildeler imidlertid ikke lagringsplassen som kreves for målstrengen. Dette må gjøres separat på forhånd.

#include <string.h>

int main(void)
{
  char puffer[128]; // Zielpuffer, der groß genug ist.

  strcpy(puffer, "FRANK");
  strcat(puffer, "ENSTEIN");

  return 0;
}

Java

String text1 = "FRANK";
String text2 = text1;

Strenger i Java er objekter i klassen String. De kan ikke lenger endres etter at de er opprettet. I eksemplet ovenfor representerer tekst1 og tekst2 det samme objektet.

Sammenslåingen av tegnstrenger utføres av operatøren (for dette tilfellet overbelastet) pluss:

String text1 = "FRANK";
String text2 = "ENSTEIN";
String ganzerName = text1 + text2;

Pascal

(Strengt tatt har følgende bare fungert siden Turbo Pascal , siden Pascal-språket som ble opprettet av Niklaus Wirth, bare visste fullpakket røye med røye , som var litt mer tungvint å bruke)

var vorname, nachname, name: string;
{… …}
vorname := 'FRANK';
nachname := 'MEIER';
name := vorname + ' ' +nachname;

PHP

I PHP er situasjonen lik Perl .

$text = "FRANK";

$text2 = $text; // $text2 ergibt "FRANK"

$text3 = <<<HEREDOC
Ich bin ein längerer Text mit Anführungszeichen wie " oder '
HEREDOC;

Tekster er sammenkoblet med et poeng.

$text = "FRANK";
$text = "FRANK" . "ENSTEIN"; // $text ergibt "FRANKENSTEIN"

$text = "FRANK";
$text .= "ENSTEIN"; // $text ergibt "FRANKENSTEIN"

Rexx

I Rexx er alt - inkludert tall - representert som en streng. Slik tildeles en strengverdi til en variabel: a = "Ottos Mops" Følgende uttrykk resulterer i verdien "Ottos Mops":

  • "Ottos" "Mops"
    (implisitt sammenkoblet; nøyaktig ett mellomrom settes automatisk inn)
  • "Ottos" || ' Mops'
    (eksplisitt sammenkoblet, ingen plass satt inn)
  • "Ottos"' Mops'
    (implisitt sammenkoblet ved å umiddelbart legge til en annen streng som er avgrenset av den andre avgrenseren)

Videre operasjoner

Bestem underlag

Anta at variabelen sinneholder strengen Ottos Mops hopst fort. Deretter kan det første tegnet ( O), de fem første tegnene ( Ottos), det syvende til det tiende ( Mops) og de siste fire ( fort) bestemmes som følger:

python

  • s[0]O
  • s[:5]eller s[0:5]eller s.split()[0]Otto
  • s[6:10]eller s.split()[1]mops
  • s[-4:]eller s.split()[-1]fortsett

Denne prosessen kalles kutting (fra "til skive" som betyr "kuttet i skiver" eller "delt opp"). Det første tegnet har indeksen 0.

Rexx

  • SubStr(s, 1, 1)eller Left(s, 1)O
  • Left(s, 4)eller Word(s, 1)Otto
  • SubStr(s, 7, 4)eller Word(s, 2)mops
  • Right(s, 4)eller Word(s, 4)fortsett

Rexx kan også behandle strenger ord for ord, der ord er atskilt med (hvilket som helst antall) mellomrom. Som med Pascal-strenger, har det første tegnet indeks 1.

  • PARSE VAR s A 2 1 O M F   ⇒ Variabler A, O, M, F inneholder 'O', 'Otto', 'Pug', 'fort'

Denne prosessen kalles tokenizing (fra engelsk "token" med betydningen "forkortelse" eller " spillbrikke " og betyr her for eksempel "brikke" eller "klump") og er også en standardfunksjon på andre språk.

PHP

  • substr($s, 0, 5)Otto
  • substr($s, 6, 4)mops
  • substr($s, -4)fortsett
  • ytterligere eksempler, se

BlitzBasic

  • Left(s, 5)Otto
  • Mid(s, 7, 4)mops
  • Right(s, 4)fortsett

Objekt Pascal

  • s[1]O
  • Copy(s, 1, 5)Otto
  • Copy(s, 7, 4)mops

Bruke StrUtils-enheten:

  • LeftStr(s, 5)Otto
  • MidStr(s, 7, 4)mops
  • RightStr(s, 4)fortsett

Algoritmer

Ulike algoritmer fungerer hovedsakelig med tegnstrenger:

I dag skriver en programmerer vanligvis ikke lenger denne typen algoritmer, men bruker konstruksjoner fra et språk eller biblioteksfunksjoner.

Bufferoverløp - strenger og datasikkerhet

Når strenger av tegn fra omverdenen blir overtatt i den interne representasjonen, bør det tas spesielle forholdsregler. I tillegg til uønskede kontrolltegn og formatering, må også maksimal lengde på tegnstrengen kontrolleres.

Eksempel: Et internasjonalt telefonnummer skal leses fra en fil. Den skal bare inneholde sifre og skilles fra adressen med et fanetegn (ASCII 9). En karakterstreng med fast lengde med 16 tegn er gitt for innspilling; dette er tilstrekkelig for alle gyldige telefonnumre. - Inndataene kan inneholde mellomrom eller bindestrek og gjøre telefonnummeret lengre. Selv om et mellomrom som ser like ut, følges ved et uhell i stedet for TAB, er resultatet mer enn 16 tegn.

Hvis dette ikke blir sjekket ved hjelp av passende kontroller, og hvis det er et passende svar, oppstår et bufferoverløp og muligens et krasj av programmet eller mystiske oppfølgingsfeil.

De vanligste angrepsvektorene på webservere inkluderer bufferoverløp. Det blir forsøkt å tilordne et innhold til en tegnstrengvariabel, hvis lengde overstiger lengden på variabelen som er reservert av kompilatoren i minnet. Dette vil overskrive andre nærliggende variabler i minnet. Hvis denne effekten utnyttes på en dyktig måte, kan et program som kjører på en server manipuleres og brukes til å angripe serveren. Men det er nok å krasje serverprogramvaren; Siden det skal beskytte nettverkstilkoblingen (" gateway "), river den feil et gap som etterlater en svakt sikret server forsvarsløs mot enhver manipulasjon.

Med mindre gyldigheten allerede er overvåket i et håndterbart miljø, bør tegnstrengoperasjoner bare utføres med funksjoner der maksimal lengde på tegnstrengen er sjekket. I C vil dette være funksjoner som B. strncpy(), snprintf()... (i stedet for strcpy(), sprintf()...).

Se også

Individuelle bevis

  1. Hvert enkelt tegn i hvert datasystem har en numerisk verdi (for det meste binær verdi), ifølge hvilken det kan sammenlignes med et annet tegn for å være lik, større eller mindre. For å bestemme duplikater i et sett med strenger, er alt som betyr noe likeverd. Imidlertid , hvis sammenligningsfunksjonen også gir resultatene større og mindre i henhold til reglene for en total ordre , kan duplikatdeteksjon gjøres mye mer effektivt med binære søk .
  2. På grunn av den synkende verdien av tegnene på økende adresse, sammenligne sammenligning operatører av ulike programmeringsspråk, samt C-funksjoner strcmp(), strncmp(), memcmp()hver maskin i stil med big endian .
  3. php.net - strenger i henhold til den offisielle PHP-manualen