Kapitel 8
Tekststrenge

Kurt Nørmark
Institut for Datalogi, Aalborg Universitet


Sammendrag
Forrige lektion Næste lektion
Stikord Referencer Indhold
I denne lektion studerer vi forskellige aspekter af tekststrenge.


Strenge og tekststrenge

Strenge og tekststrenge
Slide Indhold Stikord
Referencer 

Begrebet streng: En streng er en sekvens af data af samme type
Begrebet tekststreng: En tekststreng er en streng af datatypen tegn

  • Almen notation for tekststrenge:

    • "En tekststreng"

  • Den tomme streng

    • Strengen der ikke indeholder data

    • Strengen af længde 0 - den kortest mulige streng

    • Den tomme tekststreng noteres naturligt som ""

Tekststrenge spiller en vigtig rolle i de fleste programmer vi skriver


Tekststrenge i C

Tekststrenge og arrays
Slide Indhold Stikord
Referencer 

En tekststreng i C er et nulafsluttet array med elementtypen char.

En tekststreng i C er dermed af typen char *

Figur. En illustration af en nulafsluttet tekststreng i C

  • Det afsluttende nultegn kaldes en sentinel

    • Oversættes direkte som en 'vagt'

    • Eksplicit markering af afslutningen af tekststrengen

Figur. 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

Initialisering og assignment af tekststrenge
Slide Indhold Stikord
Referencer 

En tekststreng kan initialiseres på flere forskellige måder

Program: Forskellige initialiseringer af tekststrenge.
  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';   

Program: De fire streng initialiseringer i et helt C program - herunder udskrivninger af de fire tekststrenge.
#include <stdio.h>

int main(void) {

  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';     

  printf("%s\n%s\n%s\n%s\n", str_1, str_2, str_3, str_4);
  
  return 0;
}

Program: Output fra programmet.
Aalborg
Aalborg
Aalborg
Aalborg

Program: Tilsvarende forsøg på assignments til de fire tekststrenge.
#include <stdio.h>
#include <string.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'};


  /* Illegal assignment to array. The array name is constant */
  /* Implicite copying of characters do not take place in C. */
  str_2 = "Aalborg";

  /* Alternative: copy the characters yourself */
  strcpy(str_2, "Aalborg");


  /* Pointer assignment - OK */
  str_3 = "Aalborg";

  /* Char by char Assignment - OK, but tedious */
  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;
}

Ved initialisering via tekstkonstanter tilføjes nultegnet automatisk af compileren

Tekststrenge og pointere
Slide Indhold Stikord
Referencer 

En tekststreng opfattes i C som en pointer til det første tegn i et char array

Dette følger direkte af den generelle sammenhæng mellem arrays og pointere

Program: Et program der ved brug af pointere kopierer strengen "Aalborg" ind midt i en anden streng.
#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 pointers to target and source resp. */
  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;
}

Program: Output fra programmet.
--Aalborg

Program: Samme program med brug af strcpy.
#include <stdio.h>
#include <string.h>

int main(void) {
  char str_aal[] = "Aalborg";
  char str[14];
  int i;

  /* fill str with '-' */
  for(i = 0; i < 14; i++)
    str[i] = '-';

  strcpy(str + 2, str_aal);

  printf("%s\n", str);  
  
  return 0;
}

Program: Output fra programmet.
--Aalborg

I praksis anvendes strcpy eller strncpy fra string.h til kopiering af strenge

Kopiering af tekststreng - med håndkraft
Slide Indhold Stikord
Referencer 

En illustration af kopieringen foretaget i programmerne på forrige slide

Figur. En illustration af kopiering af en tekststreng - ved håndkraft med for-løkke.

Ændringer af tekststrenge
Slide Indhold Stikord
Referencer 

Tekststrenge, til hvilke der er allokeret plads i et array, kan ændres (muteres)

Tekststrenge, der i kildeprogrammet er angivet som en streng konstant og refereret af en pointer, kan ikke ændres

Program: Et program der ændrer det andet tegn i Aalborg fra 'a' til 'A'.
  char str_1[] = {'A', 'a', 'l', 'b', 'o', 'r', 'g', '\0'};
  *(str_1 + 1) = 'A';     // OK

  char str_2[8] = "Aalborg";
  *(str_2 + 1) = 'A';     // OK

  char *str_3 = "Aalborg";
  *(str_3 + 1) = 'A';     // Potentiel fejl. 
                          // Kan give segmentation fault under kørsel.

  char str_4[8];          // 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';     
  *(str_4 + 1) = 'A';

