I caratteri e le stringhe Il codice ASCII Il codice ASCII standard Il

Transcript

I caratteri e le stringhe Il codice ASCII Il codice ASCII standard Il
2
Il codice ASCII

I caratteri e le stringhe

Ver. 2.4


© 2010 - Claudio Fornaro - Corso di programmazione in C
Per memorizzare i simboli grafici
corrispondenti ai caratteri bisogna associare
un numero intero a ciascuno di essi
Il codice ASCII /’æski/ (American Standard
Code for Information Interchange) è una
tabella che elenca le corrispondenze tra
simboli grafici e numeri (es. A  65, B  66)
I numeri del Codice ASCII standard sono a 7
bit  27=128 caratteri diversi
Curiosità: il codice ASCII delle cifre 0-9 si può
ottenere dal corrispondente valore in BCD
facendolo precedere dal valore 011:
7 = 0111, 0110111 = 55 (codice ASCII di 7)
3
Il codice ASCII standard
127
123
122 z
97 a
96
91
90 Z
65 A
64
58
57 9
48 0
47
33
32
31
0
Altri caratteri
Lettere minuscole (a-z)
4
Il codice ASCII standard


Contiene i 95 caratteri di base
(es. non le lettere accentate)
Ha 4 sezioni importanti:
Altri caratteri

Lettere maiuscole (A-Z)


Altri caratteri
Cifre (0-9)


Altri caratteri
Carattere SPAZIO
Caratteri di controllo

