Kapitel 4
Tegn

Kurt Nørmark ©
Institut for Datalogi, Aalborg Universitet


Sammendrag
Forrige lektion Næste lektion
Stikord Referencer Indhold
I denne lektion ser vi på datatypen char, herunder læsning fra tastaturet (og filer) samt skrivning af tegn på skærmen (filer). Endvidere ser vi på en antal eksempler på programmering med tegn.


Tegn og alfabet

Alfabet
Slide Indhold Stikord
Referencer Lærebog 

Begrebet alfabet: Et alfabet er en ordnet mængde af bogstaver og andre tegn

  • ASCII alfabetet

    • American Standard Code for Information Interchange

    • Angiver tegnets placering i alfabetet ved at tildele tegnet en heltalsværdi

    • Det oprindelige ASCII tegnsæt indeholder 128 tegn

    • Det udvidede ASCII tegnsæt indeholder 256 tegn

      • De danske tegn 'æ', 'ø', 'å', 'Æ', 'Ø' og 'Å' er placeret i det udvidede ASCII tegnsæt

    • Appendix E side 609 i C by Dissection

I det seneste årti er der defineret mere omfattende alfabeter, som indeholder tegn fra mange forskellige kulturer.

Unicode er et sådant alfabet.

Henvisning

Datatypen char
Slide Indhold Stikord
Referencer Lærebog 

Datatypen char repræsenterer mængden af mulige tegn i et standard alfabet

  • Datatypen char

    • Et tegn repræsenteres i én byte, som svarer til otte bits

    • Otte bit tegn giver netop mulighed for at repræsentere tegnene det udvidede ASCII alfabet

    • Typen char er en heltalstype i C

Program: Et C program som udskriver en ASCII tegntabel.
#include <stdio.h>
#include <ctype.h>

int main(void) {
  int i;

  printf("\n");
  printf("%3s", "");           /* print top line above table */
  for (i = 0; i < 10; i++) 
    printf("%6d",i); 
  printf("\n");

  for (i = 0; i < 128; i++){   /* print the table */
    if (i % 10 == 0){          /* print leftmost column */
      printf("\n");
      printf("%3d", (i/10) * 10);    
    }
    if (isgraph(i))
      printf("%6c", i);
    else printf("%6s", "NP");
  }
  printf("\n\n");  

  return 0;
}