Program: Hele programmet der ændrer det andet tegn i Aalborg fra 'a' til 'A'.
#include <stdio.h>

int main(void) {

  char str_1[] = {'A', 'a', 'l', 'b', 'o', 'r', 'g', '\0'};
  *(str_1 + 1) = 'A';     // OK

  char str_2[8] = "Aalborg";
  *(str_2 + 1) = 'A';     // OK

  char *str_3 = "Aalborg";
  *(str_3 + 1) = 'A';     // Potentiel fejl. 
                          // Kan give segmentation fault under kørsel.

  char str_4[8];          // 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';     
  *(str_4 + 1) = 'A';

  printf("%s\n%s\n%s\n%s\n", str_1, str_2, str_3, str_4);
  
  return 0;
}

Opgave 8.2. Funktionen strrev

Strengomvending består i at bytte om på tegnene i en tekststreng, således at de første tegn ender med at være de sidste. Eksempelvis er strengomvendingen af "streng" lig med "gnerts".

Programmer funktionen strrev(char *str), som omvender tegnene i parameteren str. Bemærk at parameteren str både tjener som input og output parameter. Vi ønsker altså at bytte om på tegnene i det char array, som str peger på.

Tekststrenge i forhold til tegn
Slide Indhold Stikord
Referencer 

De to værdier 'a' og "a" er forskellige

  • 'a'

    • Et enkelt tegn af typen char

    • Heltallet 97

  • "a"

    • Et array med to elementer

    • Element nummer nul er tegnet 'a' og element nummer et er tegnet '\0'

Den tomme streng og NULL
Slide Indhold Stikord
Referencer 

Man skal kunne skelne mellem den tomme tesktstreng og en NULL pointer

NULL og "" er forskellige

  • NULL

    • NULL er en pointer værdi

    • NULL værdien bruges for en pointer, der ikke peger på en plads i lageret

    • Heltallet 0

  • Den tomme streng ""

    • Den tomme string "" er en streng værdi

    • "" er et array med ét element, nemlig '\0' tegnet


Leksikografisk ordning

Leksikografisk ordning af strenge
Slide Indhold Stikord
Referencer 

Ordningen af tegn giver anledning til en ordning af tegnstrenge (tekststrenge)

Den normale alfabetiske ordning af tekststrenge spiller en vigtig rolle ved opslag i leksika, telefonbøger, mv.

Vi vil her definere hvad det betyder af strengen s er mindre end strengen t

Notationen på denne slide er ikke C notation

  • Lad e betegne den tomme streng "" og lad s og t være to tekststrenge

  • s < t   hvis og kun hvis der findes tegn c og d samt to kortere strenge u og v

    • s = e
      t = c u     eller

    • s = c u
      t = d v

      • c < d

      • c = d og u < v

Lighed af strenge (1)
Slide Indhold Stikord
Referencer 

Der er to mulige fortolkninger af lighed af to strenge s og t

Figur. En illustration af reference lighed og strukturel lighed mellem char * variable

Lighed af strenge (2)
Slide Indhold Stikord
Referencer 

  • Pointerværdierne indeholdt i de to variable s og t er ens

    • s og t peger på det samme array af tegn

    • Hvis vi ændrer på tegnene i s ændres tegnene i t automatisk

    • Reference lighed

  • s og t udpeger forskellige arrays, med tegn der parvis er ens

    • Hvis vi ændrer på tegnene i s ændres intet i t

    • Strukturel lighed

Hvis to strenge er reference ens er de også strukturelt ens, men ikke nødvendigvis omvendt

Funktionen strcmp fra string.h
Slide Indhold Stikord
Referencer 

Functionen strcmp fra string.h implementerer den leksikografiske ordning samt strukturel lighed på tekststrenge i C

  • Tre mulige output af strcmp(str1,str2):

    • Positivt heltal:

      • str1 er leksikografisk større end str2

    • Nul:

      • str1 og str2 er strukturelt ens

    • Negativt heltal:

      • str1 er leksikografisk mindre end str2

Henvisning

