Introduzione al linguaggio C - Dipartimento di Informatica

Transcript

Introduzione al linguaggio C - Dipartimento di Informatica
Università degli Studi di Bari
Corso di Laurea in Informatica
Corso di Linguaggi di Programmazione
Corso C, sedi Brindisi e Corigliano
Introduzione al
linguaggio C
Pasquale Lops
Stefano Ferilli
Corrado Mencar
Obiettivi del corso
Fornire le conoscenze di base per la
programmazione nel linguaggio C
| Confrontare i costrutti del linguaggio C con
quelli del linguaggio Pascal
| Fornire gli elementi per sviluppare in C
mediante l’ambiente di sviluppo DEV-C++
|
|
Prerequisito: Conoscenza del Pascal
1
Testi consigliati
|
Linguaggio C (ANSI C) – II ed.
z
|
B.W. Kernighan, D.M. Ritchie (Jackson)
C Corso Completo di Programmazione
z
H.M. Deitel, P.J. Deitel (Apogeo)
Caratteristiche fondamentali
del C
Linguaggio imperativo
| Tra basso livello e alto livello
|
z
Costrutti di alto livello tipo Pascal
• Cicli, selezioni, funzioni, etc.
• Leggibilità e manutenibilità dei programmi
z
Costrutti di basso livello tipo Assembly
• Aritmetica degli indirizzi, enfasi sui puntatori,
corrispondenza con le istruzioni macchina
• Efficienza dei programmi
2
Caratteristiche fondamentali
del C
|
Tipizzazione debole
z
Controlli di tipo poco rigorosi
z
Possibili effetti indesiderati
• Utile per la programmazione di basso livello
• Scarsa manutenibilità
|
Portabilità
z
z
|
|
Assicurata dallo standard ANSI
Possibilità di sviluppare programmi non portabili
Nutrito insieme di librerie standard
Il C è case-sensitive
z
Parole chiave in minuscolo
Struttura di un programma
|
Pascal
Main program
|
Procedure
|
z
• Procedure
• …
• Funzioni
|
|
C
Funzione main
Funzione
…
Funzione
• …
z
Funzioni
• Procedure
• …
• Funzioni
• …
3
Struttura di un programma
Pascal
program nome-prog
dich-tipi
dich-variabili
dich-procedure-efunzioni
begin
istruzioni
end.
C
main() {
istruzioni
}
funzione-1
funzione-2
…
funzione-n
Struttura di un programma
|
Pascal
z
Struttura nidificata
|
C
z
• Astrazione funzionale
z
Apposita sezione
dichiarativa
• Visibilità: l’intera
procedura/funzione
• Leggibilità, controllo
Struttura appiattita
• Funzioni paritarie
z
Dichiarazioni sparse
• Visibilità: il blocco in cui
sono dichiarate
• Efficienza in spazio
4
Il più semplice programma C
main () {}
abbreviazione per:
int main (void) {}
|
Le funzioni restituiscono per default un intero
void
|
Parola chiave per specificare l’assenza di parametri
o di risultato
Funzioni
Pascal
function nome([var]
arg: tipo,…, [var]
arg: tipo): tipo;
dichiarazioni
begin … end;
|
Passaggio parametri
z
|
tipo nome(tipo arg,
…,
tipo arg)
/* dichiarazioni nel
corpo */
{ … }
|
riferimento o valore
Valore di ritorno
z
C
nome := valore
Passaggio parametri
z
|
valore
Valore di ritorno
z
return valore;
5
Tipi semplici
Pascal
C
Integer
int
Real
float, double
Boolean
--
Char
char
Modificatori di tipo
|
Ampiezza
char (8 bit) < short (16 bit) < int < long (32 bit)
float < double < long double
• Possono coincidere con 1, 2 o 3 ampiezze diverse
|
Segno
signed/unsigned
• Applicabili a char e int
• Estensione del segno
6
Il pre-processore
|
Direttive
#include “nomefile”
#include <nomeheader.h>
z
Inclusione di file esterni
• I file di intestazione raccolgono dichiarazioni di costanti e
funzioni definite in altri moduli
#define NOME espansione
z
Definizione di costanti simboliche
• Prima della compilazione tutte le occorrenze di NOME
vengono sostituite da espansione
Variabili - Costanti
Pascal
var id: tipo;
| Dichiarazione obbligatoria
z
z
C
tipo id [= valore];
| Dichiarazione obbligatoria
Globali se dichiarate nel
programma principale
Solo dichiarazione e non
inizializzazione
const id = valore;
z
z
Globali se dichiarate fuori
dalle funzioni
Possibile inizializzazione
const tipo id = valore;
|
|
Costanti matematiche:
<float.h>
Costanti di piattaforma:
<limits.h>
7
Costanti enumerative
enum nome { ID [= valore], …, ID [= valore] };
|
Valori non necessariamente distinti
z
z
|
|
Valori progressivi dall’ultimo specificato
Se non specificato, il primo valore è 0
Nomi diversi in enumerazioni distinte
Esempio
z
enum mesi {GEN=1, FEB, MAR…}
Istruzioni
|
Pascal
z
z
; separatore
Funzioni elementari
predefinite
• I/O di base
• matematiche
z
(* … *), { … }
|
C
z
; terminatore
Nessuna funzione
predefinita
#include <stdio.h>
#include <math.h>
z
/* … */
z
z
z
8
Assegnamento
Operatori aritmetici
C
Pascal
| :=
|
var := var op espr
var := var + 1
var := var - 1
|
|
|
=
var = var op espr
var op = espr
var++
++var
var---var
|
+, -, *
/, div
mod
|
|
+, -, *
/
%
Operatori relazionali
Operatori logici
|
Pascal
z
z
z
z
z
z
|
C
=
<>
<, <=, >, >=
z
not
and
or
z
z
z
z
z
==
!=
<, <=, >, >=
!
&&
||
9
Puntatori
&variabile
z
Indirizzo in memoria di variabile
• Utilizzabile per il passaggio di parametri per riferimento
*puntatore
z
Valore contenuto all’indirizzo di memoria puntatore
• * operatore di “indirezione”
tipo *puntatore
z
*puntatore è di tipo tipo, ossia
puntatore è l’indirizzo di un valore di tipo tipo
Puntatori - Esempio
int x = 1,
int *ip;
ip = &x;
y = *ip;
*ip = 0;
ip = &z[0]
|
y = 2, z[10];
/* ip puntatore ad un intero */
/* ip punta ad x */
/* y vale 1 */
/* x vale 0 */
/* ip punta a z[0] */
Esempi di costrutti validi:
*ip = *ip + 10;
*ip += 1; ++*ip;
y = *ip + 1;
(*ip)++
10
Procedura di scambio di
valori
void swap(int *x, int *y) {
int temp;
temp = *x;
*x = *y;
*y = temp;
}
|
Viene chiamata con i riferimenti: swap(&a, &b);
I/O base
|
Pascal
z
write(…)
|
C
z
• writeln(…)
z
read(…)
printf(“…”, …)
• printf(“…\n”, …)
z
scanf(“…”, …)
11
Funzioni di I/O base
printf(“formato”, parametro, …, parametro)
scanf(“formato”, &parametro, …, &parametro)
|
formato è la stringa da stampare/leggere
z
z
Possibilità di inserire caratteri speciali
Segnaposto per i parametri da stampare/leggere
• Corrispondenza fra numero e tipo dei segnaposto e
sequenza dei parametri
z
Numero di spaziature ignorato in lettura
Caratteri speciali
|
Sequenze di escape
z
z
z
z
z
z
z
z
\n
\t
\v
\b
\”
\’
\?
\\
a capo
tab orizzontale
tab verticale
cancellazione
doppi apici
apice singolo
punto interrogativo
barra rovesciata
|
Segnaposto parametri
z
z
z
z
z
z
z
%d decimale
%i intero
%f virgola mobile
%e esponenziale
%c carattere
%s stringa
%% stampa ‘%’
12
Programma di benvenuto
#include
<stdio.h>
main () {
printf(“Salve, mondo\n”);
}
#include <stdio.h>
main () {
printf(“Salve, ”);
printf(“mondo”);
printf(“\n”);
}
Somma e media di due
valori
#include <stdio.h>
main() {
int a,b,s;
printf(“Inserisci due numeri interi:\n”);
scanf(“%d %d”,&a,&b);
s = a + b;
printf(“Somma = %d\tMedia = %f\n”,s,s/2.0);
}
13
Sequenza
Pascal
begin …
end[;]
C
{ … }
|
Località delle
variabili
Selezione binaria
|
Pascal
z
if condizione then
istruzione/sequenza
[else
istruzione/sequenza
]
z
condizione è una
espressione booleana
|
C
z
|
if (condizione)
istruzione/sequenza
[else
istruzione/sequenza
]
condizione è
un’espressione che
restituisce un numero intero
z
Se il risultato è zero, la
condizione è falsa,
altrimenti è vera
14
Parità di un intero
#include <stdio.h>
main() {
int n;
printf("Inserisci un intero: ");
scanf("%d",&n);
if (n % 2 == 0)
printf("%d e' pari\n",n);
else
printf("%d e' dispari\n",n);
}
Selezione multipla
Pascal
C
case espressione of
valori: istruzione;
…
valori: istruzione[;
otherwise istruzione]
end;
switch (espressione)
{
case costante:
istruzione
[break;]
…
case costante:
istruzione
[break;]
default: istruzione
}
15
Stampa numeri
#include <stdio.h>
main() {
char n;
printf("Inserisci il numero 1 o 2: ");
scanf("%d",&n);
switch (n) {
case 1: printf(“Uno\n");
break;
case 2: printf(“Due\n");
break;
default: printf(“Numero non riconosciuto\n",n);
}
}
Segno di un intero
#include <stdio.h>
main() {
signed int n;
printf("Inserisci un intero: ");
scanf("%d",&n);
if (n > 0)
printf("Positivo\n");
else if (n < 0)
printf("Negativo\n");
else
printf("Nullo\n");
}
16
Iterazione
|
Pascal
while condizione do
istruzione
|
C
while (condizione)
istruzione
repeat
istruzione
until condizione-falsa
do {
istruzione
}
while condizione-vera
Conto alla rovescia
#include <stdio.h>
main() {
int n = 10;
while (n != 0)
{
printf("%d\n",n);
n--;
}
printf(“GO!\n");
}
17
Inserimento di valori negativi
#include <stdio.h>
main() {
signed int n;
do {
printf("Inserisci un intero negativo: ");
scanf("%d",&n);
}
while (n >= 0);
}
Iterazione
Pascal
for ind := inf to sup
do
istruzione;
≡
ind := inf;
while ind <= sup do
begin
istruzione;
ind := ind + 1
end;
C
for (espr1; espr2; espr3)
istruzione
≡
espr1;
while espr2
{
istruzione;
espr3;
}
18
Calcolo dei primi n numeri
dispari
#include <stdio.h>
main() {
int n;
printf(“Quanti numeri devo generare?\n”);
scanf(“%d”,&n);
for(int i=0; i<n; i++)
printf(“%6d.%10d\n”,i+1,2*i+1);
}
Vettori
Pascal
var:
array[dim] of tipo;
|
Indici enumerativi
z
|
C
tipo var[[dim]]
[= {val, …, val}];
|
Intervallo a piacere
Accesso:
variabile[ind]
Indici interi
z
Partono sempre da 0
|
In C var ≡ &var[0]
|
Accesso:
variabile[ind]
19
Vettori multidimensionali
Pascal
var:
array[dim,…,dim]
of tipo
|
Accesso:
var[ind,…,ind]
C
tipo
var[[dim]]…[[dim]]
[= {{val, …, val},
…, {val, …, val}}]
|
Accesso:
var[ind]…[ind]
Strutture
Pascal
variabile: record
id: tipo;
…
id: tipo;
end;
|
Accesso:
variabile.id
C
struct [nome] {
tipo id;
…
tipo id;
} [variabile = {val,
…, val}];
|
Accesso:
variabile.id
20
Strutture
p
z
Puntatore a struttura
z
Contenuto della struttura
*p
(*p).el
z
abbreviato in
p->el
Elemento della struttura
Definizione di nuovi tipi
typedef tipo Nome;
|
Semplici sinonimi di tipi esistenti
z
|
Possibilità di dare un nome a tipi complessi
Interpretata dal compilatore (a differenza
della #define)
Parametrizzazione di programmi (portabilità)
z Significatività dei nomi (documentabilità)
z
21
Forzatura di tipi
(tipo) espressione
Operatore di “Cast”
| Forzatura di un valore ad un tipo
|
z
Il tipo deve essere compatibile col valore
Input & Output (I/O)
Gestione dell’I/O tramite funzioni delle
librerie standard
| Input e Output realizzato attraverso flussi
|
Flusso (stream) = sequenza ordinata di byte
z FILE = sorgente o destinazione di un flusso
z Un FILE in C può essere:
z
• Un file del sistema operativo
• Una periferica (tastiera, monitor, stampante, etc.)
22
Flussi standard
|
stdin (standard input)
z
z
|
stdout (standard output)
z
z
|
Flusso di dati verso lo schermo
Scrittura del flusso mediante printf(…)
stderr (standard error)
z
z
|
Flusso di dati proveniente dalla tastiera
Lettura del flusso con la funzione scanf(…)
Flusso di dati verso una periferica per la notifica di
errori
Spesso stdout = stderr
Libreria per l’uso dei flussi standard: stdio.h
I formati di file
|
Testuale
File definito da linee di caratteri stampabili,
separate da ‘newline’ (‘\n’)
z Esempi: documenti di testo (txt), codice
sorgente
z
|
Binario
File definito da qualunque sequenza di byte
z Esempi: immagini, file eseguibili, etc.
z
23
La gestione dei flussi
|
Struttura dati FILE
Definita nella libreria stdio.h
z Contiene le informazioni necessarie
all’accesso (lettura e/o scrittura) ad un flusso
z Di norma, non si accede direttamente alle
informazioni contenute nella struttura, ma
essa viene passata come parametro nelle
funzioni per l’I/O
z
Apertura e chiusura di file
|
|
|
|
Aprire un file = abilitare un flusso di dati
Esempio in C:
z FILE* fp;
z fp = fopen(nomefile, mode);
Modalità di apertura (mode)
z “r”: lettura da file testuale
z “w”: scrittura di nuovo file testuale
z “a”: scrittura (append) su file testuale esistente
z “r+”: lettura/scrittura su file testuale esistente
z “rw”: lettura/scrittura su nuovo file
z mode+”b” (es. “wb”): accesso a file binario
Chiusura di un file = disabilitare un flusso di dati
z fclose(fp);
24
Lettura e scrittura per
caratteri
|
char fgetc(FILE*)
z
|
fputc(char, FILE*)
z
|
Legge un carattere da un flusso
Scrive un carattere in un flusso
feof(FILE*)
Verifica se un flusso è terminato o no
z Vale per tutti i tipi di flusso
z
Lettura e scrittura per linee
di testo
|
char* fgets(char* s, int n, FILE*
stream)
Legge una linea di testo (cioè fino alla
prossima newline) e la memorizza in s.
z Il numero massimo di caratteri che possono
essere letti è stabilito da n
z
|
fputs(char* s, FILE* stream)
z
Scrive una linea in un testo
25
Lettura e scrittura formattata
|
fscanf(FILE* f, char* format, vars)
z
z
|
Legge dal file testuale f e valorizza le variabili in vars
secondo il formato specificato in format
Esempio: fscanf(f,”%d %c”, &v1,&v2) legge
da f un decimale (%d) che memorizza in v1 e un
carattere (%c) che memorizza in v2
fprintf(FILE* f, char* format, vars)
z
z
Scrive nel file f la stringa specificata nel formato con i
valori delle variabili specificate
Esempio: fprintf(f,”%d %c”, v1, v2) scrive
in f i valori di v1 e v2 separati da uno spazio.
Altre modalità di lettura e
scrittura
|
Per blocchi (file testuali)
fread / fwrite
z Utili per la lettura/scrittura di record
z
|
Accesso diretto
z
fseek / ftell
26
La libreria standard
|
assert.h
z
|
Gestione delle asserzioni. Utile per verificare
la correttezza semantica dei programmi
ctype.h
z
Gestione dei caratteri
• Riconoscimento di categorie di caratteri (p.e.
maiuscole, minuscole, cifre, punteggiatura, etc.)
• Trasformazioni di caratteri (p.e. minuscolo Æ
maiuscolo)
La libreria standard
|
limits.h
z
|
math.h
z
|
Dimensioni dei tipi di dati dipendenti
dall’implementazione
Funzioni matematiche complesse
stdio.h
z
Funzioni per l’input e l’output
27
La libreria standard
|
stdlib.h
z
|
string.h
z
|
Funzioni di utilità generale (p.e. generazione
di numeri pseudo-casuali, conversione da
testo a numeri, etc.)
Gestione delle stringhe di testo (copia,
concatenazione, confronto, etc.)
time.h
z
Gestione delle informazioni temporali
28