Spazio (è il carattere visibile di codice più basso)
Cifre (0-9 in ordine crescente)
Maiuscole (A-Z in ordine cresc.)
Minuscole (a-z in ordine cresc.)
Le 4 sezioni sono separate
da altri caratteri generici
(punteggiatura, simboli matematici, ecc.)
Alcuni caratteri speciali (caratteri di controllo)
non vengono visualizzati, ma producono un
effetto (es. inserire un ritorno a capo, beep)
5
Il codice ASCII standard
Char Dec Oct Hex
(nul)
0 0000 0x00
(soh)
1 0001 0x01
(stx)
2 0002 0x02
(etx)
3 0003 0x03
(eot)
4 0004 0x04
(enq)
5 0005 0x05
(ack)
6 0006 0x06
(bel)
7 0007 0x07
(bs)
8 0010 0x08
(ht)
9 0011 0x09
(nl)
10 0012 0x0a
(vt)
11 0013 0x0b
(ff)
12 0014 0x0c
(cr)
13 0015 0x0d
(so)
14 0016 0x0e
(si)
15 0017 0x0f
(dle) 16 0020 0x10
(dc1) 17 0021 0x11
(dc2) 18 0022 0x12
(dc3) 19 0023 0x13
(dc4) 20 0024 0x14
(nak) 21 0025 0x15
(syn) 22 0026 0x16
(etb) 23 0027 0x17
(can) 24 0030 0x18
(em)
25 0031 0x19
(sub) 26 0032 0x1a
(esc) 27 0033 0x1b
(fs)
28 0034 0x1c
(gs)
29 0035 0x1d
(rs)
30 0036 0x1e
(us)
31 0037 0x1f
Char
(sp)
!
"
#
$
%
&
'
(
)
*
+
,
.
/
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
Dec
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Oct
0040
0041
0042
0043
0044
0045
0046
0047
0050
0051
0052
0053
0054
0055
0056
0057
0060
0061
0062
0063
0064
0065
0066
0067
0070
0071
0072
0073
0074
0075
0076
0077
Hex
0x20
0x21
0x22
0x23
0x24
0x25
0x26
0x27
0x28
0x29
0x2a
0x2b
0x2c
0x2d
0x2e
0x2f
0x30
0x31
0x32
0x33
0x34
0x35
0x36
0x37
0x38
0x39
0x3a
0x3b
0x3c
0x3d
0x3e
0x3f
Char
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\
]
^
_
Dec
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
Oct
0100
0101
0102
0103
0104
0105
0106
0107
0110
0111
0112
0113
0114
0115
0116
0117
0120
0121
0122
0123
0124
0125
0126
0127
0130
0131
0132
0133
0134
0135
0136
0137
Hex
0x40
0x41
0x42
0x43
0x44
0x45
0x46
0x47
0x48
0x49
0x4a
0x4b
0x4c
0x4d
0x4e
0x4f
0x50
0x51
0x52
0x53
0x54
0x55
0x56
0x57
0x58
0x59
0x5a
0x5b
0x5c
0x5d
0x5e
0x5f
Char Dec
`
96
a
97
b
98
c
99
d
100
e
101
f
102
g
103
h
104
i
105
j
106
k
107
l
108
m
109
n
110
o
111
p
112
q
113
r
114
s
115
t
116
u
117
v
118
w
119
x
120
y
121
z
122
{
123
|
124
}
125
~
126
(del) 127
Oct
0140
0141
0142
0143
0144
0145
0146
0147
0150
0151
0152
0153
0154
0155
0156
0157
0160
0161
0162
0163
0164
0165
0166
0167
0170
0171
0172
0173
0174
0175
0176
0177
6
Il codice ASCII esteso
Hex
0x60
0x61
0x62
0x63
0x64
0x65
0x66
0x67
0x68
0x69
0x6a
0x6b
0x6c
0x6d
0x6e
0x6f
0x70
0x71
0x72
0x73
0x74
0x75
0x76
0x77
0x78
0x79
0x7a
0x7b
0x7c
0x7d
0x7e
0x7f




Poiché i bit vengono considerati a gruppi di 8
(byte) e non di 7, il codice ASCII viene
modificato così da usare valori di 8 bit, questo
raddoppia il numero di codici utilizzabili che
passano a 256
I 128 caratteri aggiuntivi (con codice da 128 a
255) vengono utilizzati per altri simboli grafici
meno comuni (es. le lettere accentate, à, ë, î)
La parte aggiunta non è standard ed è diversa
per ciascun sistema operativo
Può essere diversa anche nello stesso sistema
operativo a seconda della lingua
7
Caratteri


Per memorizzare un carattere, il C memorizza
il numero intero corrispondente al suo codice
ASCII ('A' equivale a 65, '0' a 48, ecc.)
Costanti carattere: indicate tra apici singoli
('A'), oppure indicandone il codice ASCII in:




decimale: 65
ottale: '\101'
esadecimale: '\0x41'
Le costanti di tipo carattere vengono anche
chiamate letterali carattere (character literal )
8
Caratteri

Essendo numeri interi, i caratteri possono
essere usati nelle operazioni:
x = c–'0';
se c contiene il codice ASCII di una cifra,
c–'0' ne è il valore corrispondente
Esempio
Se c='7', allora '7'–'0' viene valutato
come 55–48, cioè il valore 7
(il risultato è di tipo int per effetto delle
promozioni integrali)
9
Caratteri

10
Caratteri
Variabili carattere: variabili di tipo intero su
8 bit, sono definite di tipo char
char y;
 definizione
y = 'A';  assegnazione con carattere
y = 65;
 ass. con cod. ASCII decimale
y = '\101';  con cod. ASCII ottale
y = '\0x41';  con cod. ASCII esadecim.

Tutte le assegnazioni precedenti sono
equivalenti ed assegnano il carattere 'A'
(codice ASCII 65) alla variabile y
y può essere usata sia come numero (65) sia
come carattere ('A'):
printf("%c ha valore %d\n", y, y);
dove la specifica %c serve per visualizzare il
simbolo corrispondente ad un codice ASCII,
mentre la specifica %d visualizza un numero
intero, questo visualizza:
A ha valore 65
11
Caratteri



Caratteri
Alcuni caratteri speciali si possono anche
ottenere utilizzando le sequenze di escape:

Caratteri speciali:
12
\'
\"
\?

\\
Ad es. per introdurre l’apice in una variabile
char si deve scrivere '\'' dove il carattere di
escape \ permette di considerare l’apice che lo
segue come carattere normale e non come
delimitatore di una costante di tipo carattere
char apice = '\'';
Poiché il carattere \ ha un significato speciale,
quando esso serve come carattere normale
deve essere raddoppiato (anche nelle stringhe)
char backslash = '\\';

I caratteri corrispondenti ai caratteri di
controllo del codice ASCII non hanno un
aspetto grafico, ma quando vengono
visualizzati producono un effetto quale un
beep, un ritorno a capo, ecc.
Si possono facilmente ottenere mediante
sequenze di escape (oppure si indicano con il
codice ASCII in decimale, ottale o esadec.):
\a
\n
\r
\t
-
quando viene visualizzato fa emettere un beep
corrisponde al carattere new line (10)
corrisponde al carattere carriage return (13)
corrisponde al carattere Tab
char beep = '\a';
13
Stringhe

I L

Stringhe
Sono vettori di char terminati da un carattere
di codice ASCII pari a 0 (il terminatore non è il
carattere '0' che ha valore 48 nel codice
ASCII, ma il carattere '\0')
C I A O \0
R E ! \0
14

67 73 65 79 0
Stringhe costanti
Sono sequenze di caratteri racchiuse da doppi
apici, la stringa "ciao ciao" è composta da
9+1 caratteri, l’ultimo è '\0'
Per includere in una stringa i caratteri \ e " è
necessario precederli dal carattere di escape \

73 74 32 82 69 33 0

Le terminate da uno 0 vengono anche dette
stringhe ASCIIZ, il linguaggio C ha solo questo
tipo di stringhe

"vero\\falso" memorizza: vero\falso
"premi \"invio\" per terminare"
memorizza: premi "invio" per terminare
Una stringa costante viene anche chiamata
letterale stringa (string literal )
15
Stringhe



Più stringhe costanti consecutive (separate da
nulla, spazi, Tab o ritorni a capo) vengono
concatenate dal compilatore in una sola:
"ciao" "ciao"
"ciao"
"ciao"
viene memorizzata come fosse scritta così:
"ciaociaociaociao" (17 caratteri)
Una stringa costante è un vettore di char di
classe di allocazione static (quindi non
modificabile) inizializzato con i caratteri dati
Le classi di allocazione sono descritte in altro set di slide
(puntatori)
16
Stringhe



Variabili stringa
Sono vettori di char di dim. fissa, l’ultimo
carattere deve essere il terminatore '\0'
char nome[15];
definisce una variabile stringa composta di 15
char, può contenere fino a 14 caratteri utili
(deve esserci spazio per il carattere '\0')
Il 1o carattere è nome[0], il 2o nome[1], ecc.
Il terminatore permette di occupare solo
parzialmente una stringa (lo spazio relativo ai
restanti caratteri esiste ma è inutilizzato)
nome: C I A O \0 ? ? ? ? ? ? ? ? ? ?
17
Stringhe



18
Stringhe
La lunghezza di una stringa è il numero di
caratteri contenuti (fino al '\0' escluso), non
la sua “capienza” (nell’es. precedente è 4)
Si noti la differenza tra:
'a'  il carattere 'a' (il numero 97)
"a"  la stringa contenente 'a' e '\0'
Essendo una stringa un vettore di char, il
nome di una stringa viene usato dal
compilatore come sinonimo dell’indirizzo di
memoria del primo carattere



Si possono inizializzare le variabili stringa in 2
modi equivalenti:
char s[20]="Ciao";
char s[20]={'C','i','a','o'};
Il carattere di posizione 4 (il 5o) è '\0' in
entrambi i casi: infatti, essendo vettori, se
l’inizializzazione non riempie completamente
la stringa, i caratteri successivi a quelli indicati
sono tutti 0 (cioè '\0')
I singoli elementi della stringa sono caratteri:
s[2] vale 'a'
s[0] = 'M'; modifica s in "Miao"
Per assegnare una stringa NON si può
scrivere s="Ciao" ma serve una funzione
19
I/O di caratteri <stdio.h>


printf("%c", varChar);
manda in output il carattere
scanf("%c", &varChar);
legge 1 carattere (anche spazi e ritorni a capo)
e lo mette in varChar,
se viene indicata un’ampiezza (es. %4c) legge
esattamente quel numero di caratteri (anche
spazi) e li assegna alla STRINGA indicata come
parametro, senza aggiungere il '\0':
scanf("%4c", varStringa);
per saltare gli spazi iniziali si usi %1s
20
I/O di caratteri <stdio.h>


putchar(varChar);
manda in output il carattere
varInt = getchar();
getchar restituisce il carattere letto o la
costante EOF per segnalare la fine dell’input,
varInt deve essere di tipo int per potervi
memorizzare anche EOF che è di tipo int.
EOF è una costante simbolica definita in
<stdio.h> con una #define, in genere
vale –1
21
I/O di stringhe <stdio.h>



22
I/O di stringhe <stdio.h>
puts(varStringa);
visualizza varStringa e aggiunge un '\n' alla
fine (cioè va a capo). Dà EOF in caso di errore
gets(varStringa);
legge da tastiera tutta la stringa in input
(spazi e Tab inclusi) fino al ritorno a capo
incluso, la mette in varStringa senza il '\n',
aggiunge '\0' alla fine.
Dà NULL in caso di errore o di fine file
printf("%s", varStringa);
%s visualizza una stringa (che può contenere
spazi, Tab, '\n', ecc.) fino al '\0' o al
numero di caratteri indicato (es. %4s)


scanf("%s", varStringa);
 SENZA &
%s salta i white space (spazi, Tab, '\n', ecc.)
iniziali e legge solo fino al primo white space
(che lascia nel buffer), per leggere il primo
carattere saltando i white space iniziali si usi
%1s (richiede una variabile stringa)
Un qualsiasi white space nella stringa di
formato richiede che tutti i white space in quel
punto dell’input vengano saltati (quindi anche
il carattere '\n' non viene considerato come
carattere ordinario: non indica affatto alla
scanf che deve attendere un ritorno a capo)
23
I/O di stringhe <stdio.h>

Una specifica di conversione della forma
%[abc] equivale a una %s salvo che:


si ferma solo quando trova un carattere diverso da
quelli dell’insieme (scanset ) indicati tra le parentesi
quadre (notare che lo scanset può includere lo
spazio e il ritorno a capo)
non salta i white-space iniziali
Esempio
scanf("%[abcfrq]", s);
Se si dà in input “abbaino”, s contiene “abba”
mentre “ino” resta disponibile per le successive
funzioni di input
24
I/O di stringhe <stdio.h>

Per specificare il complementare di uno
scanset si usa il carattere ^ come segue:
%[^abc]
la lettura si ferma solo quando trova un
carattere uguale a uno di quelli indicati tra le
parentesi quadre.
Se si dà in input “albero” alla funzione:
scanf("%[^nmrst]", s);
s contiene “albe” mentre “ro” resta
disponibile per le successive funzioni di input
25
I/O di stringhe <stdio.h>

26
I/O di stringhe <stdio.h>
Per leggere una stringa fino a fine riga
utilizzando una scanf si può quindi utilizzare
la specifica
%[^\n]%*c
che legge tutti i caratteri che trova finché non
incontra il ritorno a capo '\n',
la parte %*c legge e scarta (non memorizza)
il ritorno a capo


Se si danno in input più caratteri di quelli che
la variabile stringa può contenere, si sfora la
stringa (buffer overflow ) e si possono avere
comportamenti anomali (vedere i vettori)
Soluzione non preventiva:


richiedere al compilatore di aggiungere controlli
opportuni (il linguaggio C standard non li prevede)
Soluzioni preventive:


Non si può evitare il problema della gets, ma
questa può essere sostituita da una fgets nella
quale invece si può specificare il numero massimo
di caratteri da leggere (vedere slide sui file)
Se si usa una scanf, si può specificare la
dimensione massima del campo in input: es. %20s
27
Ritorno a capo


A seconda del sistema operativo utilizzato, il
ritorno a capo è in realtà costituito da una
sequenza di uno o più caratteri:
 MS-DOS/Win: CR+LF (codici ASCII 13 e 10: \r\n)
 Unix/Linux: LF (codice 10: \n)
Le funzioni di I/O considerano in carattere ‘\n’
indicato nel codice C come riferimento
generico al “ritorno a capo”:


in input la sequenza di ritorno a capo viene
trasformata in ‘\n’
in output il carattere ‘\n’ viene sostituito con la
sequenza propria del sistema operativo
28
Problemi di I/O


scanf("%d",&x);
gets(s);
Si supponga di inserire un valore e premere
Invio: la scanf legge il valore, ma il ritorno a
capo ‘\n’ (prodotto dal tasto Invio) viene
prelevato (e scartato) dalla gets che quindi
non aspetta altro input e mette in s una
stringa vuota (cioè un carattere ‘\0’):
la gets sembra essere saltata
Bisogna quindi “consumare” il ritorno a capo
dato dopo l’introduzione del numero da
assegnare a x
29
Problemi di I/O

Problemi di I/O
Soluzioni possibili:
1.
2.
3.
30

si aggiunge dopo la specifica %d la specifica %*c
che legge e scarta il successivo carattere in input
(il ritorno a capo): scanf("%d%*c",&x);
si previene il problema evitando di mescolare
scanf e gets:
 si usano solo scanf: risolve il problema perché
le specifiche (esclusa %c) scartano i white space
iniziali (tra cui il ‘\n’)
 si usano solo gets: risolve il problema perché
la funzione gets legge una riga e scarta il
ritorno a capo ‘\n’ alla fine della riga stessa
alcuni compilatori permettono di svuotare i buffer
di input con fflush(stdin) tra la scanf e la
gets, ma fflush su stdin non è standard
Si chiede l’introduzione di due caratteri dalla
tastiera (due input diversi) mediante il codice:
puts("Inserisci 1o carattere: ");
scanf("%c", &c);
puts("Inserisci 2o carattere: ");
scanf("%c", &d);
la prima scanf preleva il carattere per c, ma
lascia nel buffer della tastiera il ritorno a capo
e questo viene prelevato dalla seconda per d,
quindi a d viene assegnato il codice del ritorno
a capo (in realtà viene assegnato il secondo
dei due se il ritorno a capo è la coppia CR+LF)
31
Problemi di I/O

Soluzioni possibili:
1.
2.
nella prima scanf si usa %c%*c che legge ed
elimina il \n
si sostituisce la 2a scanf con:
scanf("%1s",s);
d = s[0];
avendo definito: char s[2];
Questo funziona in quanto la specifica %s legge
caratteri dopo aver saltato i white space (anche
eventuali ‘\n’), in questo caso deve prelevare un
solo carattere.
Attenzione che %1s produce una stringa (e non un
carattere) e questa è composta dal carattere letto
e dal carattere di terminazione '\0'
32
Libreria caratteri <ctype.h>

Le seguenti funzioni danno risultato vero
(valore !=0) se il carattere c è del tipo indicato
isdigit(c)  cifra decimale
isalpha(c)  lettera
 isalnum(c)  carattere alfanumerico
 isxdigit(c) cifra esadecimale
 islower(c)  lettera minuscola
 isupper(c)  lettera maiuscola
 iscntrl(c)  carattere di controllo
 isspace(c)  white space (' ','\t','\n',...)
 isprint(c)  char stampabile, incluso lo spazio
 isgraph(c)  char stampabile, escluso lo spazio
 ispunct(c)  stampabile, no spazio, no alfanum
if (isdigit(c)) printf("e’ una cifra");


33
Libreria caratteri <ctype.h>



Funzioni su stringhe <stdlib.h>
Le seguenti funzioni producono un valore int
contenente il codice ASCII del carattere c
eventualmente convertito, se possibile:

34
toupper(c)  in maiuscolo
tolower(c)  in minuscolo


Altrimenti il valore prodotto resta c (invariato)
Se si vuole convertire in maiuscolo/minuscolo
tutta una stringa è necessario applicare la
funzione a ciascuno dei caratteri:
for (i=0; i<strlen(s); i++)
s[i] = (char)toupper(s[i]);
notare il cast: toupper produce un int

varInt = atoi(stringa)
converte stringa in int
x=atoi("123");  123 in complem. a 2
varLong = atol(stringa)
converte stringa in long
y=atol("123");  123 in complem. a 2
varDouble = atof(stringa)
converte stringa in double
z=atof("1.23E5");  1.23×105 in
floating point
35
Confronto tra stringhe

Avviene confrontando i caratteri di posizione
corrispondente delle due stringhe secondo i
loro codici ASCII ( “< ” significa “precede”)
“cane”
<
“gatto”
“cane”
>
“Gatto”
“cane”
<
“cavallo”
“cavallo”
<
“cavallone”
“cavallo”
<
“cavallo ”
“ cavallo”
<
“cavallo”
“21”
>
“123”
 Attenzione!
36
Libreria stringhe <string.h>
Lunghezza di una stringa
 strlen(str)
restituisce un valore intero pari alla lunghezza
di str ('\0' escluso), il tipo restituito non è
int, ma size_t: si tratta di un tipo adatto a
contenere la lunghezza di una stringa sul
compilatore in uso (su alcuni potrebbe essere
equivalente ad un int, su altri ad un long)
int l;
char s[30]="ciao";
l=strlen(s);
 l vale 4
37
38
Libreria stringhe <string.h>
Libreria stringhe <string.h>
Copia di una stringa
 strcpy(str1,str2)
copia str2 in str1 ('\0' incluso)
Copia parziale di una stringa
 strncpy(str1,str2,n)
copia i primi n caratteri di str2 in str1 (quelli
presenti se è più corta), non aggiunge il '\0'
finale se non è tra i primi n caratteri di str2
char s[30]="hello";
strncpy(s, "ciao", 4);  "ciaoo"
strncpy(s, "hi", 2);  "hiaoo"
Mentre
char s[30]="buongiorno";
strcpy(s, "ciao");  "ciao"
Il modo corretto di cambiare valore ad una
variabile stringa è dunque il seguente:
char s[30];
strcpy(s, "ciao");
Non è invece corretto scrivere:
s = "ciao";
Solo nell’inizializzazione si può scrivere:
char s[30] = "ciao";
39
40
Libreria stringhe <string.h>
Libreria stringhe <string.h>
Concatenazione di stringhe
 strcat(str1,str2)
concatena str2 alla fine di str1 ('\0' incluso)
char s[30]="dove", t[30]=" vai";
strcat(s,t);
 s vale "dove vai"
 strncat(str1,str2,n)
concatena i primi n caratteri di str2 alla fine di
str1 (quelli presenti se è più corta), non
aggiunge il '\0' finale se non è tra i primi n
caratteri di str2
Confronto tra stringhe
 strcmp(str1,str2)
confronta str1 e str2 in base ai codici ASCII,
restituisce un intero:




minore di 0 se str1<str2
uguale a 0 se str1=str2
maggiore di 0 se str1 > str2
strncmp(str1,str2,n)
confronta i primi n caratteri di str1 e str2
(quelli presenti se almeno una è più corta)
41
42
Libreria stringhe <string.h>
Libreria stringhe <string.h>
Ricerca in stringhe
 strchr(str, carattere)
cerca carattere in str a partire dal suo primo
carattere all’ultimo, dà NULL se non lo trova
if (strchr(s, 'z') != NULL)
printf("Trovata una z!");
 strrchr(str, carattere)
cerca carattere in str a partire dal suo ultimo
carattere al primo, dà NULL se non lo trova
 strstr(str1, str2)
cerca str2 in str1, dà NULL se non la trova
if (strstr(s, "ciao") != NULL)
printf("Trovata stringa ciao!");
Ricerca in stringhe
 Le funzioni di ricerca (strchr, strrchr,
strstr, strtok, ecc.) in realtà restituiscono
l’indirizzo di memoria (“il puntatore”) a
quanto trovato e NULL se non lo trovano
43
I/O da/su stringhe <stdio.h>



sscanf(stringa, formato, variabili);
identica alla scanf, ma preleva da stringa i
caratteri come se provenissero dalla tastiera)
Esempio
se stg contiene “12 ciao 23.2”, la funzione:
sscanf(stg, "%d%s%f", &a, s, &b);
legge e assegna 12 ad a, “ciao” ad s, 23.2 a b
Utile per analizzare (parsing) una riga di cui
non è noto a priori il numero di elementi che la
compongono (per sapere quanti sono i valori
letti si valuta il valore restituito dalla sscanf)
44
I/O da/su stringhe <stdio.h>

Esempio
gets(s);
if (sscanf(s,"%d%d",&a,&b)==2) ...




s  “abcd ...”
s non contiene valori numerici, nessuna delle
variabili viene assegnata e la sscanf restituisce 0
s  “12 abcd ...”
s contiene 1 solo valore, questo viene assegnato ad
a (b resta invariato) e la sscanf restituisce 1,
s  “12 23 abcd ...”
s contiene 2 valori, questi sono assegnati ad a e a
b e la sscanf restituisce 2
s  “12 23 34 abcd ...”
s contiene più di 2 valori, i primi due sono
assegnati ad a e a b, i restanti non vengono
considerati e la sscanf restituisce 2
45
I/O da/su stringhe <stdio.h>



46
Altre funzioni di parsing
sprintf(stringa, formato, variabili);
identica alla printf, ma “scrive” in stringa i
caratteri che la printf manderebbe su
stdout (video)

Esempio
se g contiene 23 e m contiene “febbraio”
sprintf(str, "Il %d %s", g, m);
mette in str: “Il 23 febbraio”
Oltre alla sscanf, per la suddivisione
(parsing) di una stringa composta da più
parti (token) si possono usare le seguenti
funzioni (si rimanda ad altra documentazione
per i dettagli, vedere bibliografia):


Utile per assemblare una stringa composta da
parti di tipo diverso provenienti da variabili
In <string.h>:
strspn, strcspn, strpbrk, strtok
In <stdlib.h> (token di tipo numerico):
strtod, strtol, strtoul
47
Vettori di stringhe

Una matrice di char è un vettore di stringhe:
char str[4][20]={"uno", "due"};
definisce un vettore di 4 stringhe di 20 char
(i caratteri sono inizializzati a ‘\0’ se almeno
parte della matrice viene inizializzata)
Le 4 stringhe sono identificate da str[i] e
utilizzabili come normali stringhe:
scanf("%s", str[2]);  es."ciao"
str[3][0]='X';
str:
str[0] u n o \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
str[1] d u e \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
str[2] c i a o \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
str[3] X \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
48
Vettori di stringhe

Per memorizzare una sequenza di N stringhe
di lunghezza LEN in un vettore di stringhe si
può utilizzare il metodo seguente:
char str[N][LEN];
for (i=0; i<N; i++)
gets(str[i]);
49
Esercizi
1.
2.
3.
4.
5.
50
Esercizi
Scrivere un programma che date due
stringhe in input stampi la più lunga. La
prima se sono di uguale lunghezza.
Scrivere un programma che date due
stringhe in input stampi la maggiore.
Scrivere un programma che chieda in input
una stringa e calcoli da quanti caratteri è
composta (senza usare la funzione strlen
ma cercando il carattere '\0')
Scrivere un programma che data una stringa
in input, la converta tutta in maiuscolo.
Scrivere un programma che data una stringa
in input verifichi se essa contiene almeno
una ‘A’ tra i primi 10 caratteri.
6.
7.
Scrivere un programma che richieda in input
una stringa e conti quante cifre essa contiene.
Esempio
“Ciao2004! C6?” deve dare 5.
Scrivere un programma che richieda in input
una stringa e conti di quante lettere
maiuscole, lettere minuscole, cifre e altri
caratteri è composta
Esempio
“Ciao2004! C6?” deve dare:
maiuscole:2, minuscole: 3, cifre: 5, altri: 3.
51
52
Esercizi
Esercizi
Scrivere un programma che date in input due
stringhe di lunghezza diversa indichi se la più
corta è contenuta solo una volta nella più
lunga.
9. Scrivere un programma che verifichi se la
stringa data in input è palindroma o no
(“kayak”, “otto”, “elle”, “anilina”).
10. Scrivere un programma che verifichi se la
stringa data è composta di due parti uguali,
trascurando il carattere centrale se la
lunghezza è dispari (es. “CiaoCiao”,
“CiaoXCiao”).
11. Un’immagine
8.
è composta da 256x256 punti di
colore bianco o nero ed è rappresentata da
una matrice di caratteri. Ogni elemento della
matrice rappresenta un puntino e vale:
‘1’ per rappresentare un punto nero
‘0’ per rappresentare un punto bianco.
Si scriva un programma che codifichi
l’immagine sostituendo, per ciascuna riga di
punti, le sequenze consecutive dello stesso
carattere (‘0’ o ‘1’) con il carattere stesso
seguito dal numero delle sue ripetizioni. Si
ripeta codificando le colonne.
53
54
Esercizi
Homework 2
Continuazione:
Scrivere un programma che chieda all’utente di
inserire una frase (max 128 caratteri), conti
quante sono le parole (sequenze di lettere
dell’alfabeto) che la compongono e la lunghezza
media delle parole stesse.
Esempio
Se viene dato in input:
Ad es. l’immagine seguente (solo 6x3):
0000000000 (ci sono 10 zeri)
0111111100 (1 zero, 7 uno, 2 zeri)
0100000100 (1 zero, 1 uno, 5 zeri, 1 uno, 2 zeri)
viene codificata per righe come segue:
0 10
011702
0111051102
e per colonne come segue:
03
0112
011101
...
Ieri... sono andato a mangiare all'una!
il programma deve indicare che ci sono 7 parole
e che la lunghezza media è 4.14 caratteri.