Program: Et program der illustrerer den leksikografiske ordning af tekststrenge i C.
#include <stdio.h>
#include <string.h>

void pr(char*, char*, int);

int main(void) {

  int b1 = strcmp("book", "shelf");    
  int b2 = strcmp("shelf", "book");    
  int b3 = strcmp("","book");
  int b4 = strcmp("book","bookshelf"); 
  int b5 = strcmp("book", "book");
  int b6 = strcmp("7book", "book");
  int b7 = strcmp("BOOK", "book");

  pr("book", "shelf", b1);
  pr("shelf", "book", b2);
  pr("", "book", b3);
  pr("book", "bookshelf", b4);
  pr("book", "book", b5);
  pr("7book","book", b6);
  pr("BOOK", "book", b7);
  
  return 0;
}

void pr(char *s, char *t, int r){
 printf("strcmp(\"%s\",\"%s\") = %i\n", s,t,r);
}

Program: Output fra programmet.
strcmp("book","shelf") = -17
strcmp("shelf","book") = 17
strcmp("","book") = -98
strcmp("book","bookshelf") = -115
strcmp("book","book") = 0
strcmp("7book","book") = -43
strcmp("BOOK","book") = -32

Opgave 8.3. Din egen udgave af funktionen strcmp

Funktionen strcmp fra string.h sammenligner to tekststrenge med hinanden, som beskrevet på denne slide.

Programmer din egen rekursive udgave af strcmp. En rekursiv strcmp funktion programmeres uden brug af while eller for-løkker.


Tidligere eksempler

Konvertering mellem talsystemer
Slide Indhold Stikord
Referencer 

I en tidligere lektion har vi programmeret funktioner der konverterer tal mellem forskellige talsystemer

De involverede funktioner læste/skrev input/output med getchar og putchar

Det er mere alsidigt at skrive funktioner, der modtager eller returnerer tekststrenge

Henvisning

Program: En funktion der konverterer et tal n i base talsystemet (en streng) til et decimalt tal.
/* Convert the string n to a decimal number in base and return it.
   Assume that input string is without errors */
int to_decimal_number(char *n, int base){
  int ciffer_number, res = 0;
  char *ciffer_ptr = &n[0], ciffer = *ciffer_ptr;

  do {
    if (ciffer >= '0' && ciffer <= '9')
      ciffer_number = ciffer - '0';
    else if (ciffer >= 'a' && ciffer <= 'z')
      ciffer_number = ciffer - 'a' + 10;
    else ciffer_number = -1;   /* error */

    if (ciffer_number >= 0 && ciffer_number < base)
      res = res * base + ciffer_number;

    ciffer_ptr++; ciffer = *ciffer_ptr;
  }
  while (ciffer != '\0');

  return res;
}   

Program: Hele programmet.
#include <stdio.h>
#include <stdlib.h>

int read_in_base(int);

int main(void) {
  int i, n, base;
  char *the_number[20];

  for (i = 1; i <= 5; i++){
    printf("Enter number base (a decimal number)"
           "and a number in that base: ");
    scanf("%d %s", &base, the_number); 
    printf("The decimal number is: %d\n",
            to_decimal_number(the_number, base));
  }
  
  return 0;
}

/* Convert the string n to a decimal number in base and return it.
   Assume that input string is without errors */
int to_decimal_number(char *n, int base){
  int ciffer_number, res = 0;
  char *ciffer_ptr = &n[0], ciffer = *ciffer_ptr;

  do {
    if (ciffer >= '0' && ciffer <= '9')
      ciffer_number = ciffer - '0';
    else if (ciffer >= 'a' && ciffer <= 'z')
      ciffer_number = ciffer - 'a' + 10;
    else ciffer_number = -1;   /* error */

    if (ciffer_number >= 0 && ciffer_number < base)
      res = res * base + ciffer_number;

    ciffer_ptr++; ciffer = *ciffer_ptr;
  }
  while (ciffer != '\0');

  return res;
}   

Udskrivning af enumeration konstanter
Slide Indhold Stikord
Referencer 

I en tidligere lektion har vi programmeret funktioner der udskriver navnene på enumeration konstanter

De involverede funktioner skrev output med printf

Det er mere alsidigt at skrive funktioner der returnerer tekststrenge

Henvisning