Program: Udskriften fra programmet.
        0     1     2     3     4     5     6     7     8     9

  0    NP    NP    NP    NP    NP    NP    NP    NP    NP    NP
 10    NP    NP    NP    NP    NP    NP    NP    NP    NP    NP
 20    NP    NP    NP    NP    NP    NP    NP    NP    NP    NP
 30    NP    NP    NP     !     "     #     $     %     &     '
 40     (     )     *     +     ,     -     .     /     0     1
 50     2     3     4     5     6     7     8     9     :     ;
 60     <     =     >     ?     @     A     B     C     D     E
 70     F     G     H     I     J     K     L     M     N     O
 80     P     Q     R     S     T     U     V     W     X     Y
 90     Z     [     \     ]     ^     _     `     a     b     c
100     d     e     f     g     h     i     j     k     l     m
110     n     o     p     q     r     s     t     u     v     w
120     x     y     z     {     |     }     ~    NP

Tegnkonstanter (1)
Slide Indhold Stikord
Referencer Lærebog 

Printbare værdier i typen char noteres i enkelt quotes, eksempelvis 'a'.

Det er vigtigt at kunne skelne mellem tegn, strenge og tal.

Eksempelvis '7', "7" og 7.

  • Andre mulige notationer for tegn:

    • Escape notation af ikke printbare tegn

      • Eksempler:      '\n'      '\t'      '\''      '\\'

    • Oktal escape notation

      • Eksempler:      '\12'      '\141'      '\156'

    • Hexadecimal escape notation

      • Eksempler:      '\xa'      '\x61'      '\x6e'

Tegnkonstanter (2)
Slide Indhold Stikord
Referencer Lærebog 

Vi ser på et program, hvori der forekommer en række tegnkonstanter.

Program: Et C program med eksempler på forskellige tegn konstanter. Programmet fokuserer på tegnet 'n', som noteres i normal tegnnotation, oktalt, og hexadecimalt.
#include <stdio.h>

int main(void) {

  char c = 'n', d = '\156', e = '\x6e';
  int  f = 110;
  char x = '\n';

  printf("c = %c (%d, %o, %x) \n",  c,c,c,c);
  printf("d = %c (%d, %o, %x) \12", d,d,d,d);
  printf("e = %c (%d, %o, %x) \xa", e,e,e,e);
  printf("f = %c (%d, %o, %x) \n",  f,f,f,f);

  printf("x = %c (%d, %o, %x) \n",  x,x,x,x);
  
  return 0;
}

Program: Output fra programmet.
c = n (110, 156, 6e) 
d = n (110, 156, 6e) 
e = n (110, 156, 6e) 
f = n (110, 156, 6e) 
x = 
 (10, 12, a) 

Oktale og hexadecimal notation (1)
Slide Indhold Stikord
Referencer Lærebog 

Hvad er oktal og hexadecimal tal notation?

Hvorfor er oktal og hexadecimal notation praktisk i forhold til normal decimal notation?

Figur. En illustration af binære, oktale og hexadecimale tal.

Oktal og hexadecimal tal notation tillader en ciffervis konvertering til binær notation

Oktale og hexedecimal notation (2)
Slide Indhold Stikord
Referencer Lærebog 

Eksempler på binære, oktale og hexadecimale talopløsninger

  • Binære tal: Grundtal 2

    • Eksempel:      14 = 1 · 23 + 1 · 22 + 1 · 21 + 0 · 20

  • Oktale tal: Grundtal 8

    • Eksempel:      14 = 1 · 81 + 6 · 80

  • Hexadecimale tal: Grundtal 16

    • Eksempel:      14 = 14 · 160 = e · 160

Senere i denne lektion vil vi programmere funktioner der kan konvertere mellem talsystemerne

Tegn aritmetik
Slide Indhold Stikord
Referencer Lærebog 

Det er muligt at udføre aritmetiske operationer på tegn - forstået som aritmetik på de underliggende ASCII værdier

  • Addition af et tal til et tegn

    • '0' + 7 == '7'

    • Tegnet 7 positioner længere fremme i tegntabellen

  • Subtraktion af et tal fra et tegn

    • 'k' - 1 == 'j'

    • Tegnet før k

  • Subtraktion af to tegn

    • 'a' - 'A'

    • Afstanden mellem små og store bogstaver

  • Sammenligning af to tegn

    • 'a' < 'b'

    • Tegnet a kommer før b. Vurdering af alfabetisk rækkefølge

Klassificering af tegn
Slide Indhold Stikord
Referencer Lærebog 

Biblioteket ctype.h understøtter en række abstraktioner, som klassificerer tegn

  • Tegn

    • Kontrol tegn     -     iscntrl(c)

    • Printbare tegn     -     isprint(c)

      • Blanke tegn     -     isspace(c)

      • Grafiske tegn     -     isgraph(c)

        • Punkt tegn     -     ispunct(c)

        • Alfanumeriske tegn     -     isalnum(c)

          • Alfabetiske tegn     -     isalpha(c)

            • Små bogstaver     -     islower(c)

            • Store bogstaver     -     isupper(c)

          • Numeriske tegn     -     isdigit(c)

Abstraktionerne getchar og putchar
Slide Indhold Stikord
Referencer Lærebog 

Abstraktionerne getchar og putchar giver mulighed for input og output af enkelttegn.

getchar og putchar er lavniveau alternativer til scanf og printf.

Som et eksempel på getchar ser vi på tegnvis indlæsning af heltal.

Program: En funktion der læser et heltal som enkelttegn - basal udgave.
int read_int(char *prompt){
  int res = 0;  char c;
  printf(prompt);

  while (isdigit(c = getchar()))
    res = res * 10 + (c - '0');

  return res;
}  

Program: Funktionen read_int og en main funktion som kalder read_int 5 gange.
#include <stdio.h>

int read_int(char*);

int main(void) {
  int i, n = 0;

  for (i = 1; i <= 5; i++){
    n = read_int("Enter an integer: ");
    printf("Decimal value: %d\n", n);
  }

  return 0;
}

int read_int(char *prompt){
  int res = 0;  char c;
  printf(prompt);

  while (isdigit(c = getchar()))
    res = res * 10 + (c - '0');

  return res;
}  

Program: En mere brugbar udgave med mulighed for fortegn og bedre linieafslutning.
#include <stdio.h>

int read_int(char*);

int main(void) {
  int i, n = 0;

  for (i = 1; i <= 5; i++){
    n = read_int("Enter an integer: ");
    printf("Decimal value: %d\n", n);
  }

  return 0;
}

int read_int(char *prompt){
  int res = 0;  char c; int sign = 1;
  printf(prompt);

  /* Handle initial sign, if any */
  c = getchar();
  if (c == '+') {sign = 1; c = getchar();}
  else if (c == '-') {sign = -1; c = getchar();}

  /* Read digits - first char is ready in c*/
  while (isdigit(c)){
    res = res * 10 + (c - '0');
    c = getchar();
  }

  /* read rest of line */
  while (c != '\n') c = getchar();

  return sign * res;
}  

Konvertering mellem talsystemer
Slide Indhold Stikord
Referencer Lærebog 

Vi vil nu se på et program, der indlæser et tal i et n talsystem, og som konverterer det til et decimalt tal.

Vi vil tilsvarende se på et program, der konverterer et decimalt tal til et tal i et andet talsystem.

Programmerne illustrerer tillige getchar og putchar.

Program: Et C program der omregner et tal fra et talsystem til titalsystemet og udskriver resultatet.
#include <stdio.h>
#include <stdlib.h>

int read_in_base(int);
void skip_rest_of_input_line (void);

int main(void) {
  int i, n, base;

  printf("THIS PROGRAM CONVERTS NUMBERS IN A" 
         "GIVEN BASE TO A DECIMAL NUMBER.\n\n");
  do {
    printf("Enter number base (0 terminates the program, max 36): ");
    scanf("%d", &base); skip_rest_of_input_line();
    if (base > 0){
      printf("Enter a non-negative number to be converted" 
             "to decimal notation: ");
      n = read_in_base(base);
      if (n >= 0)
        printf("The decimal number is: %d\n", n);
      else {
        printf("You have typed an illegal ciffer - TRY AGAIN\n"); 
        skip_rest_of_input_line();
      }
    }
  } while (base > 0);
  
  return 0;
}

/* Read a number in base and return the corresponding decimal number.
   Return -1 if erroneous input is encountered. */
int read_in_base(int base){
  int ciffer_number, res = 0, done = 0;
  char ciffer;

  do {
    ciffer = getchar();
    if (ciffer >= '0' && ciffer <= '9')
      ciffer_number = ciffer - '0';
    else if (ciffer >= 'a' && ciffer <= 'z')
      ciffer_number = ciffer - 'a' + 10;
    else if (ciffer == '\n')
      done = 1; 
    else return -1;

    if (ciffer_number >= 0 && ciffer_number < base){
      if (!done) res = res * base + ciffer_number;
    }
    else return -1;
  }
  while (!done);

  return res;
}     

void skip_rest_of_input_line (void){
  char c;

  c = getchar();
  while (c != '\n') c = getchar();
}

Program: Et C program der omregner et tal fra titalsystemet til et andet talsystem og udskriver resultatet.
#include <stdio.h>

void print_in_base(int, int);

int main(void) {
  int i, n, base;

  for (i = 1; i <= 5; i++){
    printf("Enter positive decimal number "
           "and number base (at least two): ");
    scanf(" %d %d", &n, &base);
    print_in_base(n, base); printf("\n");
  }
  
  return 0;
}

/* Convert the decimal number n to base and print the result */
void print_in_base(int n, int base){
  int ciffer;

  if (n > 0){
    ciffer = n % base;   /* find least significant ciffer */

    /* RECURSIVELY, find and print most significant ciffers */
    print_in_base(n / base, base);  

    /* print least significant ciffer */    
    if (ciffer >= 0 && ciffer <= 9)
      putchar('0' + ciffer);
    else if (ciffer >= 10 && ciffer <= 36)
      putchar('a' + ciffer - 10);
    else putchar('?');
  } 
}  

Eksempel: Kopiering af fil
Slide Indhold Stikord
Referencer Lærebog 

Det er meget simpelt at skrive et program som kopierer en fil til en anden fil.

Program: Et C program der kopierer input til output.
#include <stdio.h>

int main(void) {

  int c;

  while ((c = getchar()) != EOF)
    putchar(c);
  
  return 0;
}

Program: Oversættelse og udførelse af copy.c.
normark$ gcc -o copy-file copy.c
normark$ copy-file < copy.c > copy-of-copy.c

Eksempel: Optælling af ord
Slide Indhold Stikord
Referencer Lærebog 

Vi vil nu studere to udgaver af programmer der tæller ord mv.

Program: Bogens udgave af ordtællingsprogrammet - et uskønt program.
#include <ctype.h>
#include <stdio.h>

int found_next_word(void);

int main()
{
   int   word_cnt = 0;

   while (found_next_word() == 1)
      ++word_cnt;
   printf("\nNumber of words = %d\n\n", word_cnt);
   return 0;
}

int found_next_word(void)  
{
   int   c;

   while (isspace(c = getchar()))
      ;                /* skip white space */
   if (c != EOF) {     /* found a word */
      while ((c = getchar()) != EOF && !isspace(c))
       ;     /* skip all except EOF and white space */
      return 1;
   }
   return 0;
}  

Program: Kernighan og Ritchies's tilsvarende, men mere generelle program.
#include <stdio.h>

#define IN 1   /* inside a word */
#define OUT 0  /* outside a word */

int main(void) {
  int c, nl, nw, nc, state;

  state = OUT;
  nl = nw = nc = 0;
  while ((c = getchar()) != EOF) {
    ++nc;
    if (c == '\n')
      ++nl;
    if (c == ' ' || c == '\n' || c == '\t')
      state = OUT;
    else if (state == OUT) {   /* entering a word */
      state = IN;
      ++nw;
    }
  }

  printf("%d %d %d\n", nl, nw, nc);    
  
  return 0;
}


Samlede referencer
Indhold Stikord
Unicode tegntabeller

 

Kapitel 4: Tegn
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: 7. Juli 2010, 15:10:51