|
Questa guida sarà più che altro una guida
alla programmazione in generale, nel senso che cercherò
di spiegarvi come si fanno le cose e perché si fanno
in quel certo modo, e quindi è adatta anche a chi
non sa (ancora) niente di programmazione e vuole farsi le
ossa. Sicuramente non è da prendere come una guida
di riferimento per il programmatore provetto... non pensateci
neanche ;). Cercherò comunque di trattare il maggior
numero di argomenti possibile, partendo da quelli elementari,
fino a giungere a quelli un po' più complicati, come
la gestione di strutture dati dinamiche e la programmazione
di rete (che al momento sto imparando io stesso :-).
Ovviamente (come troverete scritto anche dopo), accetto
suggerimenti, richieste di parlare di questo o quell'argomento,
e qualsiasi cosa vogliate scrivermi :). Il mio indirizzo
è enjoy.the.silence@iol.it, e il mio sito è
a http://sukkopera.cjb.net.
Enjoy!
INTRODUZIONE
Prima di tutto, immagino che vi servirà un compilatore
per poter provare le vostre creazioni. Se utilizzate Linux,
potete usare il classico GCC, normalmente presente in ogni
installazione, se invece usate MS-DOS, potete usare l'apposito
porting di GCC, che funzionerà anche sotto la maggior
parte delle versioni di Windows. Si chiama DJGPP e lo potete
scaricare da http://www.delorie.com/djgpp. Ve lo consiglio
caldamente ;). Per scrivere i programmi potete usare un
qualunque editor di testo (l'edit.com di MS-DOS va benissimo),
oppure un programma apposito, come l'ottimo RHIDE che è
parte di DJGPP e comprende svariate funzioni per interfacciarsi
direttamente con il compilatore ed il debugger, evitandovi
così di dover scrivere (e ricordare) tutte le varie
opzioni da linea di comando. Entrambi sono gratuiti, in
quanto distribuiti sotto licenza pubblica GNU (GPL).
Passiamo ora alla...
LEZIONE 1
Ogni buon corso di programmazione inizia con il codice
necessario per stampare "Ciao mondo!" sullo schermo;
noi non vogliamo essere da meno, quindi eccolo qua:
--- 01_first.c -----------------------------------------------------------------------------------
#include <stdio.h>
int main (void) {
printf ("Hello world!\n");
return (0);
}
--------------------------------------------------------------------------------------------------
Noterete innanzitutto che il C fa uso delle parentesi graffe,
che sfortunatamente mancano dalle tastiere italiane :/.
Per rimediare, potete tenere premuto il tasto ALT di sinistra,
e digitare 123 sul tastierino numerico: come per magia apparirà
una parentesi graffa aperta! E se usate 125 comparirà
la chiusa. Notevole, eh? ;)
Noterete poi altre parole incomprensibili (per ora!): esse
rimarranno così ancora per un po', quindi prendetele
per buone e non fatevi (e non fateMI!) troppe domande, dato
che adesso ci occuperemo solo del cuore del programma: la
linea di printf. printf è la funzione che vi permette
di scrivere sullo schermo. Essa vuole come parametro la
stringa da scrivere. Una stringa è semplicemente
una sequenza di caratteri, racchiusi tra virgolette (""),
che verranno stampati pari pari sullo schermo. Se provate
ad eseguire il programma, noterete però che il '\n'
finale non verrà visualizzato. Come mai? Semplice,
'\n' vuol dire "vai a capo", e fa sì che
quel che segue venga stampato sulla riga successiva (cosa
che in C non è mai implicita, al contrario ad esempio
del BASIC). Per essere più precisi, tutte le volte
che in una stringa compare il carattere '\', il comportamento
varia a seconda del carattere che segue. Alcuni esempi:
- '\n' -> Vai a capo
- '\t' -> Spostati orizzontalmente fino alla prossima
tabulazione (Provare per capire)
- '\a' -> Suona il campanello
- '\r' -> Ritorno carrello, ossia torna a inizio riga
(Il cui funzionamento è un po' soggettivo)
- '\b' -> Cancella il carattere precedente (Idem come
sopra, non stupitevi se funziona a seconda dell'umidità...)
Sorge spontanea una domanda: come si fa a stampare una semplice
'\'? D'altronde può essere necessario... Semplice,
basta metterne 2! Infatti "\\" stamperà
UNA semplice backslash. Ricordatevene o non capirete il
perché di centinaia di errori quando tratterete qualche
path MS-DOS... Capirete a più avanti! ;)
Qualche esempio pratico (da sostituire al printf del programma
precedente):
printf ("Hello ");
printf ("world!\n");
Questo darà esattamente lo stesso risultato di prima,
serve solo ad enfatizzare il fatto che dopo il primo printf
non c'è nessun "a capo" implicito.
printf ("Hello\nworld!\n\a");
Questo stamperà "Hello" su una riga e "world!"
sulla successiva, per dimostrare che '\n' può essere
utilizzato in qualsiasi punto di una riga. Inoltre sentirete
un bel beep del vostro speaker (A causa del '\a').
Passiamo ora ad un programma un po' più articolato:
il suo intento è di chiedervi di inserire il vostro
anno di nascita da tastiera e di calcolare quindi la vostra
età in un modo estremamente stupido (ossia sottrando
dall'anno corrente il vostro anno di nascita, se non avete
ancora compiuto gli anni sarà sbagliata, ma non importa!):
--- 01_eta.c -------------------------------------------------------------------------------------
#include <stdio.h>
int main (void) {
int nascita;
int eta;
printf ("Inserisci il tuo anno di nascita: ");
scanf ("%d", &nascita);
eta = 2002 - nascita;
printf ("Hai %d anni.\n", eta);
return (0);
}
--------------------------------------------------------------------------------------------------
Prima cosa da notare da questo programma e dal precedente:
tutte le righe finiscono con ";". Questa è
una caratteristica della sintassi del C, che non vi impone
di andare a capo dopo ogni "comando", ma semplicemente
di separarli con un ";". Quindi, in linea di massima,
nessuno vi vieterebbe di scrivere l'intero programma su
una sola riga, ma non sarebbe molto leggibile... e la leggibilità
è una caratteristica che i vostri programmi dovrebbero
sempre avere. Dimenticatevelo subito dunque ;).
Poi, questo programma utilizza 2 VARIABILI: nascita e eta.
Le variabili sono dati il cui contenuto può appunto
variare. In C, ogni variabile utilizzata in un programma
deve essere dichiarata all'inizio del programma stesso (non
è esattamente così ma per ora prendetelo per
buono). Per fare questo, si scrive il nome della variabile
preceduto da una keyword (parola riservata del linguaggio)
che ne identifica il tipo. In questo caso dovevamo memorizzare
dei numeri nelle nostre variabili, e quindi abbiamo utilizzato
il tipo "int". I tipi più comuni sono:
- int -> Intero "normale"
- float -> Un numero decimale ("con la virgola")
- double -> Come float ma con maggior precisione
- char -> UN singolo carattere
Per assegnare un valore ad una variabile, si usa l'operatore
"=", come potete notare dalla riga "eta =
...". Il valore assegnato ad una variabile può
essere immediato (Es: "eta = 25;") oppure il risultato
di una qualsiasi espressione, come nel nostro caso ("2002
- nascita" è l'espressione in questione). Le
regole che il C utilizza per valutare il risultato delle
espressioni sono le stesse che si usano in matematica, quindi
le moltiplicazioni (che si indicano con "*") e
le divisioni ("/") vengono effettuate prima delle
addizioni ("+") e delle sottrazioni ("-"),
a meno che non utilizziate le parentesi (solo tonde, scordatevi
le quadre e le graffe!). Manca l'operazione di elevamento
a potenza, o meglio, c'è, ma si effettua in un modo
diverso che al momento è meglio ignorare.
Esempio:
Se abbiamo dichiarato:
int diametro;
float circonferenza;
possiamo scrivere:
circonferenza = diametro * 3.14;
Se invece abbiamo:
int a, b, c, d;
(notate come non serva una riga per ogni variabile, se
il loro tipo è lo stesso. Ad esempio nel programma
di prima avremmo potuto scrivere semplicemente "int
nascita, eta;")
e scriviamo:
d = a + b * c;
quel che otteniamo è che PRIMA viene eseguito (b
* c), POI questo viene sommato ad a, ed il tutto viene assegnato
a d. Se volessimo eseguire prima (a + b) dovremmo scrivere:
d = (a + b) * c;
È molto più facile a farsi che a dirsi :D.
Oltre ai quattro operatori già citati, avete anche
l'operatore MODULO, che si indica con "%" e in
pratica vi dà il resto della divisione intera. Esempio:
int d1, d2, quoziente, resto;
d1 = 9;
d2 = 2;
quoziente = d1 / d2;
resto = d1 % d2;
questo farà sì che quoziente valga 4 (perchè
9 diviso 2 fa 4.5, ed essendo quoziente un intero, non può
contenere un numero con la virgola e quindi perde la sua
parte decimale. Ovviamente questo non accadrebbe se avessimo
dichiarato quoziente come float o come double) e resto valga
1 (perché 4 * 2 fa 8, e per arrivare a 9 manca ancora
1, che è appunto il resto della divisione di 9 per
2).
So che avete pensato "Ma il modulo non serve a niente!"
;). Be', non è così! L'operatore di modulo
è essenziale per almeno 2 scopi:
1. Verificare se un numero è pari: in caso affermativo
il resto della divisione per 2 deve essere 0:
- 4 % 2 fa 0, ed infatti 4 è pari;
- 75 % 2 fa 1, ed infatti 75 è dispari.
2. Verificare se un numero è divisibile per (o multiplo
di) un altro: anche in tal caso il resto deve essere 0:
- 100 % 25 fa 0, infatti 100 è un multiplo di 25;
- 6 % 4 fa 2, infatti 6 non è un multiplo di 4.
Qualche ultimo appunto sull'assegnazione di valori alle
variabili mediante espressioni: quando usate le espressioni,
il risultato viene assegnato alla variabile SOLO DOPO che
l'intera espressione è stata valutata, quindi potete
scrivere cose del tipo:
int i;
i = i + 1;
che farà sì che ad i venga assegnato il suo
valore aumentato di 1, perché l'espressione viene
valutata usando il corrente valore di i, e poi il suo risultato
venga assegnato ad i stessa.
Le variabili (e qualsiasi altra cosa!) in C sono CASE-SENSITIVE!
Quindi:
int pippo;
int PIPPO;
int PiPpO;
int pIpPo;
int PIppO;
...
sono TUTTE variabili diverse che possono tranquillamente
avere valori diversi. La regola pratica di base è
che TUTTE le variabili in C vengono scritte in MINUSCOLO.
Evitate quindi cose del tipo TimeOfDay, e usate tutt'al
più time_of_day. Notate che questa è una convenzione
di uso comune, non una regola esplicita.
Che nomi possono avere le variabili? Un nome qualsiasi,
composto però solo da:
- caratteri (a-z, A-Z);
- numeri;
- underscore ("_");
con il requisito aggiuntivo che il primo carattere non può
essere un numero, quindi nomi legali sono, ad esempio: antani,
_antani, antani99, a1b2c3, a_a_a_a, a1, _123 (di quest'ultimo,
a dire il vero, non sono sicuro :D), ma non 123antani o
123. Notate anche che il C vi garantisce che le variabili
siano distinte almeno in base ai loro primi 6 caratteri,
quindi a1, a2, a3 saranno sicuramente considerate variabili
diverse, mentre antani1, antani2, antani3 potrebbero essere
considerate tutte la stessa variabile da alcuni compilatori
(ignorate pure questo discorso, al giorno d'oggi dubito
che valga ancora...).
Torniamo ora al programma che calcola l'età: la prima
printf serve a stampare un messaggio affinché l'utente
sappia cosa deve fare, ossia inserire il suo anno di nascita.
Segue poi una scanf che serve ad effettuare l'inserimento.
Per capire come funziona, analizziamo prima la printf successiva
;):
printf ("Hai %d anni.\n", eta);
Quello che vogliamo fare qua è stampare il valore
di una variabile. In un primo impeto di pazzia potrebbe
venire in mente di scrivere:
printf ("Hai eta anni.\n");
In questo caso, quello che otterremmo sarebbe la scritta
"Hai eta anni.", perché, come abbiamo detto,
le stringhe vengono stampate pari pari, e comunque il compilatore
non potrebbe sapere se volessimo scrivere la scritta "eta"
o il valore della variabile con quel nome. Deve quindi esistere
un altro meccanismo: ogni volta che vogliamo stampare il
valore di una variabile, basta che nel corrispondente posto
nella stringa che passiamo a printf scriviamo "%d",
e passiamo poi la corrispondente variabile a printf dopo
la stringa, separata da una virgola. In pratica, il comportamento
di printf quando si trova un '%' in una stringa è
simile a quello di quando si trova una '\', ossia esso cambia
a seconda del carattere che segue: in questo caso tale carattere
cambia in rapporto al tipo di variabile di cui vogliamo
stampare il valore. La regola pratica è questa: quando
vogliamo stampare il valore di una variabile, prima di tutto
chiediamoci di che tipo è, e poi di conseguenza utilizziamo
una delle seguenti combinazioni al posto giusto:
- int -> %d
- float -> %f
- double -> %f (lo stesso di float)
- char -> %c
Esempio:
Vogliamo stampare il valore del "float circonferenza"
calcolato un po' sopra: esso è appunto un float e
quindi secondo la tabellina precedente dobbiamo utilizzare
"%f":
printf ("La circonferenza vale: %f.\n", circonferenza);
Possiamo stampare tutte le variabili che vogliamo, basta
utilizzare le combinazioni nello stesso ordine in cui diamo
le variabili, quindi:
int i1, i2;
float f1;
double d1;
char c1;
printf ("Valore di i1 = %d, valore di i2 = %d, valore
di f1 = %f, valore di d1 = %f, valore di c1 = %c\n",
\
i1, i2, f1, d1, c1);
Anche questo è molto più facile a farsi che
a dirsi ;). E anche in questo caso, se volessimo stampare
un semplice '%', basterebbe usare "%%", esattamente
come per "\\".
Ora sarà più semplice capire come funziona
l'inserimento di un valore da tastiera: tutto quello che
dobbiamo fare è utilizzare scanf, che funziona esattamente
come printf. Nell'ultimo esempio, volevamo far introdurre
un int, e quindi abbiamo utilizzato:
scanf ("%d", &nascita);
che è esattamente la stessa cosa che avremmo scritto
se avessimo voluto stampare il valore della variabile "nascita"
(utilizzando ovviamente printf al posto di scanf). Semplice
no? L'unica eccezione è la '&' prima di nascita,
che per ora vi conviene mettere senza sapere perché
è necessaria: usatela in ogni scanf e fidatevi ;).
Notate che proprio perché scanf funziona esattamente
come printf, è perfettamente legittima una cosa del
tipo:
int giorno, mese, anno;
printf ("Inserisci una data nel formato gg/mm/aaaa:
");
scanf ("%d/%d/%d", &giorno, &mese, &anno);
In questo caso le "/" presenti nella stringa di
scanf vengono ricercate tali quali nella stringa inserita
da tastiera, e vengono usate per assegnare correttamente
i valori alle varie variabili. Provare per credere!
Bene, per questa lezione è tutto! So che è
un po' lunga, ma, in fin dei conti, i concetti presentati
non sono poi molti, e sono basilari, tanto che se non ne
avessi parlato, probabilmente vi sareste lamentati che non
avreste potuto fare niente con quel che avete appena imparato
;). Per ora prendete per buono tutto quel che non ho commentato,
ne parlerò man mano nelle lezioni successive. Nella
prossima parleremo di "if" e dei cicli for/do/while,
ammesso che non cambi idea prima ;).
Sono ben accetti, per non dire richiesti, commenti, suggerimenti
e/o critiche, ed inoltre do la mia disponibilità
per aiutare quanti di voi avranno dei problemi a mettere
in pratica quello che cerco di insegnarvi. D'accordo che
non mi leggerà mai nessuno, ma io ci provo :D.
Vi lascio con un esercizietto che dovreste cercare di svolgere
entro la pubblicazione della prossima lezione, sulla quale
troverete comunque la mia soluzione (ahhh, quant'è
bello fare il prof una volta tanto!):
Scrivere un programma che permetta di inserire da tastiera
un'ora nel formato "hh:mm" e dica quanti minuti
sono passati da mezzanotte a quel momento. Ad esempio, inserendo
"5:35", il risultato corretto sarebbe: 5 * 60
+ 35 = 335.
### FINE LEZIONE 1 - Versione 1.0 (23/01/2003) ###
|