Program: En funktion som returnerer en symbolsk ugedag (en streng) givet dagens nummer.
/* Return the symbolic name of day d */
char *print_name_of_day(days  d){
  char *result;
  switch (d) {
    case sunday: result = "Sunday";
       break;
    case monday: result = "Monday";
       break;
    case tuesday: result = "Tuesday";
       break;
    case wednesday: result = "Wednesday";
       break;
    case thursday: result = "Thursday";
       break;
    case friday: result = "Friday";
       break;
    case saturday: result = "Saturday";
       break;
  }
  return result;
}  

Program: Hele programmet.
#include <stdio.h>

enum days {sunday, monday, tuesday, wednesday, thursday, 
           friday, saturday};
typedef enum days days;

days  next_day_of(days  d){
  return ( days ) (((int) d + 1) % 7);
}  

/* Return the symbolic name of day d */
char *print_name_of_day(days  d){
  char *result;
  switch (d) {
    case sunday: result = "Sunday";
       break;
    case monday: result = "Monday";
       break;
    case tuesday: result = "Tuesday";
       break;
    case wednesday: result = "Wednesday";
       break;
    case thursday: result = "Thursday";
       break;
    case friday: result = "Friday";
       break;
    case saturday: result = "Saturday";
       break;
  }
  return result;
}     

int main(void){
  
  days  day1 = saturday,  another_day;
  int i;

  printf("Day1 is %d\n", day1);

  printf("Day1 is also %s\n", print_name_of_day(day1));

  another_day = day1;
  for(i = 1; i <= 3; i++)
    another_day = next_day_of(another_day);
  
  printf("Three days after day1: %s", 
          print_name_of_day(another_day));
  printf("\n");

  return 0;
}    


Biblioteket string.h

Oversigt
Slide Indhold Stikord
Referencer 

  • char *strcat(char *s1, const char *s2);

    • Sammensætter s1 og s2 i bagenden af s1. Nultegnet i s1 overskrives.

    • Nyt nultegn indsættes efter kopi af s2. Kræver plads nok i s1. Returnerer s1.

  • char *strcpy(char *s1, const char *s2);

    • Kopierer s2 ind i starten af s1, inklusive 0 tegnet.

    • Kræver plads nok i s1. Returnerer s1.

  • char *strncpy(char *s1, const char *s2, size_t n);

    • Kopierer n tegn (eller indtil nultegn) fra s2 ind i starten af s1. Nultegnet fra s2 kopieres ikke.

    • Fylder om nødvendigt op med nultegn, så der ialt kopieres netop n tegn.

  • char *strchr(const char *s, int c);

    • Returnerer pointer til første forekomst af c i s. Ellers NULL.

  • char *strstr(const char *s1, const char *s2);

    • Returnerer en pointer til den første forekomst af s2 i s1. Ellers NULL.

  • size_t strlen(const char *s);

    • Returnerer antallet af tegn i s - nultegnet tæller ikke med.

  • int strcmp(const char *s1, const char *s2);

    • Leksikografisk sammenligning af s1 og s2. Negativ, nul, eller positiv returværdi.

Ligesom de andre standardbibliotekter er string.h beskrevet i appendix B af Problem Solving and Program Design in C

Sammensætning af tekststrenge - illustration
Slide Indhold Stikord
Referencer 

Figur. En illustration af strcat

Sammensætning af tekststrenge
Slide Indhold Stikord
Referencer 

char *strcat(char *s1, const char *s2)

Funktionen strcat indsætter strengen s2 i bagenden af en anden streng s1 forudsat der er plads efter nultegnet

Program: Et program der illustrerer strcat og strlen.
#include <stdio.h>
#include <string.h>

int main(void) {

  char s[25] = "Aalborg";  
  char t[] = "University";
  char *res;

  res = strcat(strcat(s," "),t);
  printf("%s: %i chars\n", res, strlen(s));
  
  return 0;
}

Program: Output fra programmet.
Aalborg University: 18 chars

Kopiering af tekststrenge - illustration
Slide Indhold Stikord
Referencer 

Figur. En illustration af strncpy

Kopiering af tekststrenge
Slide Indhold Stikord
Referencer 

Figur. En illustration af strncpy

Kopiering af tekststrenge
Slide Indhold Stikord
Referencer 

