mercoledì 10 settembre 2008

Il tipo "char" nel linguaggio C

Che cosa sono le variabili di tipo char per il linguaggio di programmazione C e come si possono trattare elementarmente? E' interessante notare che ogni char altro non è che un numero intero, o almeno può essere rappresentato come intero decimale, ottale o esadecimale, numero che esprime la codifica ASCII dei caratteri della tastiera.
Per capire questo fatto notiamo che vi è una sostanziale differenza in C tra la scrittura 'A' e la scrittura "A". Infatti le singole virgolette si usano per indicare il carattere (nel senso di char) A che ha una sua codifica ASCII come numero intero. Al contrario "A" è una stringa, un array o un puntatore costituito da due elementi. Il carattere di stringa A e il carattere di terminazione di stringa \0 (che viene interpretato come zero).
Quindi 'A' ha un valore, come numero intero, decimale, ottale o esadecimale. La rappresentazione non ha importanza perchè i calcoli non dipendono dalla base in cui vengono eseguiti. Quindi con i caratteri si possono fare dei calcoli, come somme e sottrazioni. Se ad esempio si volesse sapere se un carattere digitato è una cifra si potrebbe usare il frammento di codice:

char c;
c = getchar(); /* il carattere viene acquisito dalla tastiera */
if( c>='0' && c<='9' ){
return 1;
} else {
return 0;
}

Questo ci fa notare come il carattere tra virgolette singole viene trattato come interi. Ovviamente questo codice funziona solo nel caso in cui, come nell'ASCII, le cifre sono codificate come numeri consecutivi. Anche le lettere minuscole e le maiuscole sono codificate con numeri interi consecutivi. Per completezza scriviamo un codice che permetta di stampare a video i caratteri ASCII (dal 0 al 127, ma con un banale cambio delle costanti FROM e TO si può cambiare il range).
#include<stdio.h>
#define FROM 0
#define TO 127

int main(){
/* Ciclo che mostra la codifica ascii di tutti i caratteri */
int k;
char c[128];
printf("Dec\t char\n");
for(k=FROM;k<TO;k++){
c[k]=k;
printf(" %d\t %c\n", c[k], c[k]);
}
return 0;
}

L'output (piuttosto lungo) è il seguente:
Dec      Char
0
1 ☺
2 ☻
3 ♥
4 ♦
5 ♣
6 ♠
7 /* Questo è il cicalino del computer */
8 /* Questo è lo spazio */
9 /* Questo è il carattere di tabulazione \t */
10 /* Qui c'è il carattere di newline \n */

11 ♂
12 ♀
13
14 ♫
15 ☼
16 ►
17 ◄
18 ↕
19 ‼
20 ¶
21 §
22 ▬
23 ↨
24 ↑
25 ↓
26 →
27 ←
28 ∟
29 ↔
30 ▲
31 ▼
32
33 !
34 "
35 #
36 $
37 %
38 &
39 '
40 (
41 )
42 *
43 +
44 ,
45 -
46 .
47 /
48 0
49 1
50 2
51 3
52 4
53 5
54 6
55 7
56 8
57 9
58 :
59 ;
60 <
61 =
62 >
63 ?
64 @
65 A
66 B
67 C
68 D
69 E
70 F
71 G
72 H
73 I
74 J
75 K
76 L
77 M
78 N
79 O
80 P
81 Q
82 R
83 S
84 T
85 U
86 V
87 W
88 X
89 Y
90 Z
91 [
92 \
93 ]
94 ^
95 _
96 `
97 a
98 b
99 c
100 d
101 e
102 f
103 g
104 h
105 i
106 j
107 k
108 l
109 m
110 n
111 o
112 p
113 q
114 r
115 s
116 t
117 u
118 v
119 w
120 x
121 y
122 z
123 {
124 |
125 }
126 ~
127 ⌂

Il seguente frammento di codice:
printf("0 decimale -> %d, 0 esadecimale -> %x, 0 carattere -> %c\n", '0', '0', '0');

mostra come, usando il carattere '0' e i comandi di formattazione %d, %x e %c si può scrivere il carattere '0' come intero decimale, esadecimale oppure come vero carattere. Infatti l'output è il seguente:
0 decimale -> 48, 0 esadecimale -> 30, 0 carattere -> 0

Notiamo come si possono fare operazioni come sottrazioni e somme tra i caratteri. Infatti il codice:
printf("'8'-'5' decimale -> %d, '8'-'5' esadecimale -> %x\n", '8'-'5', '8'-'5');

il cui output è:
'8'-'5' decimale -> 3, '8'-'5' esadecimale -> 3

che mostra l'indipendenza dell'operazione dalla rappresentazione scelta. Queste caratteristiche dei caratteri e della loro codifica permettono di scrivere agevolmente una funzione che converta un carattere maiuscolo (cioè con codifica compresa tra gli interi 65 e 90) nel corrispondente minuscolo (cioè con codifica compresa tra gli interi 97 e 122), usando il fatto che le minuscole sono separate dalle maiuscole della quantità 'a'-'A' e che quindi una minuscola si ottiene dalla maiuscola corrispondente aggiungendo tale quantità:
char tolowercase(char c);

char tolowercase(char c){
/* Se c è un carattere maiuscolo */
if( c>='A' && c<='Z' ){
return c + ('a' - 'A');
} else {
return c;
}
}

In modo analogo si ppotrebbe definire la funzione touppercase per convertire un carattere minuscolo in uno maiuscolo sottraendo laddove abbiamo aggiunto. Per oggi è tutto. A presto con altri approfondimenti sul fantastico mondo del linguaggio di programmazione C.

0 commenti: