Fondamenti di Linguaggio C - Corso di Informatica Grafica - Prof. Manuel Roveri

Pagina creata da Emanuele Fiore
 
CONTINUA A LEGGERE
Corso di
Informatica
                                           Fondamenti di
Grafica                                    Linguaggio C
Linguaggio C: Identificatori, dichiarazione e definizione – Variabili - Tipi di
dato fondamentali – Costanti - Strutture di controllo - Input/output              Prof. M. Roveri
elementare
1. Identificatori, definizione e dichiarazioni
1.1 Identificatori

Gli identificatori assegnano i nomi alle entita' (variabili e funzioni).

All'interno di un programma un'entita' deve avere un identificatore univoco.

Regole e caratteristiche degli identificatori:

 ♦ case sensitive: distinzione maiuscolo/minuscolo;

 ♦ lunghezza massima: dipendente dall’implementazione del compilatore e del sistema operativo. Lo standard
      garantisce 31 caratteri significativi per i nomi delle entita' interne e 6 caratteri per i nomi delle entita' esterne;

 ♦ sintassi: deve iniziare o con una lettera o con l'underscore ('_') e puo' proseguire con lettere, underscore o cifre.
       Non puo' essere una parola chiave del C.

1.2 Definizione e dichiarazione

Le proprietà di una entità (variabile o funzione) vengono descritte durante la sua definizione o dichiarazione.

Con la dichiarazione, l'entità viene associata all'identificatore (nome della variabile o della funzione) e ne viene
dichiarata la tipologia, ma non viene né riservata la memoria per le variabili, né specificato il codice per le funzioni.

Con la definizione, oltre ad associare l'identificatore alla entità e definirne la tipologia (es: variabile di tipo float), viene
riservata memoria per le variabili, o specificato il codice per le funzioni.

2. Variabili
Una variabile può essere descritta come un contenitore, il cui contenuto è sempre a disposizione e rappresenta il
valore della variabile stessa.