char *strcpy(char *s1, const char *s2)

Funktionen strcpy kopierer en tekststreng s2 ind i et char array s1, til og med det afsluttende 0-tegn

strcpy antager at der er plads nok i arrayet - hvis ikke overskrives nabo celler i lageret

Program: Et program der illustrerer strcat og strlen.
#include <stdio.h>
#include <string.h>

int main(void) {

  char source[] = "Aalborg";  
  char target_1[8], target_2[5];

  strcpy(target_1, source);         // Enough space in target_1.
  printf("%s: %i chars\n", target_1, strlen(target_1));

  strcpy(target_2, source);         // Insufficient space in target_2. Very problematic.
  printf("%s: %i chars\n", target_2, strlen(target_2));
  
  return 0;
}

Program: Output fra programmet.
Aalborg: 7 chars
Aalborg: 7 chars

En alternativ funktion til strcpy
Slide Indhold Stikord
Referencer 

Som de fleste andre funktioner i string.h allokerers der ikke lager i strcpy

Her vil vi programmere en streng-kopierings funktion der allokerer plads til en ny kopi

Program: Et funktioner der allokerer plads til og kopierer en streng.
/* Copy s to a fresh allocated string and return it */
char *string_copy(const char *s){
  char *new_str;

  new_str = (char *)malloc(strlen(s)+1);
  if (new_str == NULL){
    printf("Cannot copy string.\n");
    exit(EXIT_FAILURE);
  }
  strcpy(new_str,s);

  return new_str;
}  

Program: Hele programmet.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


/* Copy s to a fresh allocated string and return it */
char *string_copy(const char *s){
  char *new_str;

  new_str = (char *)malloc(strlen(s)+1);
  if (new_str == NULL){
    printf("Cannot copy string.\n");
    exit(EXIT_FAILURE);
  }
  strcpy(new_str,s);

  return new_str;
}  


int main(void) {
  char s[] = "Aalborg University", *t;

  t = string_copy(s);

  strcpy(s,"---");      /* destroy s */
  printf("The destroyed original is: %s.\nThe copy is: %s\n", s, t);
  free(t);
  return 0;
}

Program: Output fra programmet.
The destroyed original is: ---.
The copy is: Aalborg University 

Illustration af strncpy (1) - illustration
Slide Indhold Stikord
Referencer 

Figur. En illustration af strncpy

Illustration af strncpy (2) - illustration
Slide Indhold Stikord
Referencer 

Figur. En illustration af strncpy

Substring ved brug af strncpy
Slide Indhold Stikord
Referencer 

char *strncpy(char *s1, const char *s2, size_t n)

strncpy kan bruges til at udtrække en substreng s1 af en anden streng s2

Program: Et program der udtrækker en substreng af en streng. Det er essentielt at target initialiseres med nultegn, idet det viser sig, at strncpy ikke overfører et nultegn.
#include <stdio.h>
#include <string.h>
#define LEN 25

int main(void) {

  char str[] = "The Aalborg University first year of studies";
  char target[LEN];
  int i; 

  strncpy(target, str+4, 18);
  target[18] = '\0';

  printf("The substring is: %s\nLength: %i\n",
          target, strlen(target));
  
  return 0;
}

Program: Output fra programmet.
The substring is: Aalborg University
Length: 18

Lokalisering af et tegn i en streng - illustration
Slide Indhold Stikord
Referencer 

Figur. En illustration af strchr

Lokalisering af en delstreng i en streng - illustration
Slide Indhold Stikord
Referencer 

Figur. En illustration af strstr

Lokalisering af en delstreng i en streng
Slide Indhold Stikord
Referencer 

char *strstr(const char *s1, const char *s2)

Funktionen strstr lokaliserer en mulig delstreng s2 (eksklusiv nultegnet) i en anden streng s1

Program: Et program der leder efter en delstreng af en streng.
#include <stdio.h>
#include <string.h>

int main(void) {

  char str[] = "The Aalborg University first year of studies",
       *search_result;

  search_result = strstr(str, "University");

  printf("We located: %s\nLength: %i\n",
          search_result, strlen(search_result));
  
  return 0;
}

Program: Output fra programmet.
We located: University first year of studies
Length: 32


Andre emner om tekststrenge

Arrays af tekststrenge
Slide Indhold Stikord
Referencer 

