![]() ![]() ![]() | Tekststrenge |
Denne lektionen er om tekststrenge, som både har berøringspunkter med arrays og pointers. Programmering med tekststrenge er vigtig i enhver form for tekstbehandling. Lektionen udspænder kapitel 27 - kapitel 31.
27.1. Strenge og tekststrenge
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Vi starter forholdsvis generelt med at definere strenge og tekststrenge.
|
I de fleste programmeringssprog noteres tekststrenge ved brug af dobbelte anførselstegn. Dermed adskiller strenge sig fra tegn (se afsnit 16.3) der i mange sprog noteres ved enkelte anførselstegn. Se endvidere afsnit 27.6.
|
27.2. Tekststrenge og arrays
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Efter den korte, generelle introduktion til tekststrenge i afsnit 27.1 ser vi nu konkret på tekststrenge i C. Den vigtigste detalje er konventionen om, at der skal bruges et særligt tegn, nultegnet, for at afslutte en tekststreng. Nultegnet er det tegn i ASCII alfabetet (afsnit 16.1 og program 16.2) som har talværdien 0. Det er med andre ord det første tegn i tabellen.
En tekststreng i C er et nulafsluttet array med elementtypen char. |
I figur 27.1 herunder ser vi tekststrengen "Aalborg", som det repræsenteres i et array. Læg mærke til tegnet i position 7: nul tegnet. Uden dette tegn ved vi ikke hvor tekststrengen afsluttes i lageret.
Figur 27.1 En illustration af en nulafsluttet tekststreng i C |
|
Herunder, i figur 27.2 viser vi tekststrengen "Aalborg" placeret midt i et array. Med en char pointer som peger på celle 2 i tabellen har vi stadig fat i "Aalborg".
Figur 27.2 En tekststreng som er placeret 'i midten' af et array of char |
En tekststreng i C skal ikke nødvendigvis udfylde hele det omkringliggende array |
27.3. Initialisering af tekststrenge
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Der er flere forskellige måder at initialisere en tekststreng. Herunder, i program 27.1 viser vi essentielt tre forskellige. Bemærk at de tre første initialiseringer foregår som en del af erklæringen af hhv. str_1, str_2 og str_3.
Den røde måde benytter manifest array notation, som blev diskuteret i program 21.3 i afsnit 21.2.
Den blå og den lilla måde er overfladisk set sammenfaldende. Her benytter vi en strengkonstant i dobbeltquotes, som diskuteret i afsnit 27.1. Den blå måde bruger en array variabel, og den lilla en pointervariabel. I den blå måde, hvor vi initialiserer str_2 sker der en implicit kopiering af tegn fra tekststrengen "Aalborg" over i arrayet. I afsnit 27.5 diskuterer vi nogle vigtige forskelle mellem den blå og lilla form, hvad angår mulighederne for efterfølgende ændringer (mutation) af tegn i strengene.
Med den brune måde indsætter vi enkelttegn i et array pr. assignment.
Læg mærke til at den røde og brune måde kræver eksplicit indsættelse af nultegnet. Nultegnet skal ikke indsættes eller noteres eksplicit, når vi bruger strengkonstanter.
1 2 3 4 5 6 7 8 9 10 | char str_1[] = {'A', 'a', 'l', 'b', 'o', 'r', 'g', '\0'}; char str_2[] = "Aalborg"; char *str_3 = "Aalborg"; char str_4[8]; str_4[0] = 'A'; str_4[1] = 'a'; str_4[2] = 'l'; str_4[3] = 'b'; str_4[4] = 'o'; str_4[5] = 'r'; str_4[6] = 'g'; str_4[7] = '\0'; | |||
|
Vi skriver endnu et program, som ligner program 27.1. I program program 27.2 gennemfører vi assignments i stedet for initialiseringer. De første to assignments, på det røde og blå sted, er ulovlige. Den første bruger en initializer, som kun må anvendes i erklæringer. Den anden forsøger at assigne en tekstreng (som er konstant tekststreng i programmet) til en array variabel str_2. Dette er ulovlig, idet str_2 er konstant (kan ikke assignes). Ydermere vil der ikke - bag ryggen på programmøren - blive kopieret tegn fra den konstante tekststreng til str_2 arrayet. Det lilla assignment af str_3 er lovlig, men bemærk, at der er tale om en pointer assignment. De brune assignments til str_4 elementerne er naturligvis også OK.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #include <stdio.h> int main(void) { char str_1[8], str_2[8], *str_3, str_4[8]; /* Ulovlig brug af initializer */ str_1 = {'A', 'a', 'l', 'b', 'o', 'r', 'g', '\0'}; /* Ulovlig assignment til array navn. Implicit kopiering finder ikke sted */ str_2 = "Aalborg"; /* Alternativ: kopier tegnene selv */ strcpy(str_2, "Aalborg"); /* Pointer assignment - OK */ str_3 = "Aalborg"; /* Tegnvis assignment - OK */ str_4[0] = 'A'; str_4[1] = 'a'; str_4[2] = 'l'; str_4[3] = 'b'; str_4[4] = 'o'; str_4[5] = 'r'; str_4[6] = 'g'; str_4[7] = '\0'; printf("%s\n%s\n%s\n%s\n", str_1, str_2, str_3, str_4); return 0; } | |||
|
27.4. Tekststrenge og pointere
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Vi skal nu se på forholdet mellem tekststrenge og pointere. I bund og grund er dette forhold afledt af at en tekststreng er et array (afsnit 27.2), og at et array er en pointer til det første element i arrayet (afsnit 24.1).
En tekststreng opfattes i C som en pointer til det første tegn Dette følger direkte af den generelle sammenhæng mellem arrays og pointere |
Herunder, i program 27.3 ser vi et eksempel på et program, der tilgår tekststrenge via pointere. Overordnet set kopierer programmet tegnene i "Aalborg" ind midt i strengen str.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include <stdio.h> int main(void) { char str_aal[] = "Aalborg"; char str[14]; char *str_1, *str_2; int i; /* fill str with '-' */ for(i = 0; i < 14; i++) str[i] = '-'; /* let str_1 and str_2 be running pointers */ str_1 = str; str_2 = str_aal; /* copy str_all into the middle of str */ str_1 += 2; for( ; *str_2 != '\0'; str_1++, str_2++) *str_1 = *str_2; /* terminate str */ *str_1 = '\0'; printf("%s\n", str); return 0; } | |||
|
Lad os forklare programmet i lidt større detalje. I starten af main ser vi to variable str_all og str, som er strenge. Vi initialiserer str_all til "Aalborg". str initialiseres i den første forløkke til udelukkende at indeholde tegnene '-'.
Dernæst assignes str_1 og str_2 til pointere til de første tegn i hhv. str og str_all. Med rødt ser vi at str_1 føres to positioner frem i arrayet med '-' tegn. Dernæst kommer en forløkke, som kopierer tegnene i str_all over i str. Dette sker gennem de pointere vi har sat op til at gennemløbe disse arrays. Før vi udskriver str med printf indsætter vi eksplicit et '\0' tegn i str.
Herunder, i program 27.4 ser vi outputtet fra program 27.3.
1 | --Aalborg | |||
|
27.5. Ændringer af tekststrenge
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Vi arbejder i dette afsnit videre på program 27.1. Det er vores mål at forklare under hvilke omstændigher vi kan ændre i de tekststrenge, som indgår i program 27.1.
Tekststrenge, til hvilke der er allokeret plads i et array, kan ændres (muteres) Tekststrenge, der er angivet som en strengkonstant refereret af en pointer, kan ikke ændres |
Mutation er et biologisk inspireret ord, som betyder at ændre (i en del af) noget. Ordet benyttes ofte når vi foretager ændringer i en del af en eksisterende datastruktur, eksempelvis et array.
Vores pointe bliver illustreret i program 27.5. Svarende til de farvede aspekter i program 27.1 foretager vi fire ændringer i strengen "Aalborg". Det er vigtigt at bide mærke i, at disse ændringer fortages i kommandoer, og sammen med erklæringerne af de benyttede variable.
Kun den lilla ændring giver problemer. str_3 peger på en tekststreng, der ikke er allokeret som et array i det program vi har skrevet. str_3 peger derimod på en konstant tekststreng, som er en del af programmet. Denne tekststreng er lagret sammen med programmet, på et sted vi ikke kan ændre i strengen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | char str_1[] = {'A', 'a', 'l', 'b', 'o', 'r', 'g', '\0'}; *(str_1 + 1) = 'A'; char str_2[8] = "Aalborg"; *(str_2 + 1) = 'A'; char *str_3 = "Aalborg"; *(str_3 + 1) = 'A'; /* Fejl. Segmentation fault under kørsel */ char str_4[8]; str_4[0] = 'A'; str_4[1] = 'a'; str_4[2] = 'l'; str_4[3] = 'b'; str_4[4] = 'o'; str_4[5] = 'r'; str_4[6] = 'g'; str_4[7] = '\0'; *(str_4 + 1) = 'A'; | |||
|
Moralen vi kan uddrage af ovenstående er at mutation af en tekststreng kræver at denne tekststreng er allokeret statisk (afsnit 26.1) eller dynamisk (afsnit 26.2) i programmet. Vi kan ikke ændre i konstante tekststrenge, der er angivet som en del af programmet, og til hvilke vi har etableret en pointer.
27.6. Tekststrenge i forhold til tegn
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Vi vil her påpege en væsentlig forskel mellem notationen for tegn og tekststrenge.
Tekststrenge er sammensat af tegn De to værdier 'a' og "a" meget forskellige |
Forskellen på notationen for tegn og tekststrenge kan eksemplificeres som følgende:
|
27.7. Den tomme streng og NULL
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
I lighed for forskellen på 'a' og "a" vil vi nu pege på forskellen mellem NULL og den tomme tekststreng.
Man skal kunne skelne mellem den tomme tesktstreng og en NULL pointer NULL og "" er meget forskellige |
NULL og den tomme streng kan karakteriseres som følger:
|