Ad ogni variabile e' associato:

 • un nome (identificatore);

 • un tipo (insieme dei valori che puo' assumere);

 • un'area di memoria (per contenere il valore assunto);

 • un indirizzo (riferimento all'area di memoria);

 • un valore (in istanti diversi la variabile può assumere valori differenti, purché coerenti con il tipo).

Si definisce una variabile con la sintassi:

tipo identificatore1 [= inizializzazione1 ] [, identificatore2 [= inizializzazione2 ]] ... ;
Il C é un linguaggio:

 • tipato, poiché le variabili sono dotate di tipo.

 • non strettamente tipato, poiché i controlli sui tipi non sono stretti a differenza, per esempio, di quanto avviene nel
      Pascal (linguaggio strettamente tipato).

3. Tipi di dato fondamentali
Per tipo di dato si intende un insieme di valori e un insieme di operazioni che possono essere applicati. Ad esempio i
numeri interi e le usuali operazioni aritmetiche come somma, sottrazione, ecc.
Ogni tipo di dato ha una propria rappresentazione in memoria (codifica binaria) che utilizza un certo numero di celle di
memoria. Tuttavia l’uso nei programmi dei tipi di dato consente di trattare le informazioni in maniera astratta, cioè
prescindendo dalla loro rappresentazione nella macchina. In altre parole, se si sommano due interi non vi è necessità
di preoccuparsi di come devono essere sommati i bit che corrispondono ai due addendi in memoria, ma si indica solo
un segno di somma nell’istruzione in C (ad esempio: c=a+b;).
L’uso di variabili con tipo ha importanti conseguenze:
  • per ogni variabile è possibile determinare a priori l’insieme dei valori ammissibili e l’insieme delle operazioni
        applicabili;
  • per ogni variabile è possibile determinare a priori la quantità di memoria necessaria;
  • è possibile rilevare a priori (a tempo di compilazione) errori nell’uso delle variabili all’interno di operazioni non
        lecite per il tipo corrispondente.

I tipi di dato si dividono in:
  • tipi semplici;
  • tipi strutturati.

I tipi semplici consentono di rappresentare informazioni composte da un valore come ad esempio una temperatura,
una velocità, ecc.
I tipi strutturati consentono di rappresentare informazioni costituite dall’aggregazione di varie componenti come ad
esempio una data, una matrice, una cartella clinica, ecc.
Un valore di un tipo semplice è logicamente indivisibile, mentre un valore di un tipo strutturato può essere scomposto
nei valori delle sue componenti. Ad esempio: un valore di tipo data è costituito da tre valori (semplici).

3.1 Tipi di dato predefiniti

Il C mette a disposizione un insieme di tipi predefiniti (tipi built-in) e dei meccanismi per definire nuovi tipi (tipi user-
defined).
I tipi semplici che il C mette a disposizione sono:
  • interi;
  • reali;
  • caratteri.

3.1.1 Rappresentazione numerica

I tipi di dato predefiniti del C, adatti a rappresentare numeri, si differenziano tra tipi per numeri interi oppure con
virgola e per il numero di bit che sono utilizzati nella loro rappresentazione nell’elaboratore.

INTERI CON SEGNO (INT)

In C esistono 3 tipi di interi con segno:
• short (dichiarabile nei seguenti modi short int, signed short, signed short int);
 • int (dichiarabile nei seguenti modi signed int, signed);
 • long (dichiarabile nei seguenti modi long int, signed long, signed long int).

Il loro intervallo di definizione va da -2 n-1 a +2 n-1 -1, dove n dipende dal compilatore e rappresenta il numero di bit
impiegati per la loro rappresentazione.
Analizzando la loro occupazione in memoria (direttamente legata al numero di bit con il quale il dato è memorizzato e
quindi all’intervallo di rappresentazione), valgono le seguenti relazioni:
  • sizeof(short) = 4 (ovvero, almeno 32 bit).

L’operatore sizeof() in C ritorna il numero di byte occupati da una variabile o da un tipo di dato che gli viene passato
come operando.
I valori limite sono contenuti nel file limits.h, che definisce le costanti:
SHRT_MIN, SHRT_MAX, INT_MIN, INT_MAX, LONG_MIN, LONG_MAX
Queste costanti possono ad esempio servire in un programma per controllare se il dato immesso da un utente cade
nell’intervallo di rappresentazione. Se non lo fosse, possiamo segnalarlo all’utente al posto che far continuare
l’esecuzione e generare quindi un probabile errore di overflow/underflow.
Se si vuole dichiarare una costante, si scriveranno i numeri interi semplicemente in decimale, ad esempio 0, 10, -10, . .
.
Gli operatori utilizzabili sono: +, -, *, /, %, ==, !=, , =
Per quanto riguarda le funzioni di ingresso/uscita si usano le funzioni printf e scanf, con i seguenti indicatori di formato
(dove d indica “decimale”):
  • %hd per short
  • %d per int
  • %ld per long (con l minuscola)

Ad esempio per stampare un intero che era stato definito come short si può scrivere:
printf(“%hd", contatore);

INTERI SENZA SEGNO (unsigned)

In C esistono 3 tipi di interi senza segno:
  • unsigned short (oppure: unsigned short int);
  • unsigned int;
  • unsigned long (dichiarabile nei seguenti modi long int, unsigned long, unsigned long int).

Il loro intervallo di definizione va da 0 a +2 n -1, dove n dipende dal compilatore e rappresenta il numero di bit
impiegati per la loro rappresentazione.
Le costanti definite che indicano gli intervalli di rappresentazione sono contenuti nel file limits.h e sono:
USHRT_MAX, UINT_MAX, ULONG_MAX (si noti che il minimo `e sempre 0).

Se si vuole dichiarare una costante si scriverà:
 • decimale: come per interi con segno;
 • esadecimale: 0xA, 0x2F4B, . . .

Ingresso/uscita: tramite printf e scanf, con i seguenti specificatori di formato:
  • %u per numeri in decimale;
  • %o per numeri in ottale;
  • %x per numeri in esadecimale con cifre 0, . . . , 9, a, . . . , f;
  • %X per numeri in esadecimale con cifre 0, . . . , 9, A, . . . , F.

Per interi short si antepone h e per interi long si antepone l (minuscola).
TIPI REALI o FLOATING POIN (float)

In C i tipi reali vengono rappresentati mediante virgola e ne esistono 3 tipi:
  • float (dimensione in memoria 4 byte);
  • double (dimensione in memoria 8 byte);
  • long double (dimensione in memoria 12 byte).

In particolare questa notazione si chiama in virgola mobile.
Le grandezze e gli intervalli di questi tipi di dato sono scritte nel file float.h di libreria e dipendono dal compilatore.
Comunque valgono le seguenti relazioni:
sizeof(float) = sizeof(double) = sizeof(long double)
Se si vuole dichiarare una costante si scriveranno gli interi semplicemente in decimale USANDO SEMPRE IL PUNTO
oppure usando la notazione scientifica.
Esempio:
double x, y, z, w;
x = 123.45;
y = 0.0034; y = .0034;
z = 34.5e+20; z = 34.5E+20;
w = 5.3e-12;
Per quanto riguarda l’output di variabili float mediante printf:
  • se si usa %f si stampa il numero in virgola fissa;
  • se si usa %8.3f si stampano 8 cifre complessive, di cui 3 cifre decimali;
  • se si usa %e si stampa in forma esponenziale.

Esempio:
float x = 123.45;
printf("|%f| |%8.3f| |%-8.3f|\n", x, x, x);
Si ottiene in output:
|123.449997| | 123.450| |123.450 |
Esempio:
double x = 123.45;
printf("|%e| |%10.3e| |%-10.3e|\n", x, x, x);

Si ottiene in output:
|1.234500e+02| | 1.234e+02| |1.234e+02 |

Si può stampare anche in forma ottimizzata usanto %g (oppure %G) che sceglie la forma più compatta fra la notazione
esponenziale (%e) e quella di %f.
Per quanto riguarda l’input con scanf nel caso dei float si può usare indifferentemente %f o %e.

3.1.1 Rappresentazione dei caratteri

I caratteri alfanumerici del codice ASCII (American Standard Code For Information Interchange) compongono
praticamente tutti i nostri file di testo e moltissimi altri file.
Questi caratteri vengono rappresentati in C mediante la dichiarazione di variabili di tipo char.
Un codice associa ad ogni carattere un intero.
Ad esempio il codice ASCII associa al carattere ’#’ il numero decimale 35 e alle lettere ’0’… ’9’ della nostra tastiera i
numeri decimali dal 48 al 57.
Ad esempio, alle lettere ‘a’… ‘z’ della nostra tastiera sono stati associati i numeri decimali dal 97 al 122.
È importante ricordare che i caratteri in C possono essere usati come interi, se si ricorda la corrispondenza fra il
carattere ed il suo valore nel codice.
In C esistono 3 tipi di caratteri:
  • char;
  • signed char (rappresentato in complemento a 2);
  • unsigned char.

I tipi signed ed unsigned char sono esattamente rappresentati come interi.
Attenzione, il tipo char dipende invece dal compilatore e può essere stato definito come signed oppure unsigned.
Tipicamente vale sizeof(char) = sizeof(int) ove sizeof(char) vale 8 bit.
Tutti gli operatori definiti su int (+, -, *, /, %, ==, !=, , =) valgono sui caratteri.
Attenzione: questo è interessante poiché permette di ordinare i caratteri.
Se ad esempio x=’a’ e y=’b’ allora la proposizione (y>x) è vera. Questo è possibile perché il C vede il contenuto di x
come 97 (ovvero ‘a’ nel codice ASCII) ed il contenuto di y come 98!
Ad esempio se una variabile carattere x rispetta la seguente proposizione ((x>96)AND(x
'\"' " (apice doppio)
'\0'  (carattere NULL)

5. Strutture di controllo
Le istruzioni di controllo del flusso specificano l’ordine secondo il quale i calcoli devono essere effettuati.

5.1 Espressioni come istruzioni

La maggior parte delle istruzioni sono istruzioni-espressione, sono cioe' delle espressioni seguite dal ; (punto e
virgola).
La sintassi è la seguente:
espressione;
N.B.1: L'espressione e' opzionale.
N.B.2: Il ; (punto e virgola) e' il terminatore di istruzione.
Il valore dell'espressione viene trascurato, mentre di fondamentale importanza sono gli effetti collaterali che
modificano i valori delle variabili o aree di memoria. Gli effetti collaterali sono valutati completamente prima che
venga eseguita la successiva istruzione.
Esempio:
;
Questo è il caso dell'istruzione nulla ed il suo impiego e' tipico laddove la sintassi richieda una istruzione, ma il
programma non debba eseguire alcuna azione.

5.2 Blocchi

In C i blocchi sono realizzati mediante l'uso delle parentesi graffe dentro le quali vi è una sequenza di istruzioni.
E' possibile dichiarare delle variabili locali all'interno di un blocco di istruzioni C. I blocchi possono essere innestati uno
dentro l’altro a piacere: le dichiarazioni delle variabili locali seguono immediatamente la parentesi sinistra e
precedono la parte eseguibile del blocco.
{ dichiarazioni istruzioni }
L'impiego dei blocchi è finalizzato alla:
  • scrittura di un insieme di istruzioni (nei casi in cui la sintassi permetta l'inserimento di solamente una istruzione);
  • definizione del corpo di una funzione.

Esempio 1:
int a, b;
....
{ int temp; /* parte dichiarativa del blocco */
temp = a;
a = b;
b = temp;
} /* Attenzione: da qui in poi la variabile temp cessa di esistere */

Esempio 2:
{} /* blocco vuoto */
Valgono le usuali regole di visibilità: le variabili locali sono visibili dal punto della loro dichiarazione fino alla fine del
blocco cui appartengono; inoltre, le variabili locali nascondono (rendendo non accessibili) le variabili omonime globali,
cioè dichiarate in blocchi più esterni
5.3 Istruzioni di selezione

Il C mette a disposizione due istruzioni di selezione:
     • il costrutto IF
     • il costrutto SWITCH

5.3.1 Costrutto IF

E’ composto da una espressione e uno/due/tre/enne blocchi di codice (chiamati i "rami" dell'if).
Le due forme tipiche in cui si può presentare la sintassi relativa al costrutto IF sono le seguenti:
1° caso:
if (espressione)
         istruzione_1
2° caso:
if (espressione)
         istruzione_1
else
         istruzione_2
istruzione_1 viene eseguita se espressione, una volta valutata assieme a tutti i suoi effetti collaterali, torna un
valore vero (cioè non zero); altrimenti se espressione torna un valore falso (cioe' uguale a zero) viene eseguita
istruzione_2, se esistente.
Nel caso di IF innestate, la parte else viene abbinata sempre all'ultima if posta nello stesso blocco della else, ma non
gia' abbinata ad una precedente else.
Per migliorare la leggibilita' e' consigliata una buona e coerente indentazione del programma, tale che rispecchi la
struttura del codice.
Per evitare possibili ambiguita' nelle IF innestate, e' possibile l'utilizzo di blocchi per racchiudere i costrutti piu' interni.

Esempio 1:
if (a > b)
          m = 0;
else
          m = 5;

Esempio 2:
if (a > b)
          if (c > d)
                    n = 0;
          else
                    m = 5; /* a > b e c  b)
{
          if (c > d)
          n = 0;
}
else
          m = 5; /* a
if (expr2)
                  istr2
         else
                  if (expr3)
                           istr3
                  else
                           if (expr4)
                                    istr4
else
istr5

5.3.2 Costrutto SWITCH

Il costrutto SWITCH è solitamente impiegato quando si devono controllare molti casi. In questo modo il codice risulta
essere più ordinato.
Il costrutto è composto da etichette (CASE) e da un caso generale (DEFAULT). Le etichette del case devono essere delle
costanti.
La forma tipica della sintassi relativa al costrutto SWITCH è la seguente:
switch (espressione)
{
case espr_costante_1:
[istruzioni]
...
case espr_costante_2:
[istruzioni]
...
default:
[istruzioni]
...
}
N.B. – L’etichetta default e le istruzioni ad essa relativa, sono opzionali, così pure è opzionale la lista di istruzioni che
seguono ogni etichetta (label) del case.

L'espressione viene valutata assieme ai suoi effetti collaterali ed il valore ritornato da essa, che deve essere di tipo
intero (char, int, long) viene confrontato con le espressioni costanti associate alle case.
In caso di corrispondenza il controllo viene passato alle istruzioni ad essa associate, e continua fino al termine
dell'istruzione SWITCH (quindi fino al raggiungimento della parentesi } di chiusura dell'istruzione).
Se il valore dell'espressione non corrisponde a nessuna delle espressioni costanti, allora il controllo viene trasferito
alla prima istruzione associata alla label default, e prosegue fino al raggiungimento del termine dell'istruzione SWITCH.
Se nemmeno la label default è specificata, la SWITCH termina immediatamente.
E' permesso l'innestamento dei costrutti SWITCH.
Tra gli statement che compongono il corpo dello SWITCH e' permesso l'utilizzo dell'istruzione di salto BREAK. Quando
tale istruzione viene incontrata, essa causa il termine dell'esecuzione dell'istruzione SWITCH ed il controllo passa
all'istruzione successiva.

Esempio:
// conteggio dei tipi di caratteri
char c;
int n_cifre, n_separatori, n_altri;
...
c = ....; // sia c il carattere da esaminare
switch (c)
{
            case '0':
                       n_cifre = n_cifre + 1;
break;
          case '1':
                      n_cifre = n_cifre + 1;
                      break;
                      .....
          case '9':
                      n_cifre = n_cifre + 1;
                      break;
          case ' ':
                     n_separatori = n_separatori + 1;
                     break;
          case '\n':
                     n_separatori = n_separatori + 1;
                     break;
          case '\t':
                     n_separatori = n_separatori + 1;
                     break;
          default:
                     n_altri = n_altri + 1;
}
...

5.4 Istruzioni di Iterazione

Il C mette a disposizione tre istruzioni di iterazione:
  • il costrutto WHILE
  • il costrutto DO-WHILE
  • il costrutto FOR

5.4.1 Costrutto WHILE

E’ il costrutto più generale, da cui si possono ottenere tutti gli altri costrutti per l’iterazione.
La sua struttura è la seguente:

while (espressione)
         istruzione

oppure:

while (espressione)
         {
         istruzione1
         istruzione2
         ....
         istruzionen
         }

L'espressione viene valutata e, se ha valore diverso da 0 (vero), viene eseguita l'istruzione successiva (che può anche
essere un intero blocco di istruzioni, opportunamente delimitato dalle parentesi graffe). Una volta che quest'ultima è
terminata, l'espressione viene valutata nuovamente e, se è nuovamente vera, si ripete l'istruzione. Ciò si replica fino a
quando l'espressione ha valore 0 (falso), e in questo caso il controllo si trasferisce all'istruzione successiva, al while.
Un ciclo while può essere eseguito zero o più volte, poiché l'espressione potrebbe essere falsa già la prima volta. Si
tratta di un ciclo a condizione iniziale: prima di eseguire il ciclo si valuta la condizione.
Il problema principale delle strutture iterative è che possono entrare in ciclo infinito. Questo accade se per un errore
di programmazione o per qualche condizione esterna alla espressione del while rimane sempre vera.
All'interno del blocco di istruzioni puo' comparire l'istruzione BREAK che, se eseguita, provoca il termine del WHILE
nonché l'istruzione CONTINUE che, una volta invocata, forza l’inizio dell’iterazione successiva del ciclo, provoca cioè
l’esecuzione immediata della parte di controllo del ciclo.
In caso di cicli innestati, entrambe le istruzioni BREAK e CONTINUE non hanno influenza sui cicli piu' esterni.
Esempio: vengono sommati i numeri interi che l’utente immette da tastiera fino a quando non viene immesso uno
zero.

#include 
int main()
{
int i, somma;
somma = 0;
i = 1; // valore iniziale (serve solo per entrare nel while)
while (i != 0)
{
scanf ("%d" , &i);
somma = somma + i;
}
printf("La somma e' %d", somma);

5.4.2 Costrutto DO-WHILE

Il costrutto DO-WHILE presenta la seguente sintassi:

do
         istruzione
while (espressione);

Per ogni ciclo viene eseguita l’istruzione, poi viene valutata l'espressione.
Se risulta vera (diversa da zero) il ciclo viene riavviato, altrimenti l'istruzione DO-WHILE ha termine.
L’istruzione viene eseguita almeno una volta: infatti il costrutto do-while è un ciclo a condizione finale: prima di
valutare la condizione si esegue il ciclo. Quindi il corpo del ciclo viene eseguito sempre almeno una volta
Al posto dell’istruzione può esserci un blocco. All’interno di un blocco di istruzioni può comparire l'istruzione BREAK
che, se eseguita, provoca il termine del DO-WHILE nonche' l'istruzione CONTINUE che, una volta invocata, forza l’inizio
dell’iterazione successiva del ciclo, provoca cioè l’esecuzione immediata della parte di controllo del ciclo.
In caso di cicli innestati, entrambe le istruzioni BREAK e CONTINUE non hanno influenza sui cicli piu' esterni.

5.4.3 Costrutto FOR

Il costrutto FOR è equivalente al costrutto WHILE, ma l’uso è consigliato solo nel caso in cui il
numero di iterazioni SIA NOTO A PRIORI.
Per esempio, se si deve scandire una struttura dati che ha sempre N elementi, allora si userà un ciclo FOR. Nel caso in
cui si debba continuare a chiedere all’utente di digitare un numero finché non viene immesso un numero pari a zero,
allora si userà un costrutto WHILE in quanto il numero di iterazioni non è noto a priori.
Il costrutto FOR è composto nel seguente modo:

for ( expr1 ; expr2 ; expr3 )
         istruzione

Se si vuole iterare un blocco di codice, il costrutto FOR è composto nel seguente modo:

for ( expr1 ; expr2 ; expr3 )
         {
         istruzione1
         istruzione2
         ...
istruzionen
         }
in cui:
  • expr1 è l’espressione iniziale,
  • expr2 è l’espressione booleana (del ciclo),
  • expr3 è l’espressione incremento.

L'espressione iniziale permette di inizializzare le variabili di ciclo e viene eseguita una volta sola, prima di qualsiasi altra
operazione.

Esempio: contatore = 0.
Successivamente ad essa, viene valutata l'espressione del ciclo e, se questa ha valore diverso da 0, viene eseguita
l'istruzione che costituisce il corpo del ciclo (o il blocco di istruzioni fra parentesi graffe).
Esempio: contatore < 9.
Al termine dell'esecuzione del corpo del ciclo, viene valutata l'espressione-incremento, di solito per poter aggiornare i
valori delle variabili di ciclo.
Esempio: contatore = contatore + 1.
Quindi, si valuta nuovamente l'espressione del ciclo e cosi via. Il ciclo si ripete finché non si valuta come falsa
l'espressione del ciclo (valore 0).
All’interno di un blocco di istruzioni può comparire l'istruzione BREAK che, se eseguita, provoca il termine del FOR
nonche' l'istruzione CONTINUE che, una volta invocata, forza l’inizio dell’iterazione successiva del ciclo dopo avere
valutato espr3.
In caso di cicli innestati, entrambe le istruzioni BREAK e CONTINUE non hanno influenza sui cicli piu' esterni

6. ISTRUZIONI DI INPUT/OUTPUT
6.1 Output: printf

Obiettivo: dichiarare una variabile i intera, assegnarvi un valore e stamparla a video.
Un semplice programma che esegue queste azioni è il seguente:
#include 
int main()
{
          int i;
          i = 3;
          printf("%d", i);
}
Nella parte dichiarativa si dichiara la variabile i come variabile intera (int). Nella prima riga della parte esecutiva si
assegna il valore 3 alla variabile i.
La terza riga del main chiama la funzione printf che permette di stampare la variabile i passata (alla destra della
virgola) a terminale. Alla sinistra della virgola è presente una stringa chiamata stringa di controllo. Essa ha il compito di
definire in che modo il contenuto della variabile i debba essere stampato. Ad esempio “%d” significa che i verrà
stampata come un intero: a monitor comparirà il numero 3.
Come già visto, se si scrive:
printf("Hello WORLD");
compare a monitor:
Hello WORLD

Se invce si scrive:
printf("Il valore contenuto e’: %d", i)
compare a monitor:
Il valore contenuto e’: 3
Questo accade poiché la funzione printf stampa la stringa di controllo e sostituisce alle parti della stringa che iniziano
con % (in questo caso %d) i valori delle variabili passati alla destra della virgola (il valore di i).
6.2 Input: scanf

Obiettivo: dichiarare una variabile i intera, leggere un valore dalla tastiera e copiarlo in una variabile.
Un semplice programma che esegue queste azioni è il seguente:
#include 
int main()
{
          int i;
          printf("immetti un numero intero :");
          scanf("%d", &i);
          printf("il valore memorizzato e’ %d", i); /* lo stampiamo per controllo */
}
Nella parte dichiarativa si dichiara la variabile i come intera (int). Nella prima riga della parte esecutiva si stampa un
messaggio per l’utente affinché capisca che gli stiamo chiedendo di battere un numero intero sulla tastiera.
L’immissione si conclude
automaticamente con la pressione del tasto enter (invio).
La terza riga del main chiama la funzione scanf che permette di copiare il numero letto da tastiera nella variabile i. Alla
sinistra della virgola è scritto come deve essere letto il dato immesso dalla tastiera. In questo caso l’indicazione “%d”
indica che deve essere letto come un numero intero.
Questa considerazione non è banale. Infatti se l’utente digitasse 1024 sulla tastiera seguito dalla pressione dell’enter,
il sistema potrebbe interpretare questo dato sia come il numero intero 1024 ma anche come la stringa composta dai
caratteri ‘1’, ‘0’, ‘2’ e ‘4’. Indicando %d, si toglie ogni possibilità sull’interpretazione di come il dato debba essere letto
ossia come un numero intero.
Alla destra della virgola è presente l’indirizzo dove il valore letto deve essere memorizzato (&i significa “all’indirizzo di
i”).
Attenzione, non è corretto scrivere scanf("%d", i); senza &.
L’ultima riga del main stampa il valore immesso. In questo modo è possibile effettuare una verifica secondo le
modalità già descritte a proposito della funzione printf.
Puoi anche leggere