Et array af tekststrenge kan enten forstås som en to dimensionel char tabel eller som en pointer til en char pointer

Program: Et program der allokerer og tilgår et array af tre tekststrenge.
  char *numbers[] = {"one", "two", "three"};
  char ch1, ch2, ch3, ch4;

  ch1 = **numbers;
  ch2 = numbers[0][0];
  ch3 = *(*(numbers+1) + 1);
  ch4 = numbers[2][2];  

Figur. En illustration af variablen numbers fra ovenstående program

Program: Hele programmet.
#include <stdio.h>

int main(void) {

  char *numbers[] = {"one", "two", "three"};
  char ch1, ch2, ch3, ch4;

  ch1 = **numbers;
  ch2 = numbers[0][0];
  ch3 = *(*(numbers+1) + 1);
  ch4 = numbers[2][2];  

  printf("ch1 = %c, ch2 = %c, ch3 = %c, ch4 = %c\n", ch1, ch2, ch3, ch4);
  
  return 0;
}

Program: Output fra programmet.
ch1 = o, ch2 = o, ch3 = w, ch4 = r

Variablen numbers kunne alternativt erklæres og initialiseres som char numbers[][6] = {"one", "two", "three"}

Program: Programmet med alternativ array erklæring.
#include <stdio.h>

int main(void) {

  /* char *numbers[] = {"one", "two", "three"}; */
  char numbers[][6] = {"one", "two", "three"};
  char ch1, ch2, ch3, ch4;
  int i;

  ch1 = **numbers;
  ch2 = numbers[0][0];
  ch3 = *(*(numbers+1) + 1);
  ch4 = numbers[2][2];  

  printf("ch1 = %c, ch2 = %c, ch3 = %c, ch4 = %c\n", ch1, ch2, ch3, ch4);

  /* Printing 18 characters */
  for(i=0; i < 18; i++)
    printf("%c", *(&numbers[0][0] + i));
  printf("\n");

  /* Printing 3 strings */
  for(i=0; i < 3; i++)
    printf("%s", numbers[i]);

  printf("\n");
  return 0;
}

Program: Output fra det alternative program (0 tegn ændret til N, ? er ukendt værdi).
ch1 = o, ch2 = o, ch3 = w, ch4 = r
oneN??twoN??threeN
onetwothree

Input og output af tekststrenge
Slide Indhold Stikord
Referencer 

Input af teststrenge med scanf har specielle regler

Output af tekststrenge med printf virker som forventet

Program: Et program der indlæser og udskriver en tekststreng med scanf og printf.
// Source file: string-input.c.  Read a string with spaces.
#include <stdio.h>
#include <string.h>

int main(void) {
  char input[100];

  do {
    printf("Enter a string: ");
    scanf("%s", input);
    printf("You entered \"%s\"\n", input);
  }  while (strcmp(input, "exit"));
  
  return 0;
}

Program: Et program der indlæser en line af tekst med gets.
// Source file: string-input-gets.c
#include <stdio.h>
#include <string.h>
#define LIMIT 20

int main(void) {
  char input[LIMIT];

  do {
    printf("Enter a string: ");

    gets(input);                            // Dangerous if the input entered 
                                            // is longer than LIMIT
    printf("You entered \"%s\"\n", input);
  }  while (strcmp(input, "exit"));
  
  return 0;
}

Funktionen gets læser en linie fra standard input og gemmer det i s.

En lang linie vil kunne forårsage overflow i s   -   brug fgets i stedet for.

Programparametre
Slide Indhold Stikord
Referencer 

Operativsystemet overfører et array af strenge til main funktionen med information om, hvordan programmet er kaldt

Dette giver muligheder for at overføre programparametre som tekststrenge

Program: Et program der udskriver de overførte programparametre.
/* Echo the command line arguments. */

#include <stdio.h>

int main(int argc, char *argv[]){
   int   i;

   printf("\n  argc = %d\n\n", argc);

   for (i = 0; i < argc; ++i)
      printf("   argv[%d] = %s\n", i, argv[i]);

   return 0;
}

Program: Oversættelse og kørsel af programmet.
> gcc prog-pars.c -o prog-pars
> ./prog-pars Imperative Programming

  argc = 3

   argv[0] = ./prog-pars
   argv[1] = Imperative
   argv[2] = Programming

Konvertering mellem strenge og tal
Slide Indhold Stikord
Referencer 

Det er ofte nødvendigt at kunne konvertere en streng til et tal, og omvendt

  • Konvertering af en streng til et tal

    • Funktionerne atof, atoi, atol alle fra stdlib.h

    • Alternativt kan man læse fra en tekststreng med sscanf

  • Konvertering af et tal til en streng

    • Funktionerne ftoa, itoa, og ltoa er ikke standard funktioner i C

    • Det anbefales at bruge funktionen sprintf fra stdio.h

Program: Eksempel på konvertering af tekststrenge til tal, og fra tal til tesktstrenge - med atoi/atof/atol og sprintf.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20

int main(void) {

  /* Strings to numbers: */
  int     i = atoi("1234");
  double  d = atof("123.456");
  long    l = atol("12345678");

  char s1[MAX], s2[MAX], s3[MAX];

  printf("i = %i, d = %f, l = %li.\n",
         i, d, l);
  
  /* Numbers to strings: */
  sprintf(s1, "%i",  i);
  sprintf(s2, "%f",  d);
  sprintf(s3, "%li", l);

  printf("s1 = %s, s2 = %s, s3 = %s.\n",
         s1, s2, s3);

  return 0;
}

Henvisning

Program: Program output.
i = 1234, d = 123.456000, l = 12345678.
s1 = 1234, s2 = 123.456000, s3 = 12345678.

Program: Eksempel på konvertering af tekststrenge til tal, og fra tal til tesktstrenge - med sscanf og sprintf.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20

int main(void) {
  int i;
  double d;
  long l;

  char s1[MAX], s2[MAX], s3[MAX];

  /* Strings to numbers med sscanf: */
  sscanf("1234",     "%d",  &i);
  sscanf("123.456",  "%lf", &d);
  sscanf("12345678", "%li", &l);

  printf("i = %i, d = %f, l = %li.\n",
         i, d, l);
  
  /* Numbers to strings: */
  sprintf(s1, "%i",  i);
  sprintf(s2, "%f",  d);
  sprintf(s3, "%li", l);

  printf("s1 = %s, s2 = %s, s3 = %s.\n",
         s1, s2, s3);

  return 0;
}

Program: Program output.
i = 1234, d = 123.456000, l = 12345678.
s1 = 1234, s2 = 123.456000, s3 = 12345678.

Opgaver
Slide Indhold Stikord
Referencer 

Opgave 8.5. Flertals navneord

Skriv et program som oversætter udvalgte engelske navneord fra ental til flertal. Følgende regler skal følges:

  1. Hvis et navneord ender i et "y" fjernes "y" og der tilføjes "ies".
  2. Hvis et navneord ender i et "s", "ch" eller "sh" tilføjes et "es".
  3. I alle andre tilfælde tilføjes et "s" til navneordet

Udskriv hvert navneord i både ental og flertal.

Afprøv dit program på følgende engelske navneord:

  • chair dairy boss circus fly dog church clue dish

Denne opgave svarer til opgave 5 side 532 i 6. udgave af lærebogen

Opgave 8.5. Længste fælles endelse af to ord

Skriv et program med en funktion der finder og returnerer det længste fælles endelse (suffix) af to ord.

Funktionen skal have tre parametre. De to ord (to tekststrenge) skal overføres som input parametre. Den længste fælles endelse skal returneres i en output parameter (en tekststreng). (Hvordan markerer du forskellen på en input parameter og en output parameter, som begge er tekststrenge?) Funktionen skal dynamisk allokere plads til tekststrengen med den længste fælles endelse inden den returneres (brug malloc).

Eksempelvis er "logi" den længste fælles endelse af ordene "datalogi" og "biologi". Og den længste fælles endelse af "program" og "diagram" er "gram".


Samlede referencer
Indhold Stikord
Tidligere program der genererer ASCII tegntabel
Tidligere programmer
Tidligere program
printf familien i IO lektionen

 

Kapitel 8: Tekststrenge
Kursets hjemmeside     Forfatteren's hjemmeside     Om frembringelsen af disse sider     Forrige lektion (top)     Næste lektion (top)     Forrige lektion (bund)     Næste lektion (bund)     
Genereret: 6. november 2012, 16:27:43