Introduzione al c
-
Upload
markonline-staff -
Category
Documents
-
view
243 -
download
0
description
Transcript of Introduzione al c
1
Introduzione al Linguaggio C
Overview
Linguaggio general purposeProcedurale (a differenza di Java che e’ object-oriented)
C++ è l’estensione OO del CApplicazioni: compilatori, sistemi operativi, grafica, giochi, sistemi embedded
Cosa hanno in comune queste applicazioni?Limitato set di keyword (32) Da un lato, linguaggio di alto livello
Costrutti di controllo del flusso (simile a Java)Funzionalità di basso livello
Gestione diretta della memoriaManipolazione di indirizzi
2
Linguaggio di per se’ limitato
Utilizzo di funzioni di libreriaAssenza di operatori predefiniti per oggetticomplessi (stinghe, strutture dati)Utilizzo di funzioni di libreria per l’I/O
Le funzioni piu’ comuni sono contenute in una libreria standard (circa 150 funzioni)
Buona portabilità a livello di codice sorgenteMa questo dipende dalle librerie che usiamo… e dall’uso di dialetti
Perche’ studiare il C (dopo Java)?
Linguaggio al tempo stesso di alto e basso livelloMaggior controllo degli aspetti di basso livelloIn generale, migliori performance rispetto a Java
Anche se Java e’ migliorato tantissimo negli ultimi anni
Pero’:Saremo responsabili della gestione della memoriaIl linguaggio ci lascera’ fare molte cose che Java ciproibiva (e.g. conversioni implicite tra tipi)Maggiori possibilita’ di errori
3
Principali similitudini con JavaOperatori
Aritmeticiint i = i+1; i++; i--; i *= 2;+, -, *, /, %,
Relazionali e logici<, >, <=, >=, ==, !=&&, ||, &, |, !
Sintassi, strutture di controlloif ( ) { } else { }while ( ) { }do { } while ( );for(i=1; i <= 100; i++) { }switch ( ) {case 1: … }continue; break;
Cenni storici - I
Il linguaggio C è stato sviluppatointorno al 1972 nei Bell Laboratories AT&T americani, Dennis Ritchie.E’ nato come linguaggio di sviluppo del Sistema Operativo UNIX.Gli antenati del C possono essere riunitiin linea genealogica:
Algol 60 1960 (Comitato Int.)CPL 1963 (Cambridge)BCPL 1967 (Cambridge)B 1970 (Thompson)C 1972 (Ritchie)
4
Cenni storici
AlgolLinguaggio modulare e con sintassi regolareAbbastanza complesso
CPL (Combined Programming Language) e BCPLMigliorano le caratteristiche di AlgolAncora pero’ molto complessi
BLinguaggio vicino alla macchinaSviluppato per lo UNIX del DEC PDP-7Non tipato
CInclude le migliori caratteristiche dei linguaggi sopra citati
Cenni Storici - III
1983: l’American National Standards Institute(ANSI) ha iniziato i lavori per la definizione dell’ANSI C1983: Bjarne Stroustrup (Bell Labs) sviluppa il C++ a partire da C e Smalltalk
Paradigma di programmazione a oggettiNato come preprocessore per il C
1988: nasce l’ANSI C1999: Versione corrente dell’ANSI C (ANSI C 99)
Alcune modifiche sostanziali rispetto alle versioniprecedentiE.g. dichiarazione variabili in qualsiasi statementTipi boolean, complexDichiarazione variabili nelle strutture di controllo
5
Perché programmare in C
Portabilità del codice e del compilatoreCodice generato molto efficienteFacilità di accesso al livello “macchina”Interfacciamento completo al S.O. UNIXNon complesso
Struttura dei Programmi
- Un programma è formato da uno o piùblocchi chiamati funzioni
- Una funzione è formata da un insieme diuna o più istruzioni
Esempio:#include<stdio.h>main() /* esempio di programma C */{
printf(“Hello World!\n”);}
6
Commenti
#include<stdio.h> Direttiva di preprocessore (include file .h)/* */ Apertura e chiusura di un commento
main() Nome di funzioneMain e’ la funzione chiamata quandosi invoca un programma
{ Inizio corpo funzioneprintf(“Hello World\n”); Invocazione funzione printf
} Fine corpo funzione
Strumenti
Quello che vi occorre è Un compilatore C (ANSI C compatibile!!)Un editor di testo
Io uso Emacs….http://www.gnu.org/software/emacs/http://www.xemacs.org/Download/win32/Altro editor: VI http://www.vim.org/
GCC – GNU C CompilerDistribuito con tutte le distribuzioni di LinuxSe avete una macchina con Linux il gioco è fatto…
Alcune distribuzioni consentono il boot da USB stick…MAC OS – XCode
http://developer.apple.com/technologies/tools/xcode.html
7
CygWin
Suite di utility Unix per sistema operativoWindows
Inclusa una shell UnixIncluso il compilatore GCC
Download all’indirizzohttp://www.cygwin.com/
Cygwin - Download
8
Cygwin - Download
Cygwin - Download
9
Cygwin - Download
Cygwin - Download
10
Eclipse CDT
http://www.eclipse.org/cdt/Ambiente integratoSyntax highlighting, debugger integratonell’editor…Appropriato se siete gia’ abituati a lavorare con Eclipse (JDT)
Sovrapponibile.. scaricate versioni compatibili (Helios) dientrambi e scompattateli nella stessa dir…
Abituatevi anche e soprattutto ad usarecompilatore e altri strumenti da riga dicomando!!!
Eclipse CDT
11
Programmare in C in <120 min.
Viewer discretion is advised
Compilazione di un programma C
Il codice sorgente puòessere altamenteportabileLa compilazioneproduce un eseguibile
In linguaggiomacchina, quindieseguito direttamentedalla macchinaDipendentedall’architettura e dalS.O.
Invece, Java produce bytecode
Eseguito dalla Java Virtual MachineIndipendentedall’architettura e dalS.O.
Source codeHello.c
Preprocessed codeHello.i
Object moduleHello.o
ExecutableHello / Hello.exe
Librerie
Informazioni dirilocazione
Altriobject module
Preprocessore
Compilatore
Linker
Assembly codeHello.s
Assemblatore
12
Il preprocessore
Trasforma il file sorgente inizialeprocessando direttive del preprocessoreIniziano con “#”, eg.
#define definizione di costanti/macro#include inclusione di altri sorgenti#if #else #endif compilazione condizionale
Compilazione ed esecuzione
cc ciao.cO anche gcc ciao.cSpesso cc e’ un link simbolico (alias) di gcc
Produrra’ il file eseguibile a.outa.exe con Cygwin
Per eseguirlo:./a.out
Hello World
13
Alcune opzioni GCC
gcc –Wall –pedantic –ansi ciao.c –o ciao.out
-Wall produce tutti I possibili warning (usatelo!)-ansi evita che usiate codice non-ANSI
e.g. parte del dialetto GCC-pedantic visualizza tutti i warning circa la compliance ISO C-o file_output specifica il nome del file eseguibile
Ritorno a capo
La funzione printf non genera un carattere diritorno a capo al termine della stringa
Come System.out.print, non come System.out.printlnOccorre stampare esplicitamente un caratterespeciale ‘\n’Qual’e’ la differenza tra questi due programmi?
main(){printf(“ciao”);printf(“mondo”);printf(“\n”);
}
main(){printf(“ciao mondo \n”);
}
14
Un programma (un po’) piu’ complesso…
Conversione da °C a °F°C = (5/9)(°F-32)
Output
1 -1720 -640 460 1580 26100 37120 48140 60160 71180 82200 93220 104240 115260 126280 137300 148
15
Dichiarazione di variabili
int fahr, celsius;int lower, upper, step;
Nome del tipo seguito da lista di nomi divariabili (identificatori)Tipo int: intero
Numero di bit machine dependent, spesso 16 bit [-32768, +32767]Che tipo di rappresentazione numerica è usata?
printf..
printf("%d\t%d\n", fahr, celsius)
Stampa il valore della variable fahrStampa un carattere \t (tabulazione)Stampa il valore della variable celsiusStampa un ritorno a capo \n
"%d\t%d\n“ e’ una stringa di formattazione%d in posizione i-esima indica che va prodottol’output (come decimale intero) della i-esimavariabile nella lista dopo la stringa diformattazione
16
Giustificazione numeri…
L’output prodotto in precedenza contenevaprintf("%3d %6d\n", fahr, celsius);
Riserva 3 cifre per fahr e 6 per celsius
Problema
Le temperature °F sono interi a intervalli di 20Le conversioni °C sono troncate all’interoinferiore → non molto preciseDobbiamo utilizzare variabili floating pointfloat fahr, celsius
Tipicamente a 32 bit
17
Programma rivisitato
#include <stdio.h>main(){
float fahr, celsius;float lower, upper, step;
lower = 0; /* lower limit of temperatuire scale */upper = 300; /* upper limit */step = 20; /* step size */fahr = lower;while (fahr <= upper) {
celsius = (5.0/9.0) * (fahr-32.0);printf("%3.0f %6.1f\n", fahr, celsius);
fahr = fahr + step;}
}
Cosa notiamo di diverso?
float fahr, celsius;float lower, upper, step;
Dichiarazione di variabili di tipo float
celsius = (5.0/9.0) * (fahr-32.0);Perche’ 5.0 9.0 32.0?Come vedremo, il C effettua una conversione implicita5 e 9 sarebbero trattate come costanti intere
Il risultato di 5/9 sarebbe troncato all’intero inferiore (0)
Se scrivevamo fahr-32?fahr e’ float32 interoIn questo caso il C avrebbe convertito tutto al tipo float (+ preciso di int)Quindi andava bene, ma meglio far vedere esplicitamente che 32 e’ float
Questo problema sarà affrontato in dettaglio piu’ avanti nelcorso…
18
printf: stringhe di formattazione per numeri
printf("%3.0f %6.1f\n", fahr, celsius);
%3.0f fahr e’ stampato utilizzando spazio x 3 caratteri di ampiezza senza decimali%6.1f celsius e’ stampato utilizzando spazio x 6 caratteri di ampiezza, incluso 1 decimale
printf: riepilogando…
%d Intero in notazione decimale%4d Intero in notazione decimale, 4 caratteri%f Float%.2f Float, 2 caratteri dopo il punto decimale%6.2f Float 6 caratteri di cui 2 dopo il punto decimale
Ve ne sono altre (%o ottale, %x esadecimale, %ccarattere, %s stringa)Usate printf(“%%”) per stampare un carattere“%”
19
Il costrutto FOR
#include <stdio.h>
main(){int fahr;for (fahr = 0; fahr <= 300; fahr = fahr + 20)
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
Come funziona la struttura iterativa FOR?Ricordate da Java…
Dichiarazione di costanti
Utilizzo della direttiva di preprocessore #define
#define nome testo_da_sostituire
Il preprocessore analizza il programma e rimpazza ogni occorrenza dinome con testo_da_sostituire
#include <stdio.h>
#define LOWER 0 /* lower limit of table */#define UPPER 300 /* upper limit */#define STEP 20 /* step size */
/* print Fahrenheit-Celsius table */
main(){int fahr;for (fahr = LOWER; fahr <= UPPER; fahr = fahr + STEP)printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
20
Output preprocessore
gcc -E fahr4.c –o fahr4.iEsegue solo lo step di preprocessore del compilatore(ricordate?) e produce il file fahr4.i
Output (la parte superiore contiene stdio.h)…main(){int fahr;for (fahr = 0; fahr <= 300; fahr = fahr + 20)printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
Lettura e scrittura di caratteri
Impariamo a realizzare semplici “filtri”Programmi che leggono una sequenza dicaratteri e producono in output unasequenza di caratteri
c=getchar() Legge un carattere dal canale standard di input
putchar(c)Scrive il carattere c sul canala standard di output
21
Copia di un file
leggo un carattere;while(il carattere letto non è il carattere di fine file)
{stampo il carattere;leggo il carattere successivo;
}
In C (libreria stdio.h) il carattere di fine file è rappresentato mediante EOF
Copia di un file - Implementazione
#include <stdio.h>
main(){int c;c = getchar();while (c != EOF) {putchar(c);c = getchar();
}}
Notate qualcosa di strano?
22
int c?
Assegniamo un carattere a una variabile int?In realtà, in C esiste il tipo char
tipicamente 8 bitdi fatto è trattato come intero
Il C consente assegnazioni tra tipi eterogeneiCosa accade?
int c=‘a’;
char c=‘a’;
(Le costanti char si sono rappresentate da caratteri tra singoli apici)printf(“%d”,’a’) stampa il valore 97Come vedete.. è possibile fare di tutto… a vostro rischio e pericolo
1000011000000000
10000110
Il codiceASCII di ‘a’ è 97
Il codiceASCII di ‘a’ è 97
Quindi…
Quindi meglio dichiarare char c?Beh… il fatto è che EOF è una costante intche indica la fine del file
In alcune architetture la dimensione dell’intpotrebbe essere >255Quindi è safer utilizzare intAnche se nella maggior parte dei casi char vabene
23
Versione compatta!
#include <stdio.h>main(){
int c;while ((c = getchar()) != EOF)
putchar(c);
}
Come lo usiamo?
In una shell Unix, se invochiamo un comando seguito da <filename→ il comando considera come canale diinput standard il fileSe invochiamo un comando seguito da>filename→ il comando produce l’output su file
./copyfile <file1 >file2
24
Confronto (!=) ha precedenzasu assegnazione (=)
#include <stdio.h>main(){
int c;while (c = getchar() != EOF)
putchar(c);}
Cosa accade?c = getchar() != EOF equivale a c = (getchar() != EOF)Il risultato di un’ espressione booleana è 0 se falso, 1 se vero…Quale sarà l’output del programma?
Ora provate voi…
Scrivete un programma per il conteggio deicaratteri contenuti in un file…
25
Altro esercizio…
Stampiamo i codici ASCII di tutti i carattericontenuti in un file…
Stampiamo tutte le ‘a’ contenute in un file
#include <stdio.h>main(){
int c;while ((c = getchar()) != EOF){if(c==‘a’)putchar(c);
}}
26
Esercizio
Contiamo le righe di un fileCome?
Ogni riga termina col carattere di ritorno a capo ‘\n’
Vettori (array) in C
Dichiarazione array:tipo identificatore[dimensione]
Esempio:int ndigit[10]
Come in Java l’accesso agli elementi del vettore avviene mediante indici interindigit[0], ndigit[1], … , ndigit[9]
27
Esempio
Contiamo cifre, spazi bianchi e altri caratteriin un testoCi occorrono:
Una variabile per contare gli spazi bianchiint nwhite;
Una per contare gli altri caratteriint nother;
10 variabili per contare 0, 1,…9,Beh, un vettore di 10 interi…int ndigit[10];
Codice…#include <stdio.h>main(){
int c, i, nwhite, nother;int ndigit[10];
nwhite = nother = 0;for (i = 0; i < 10; ++i)
ndigit[i] = 0;
while ((c = getchar()) != EOF)if (c >= '0' && c <= '9')
++ndigit[c-'0'];else if (c == ' ' || c == '\n' || c == '\t')
++nwhite;else
++nother;
printf("digits =");for (i = 0; i < 10; ++i)
printf(" %d", ndigit[i]);printf(", white space = %d, other = %d\n",nwhite, nother);
}
28
Inizializziamo le variabili
nwhite = nother = 0;for (i = 0; i < 10; ++i)
ndigit[i] = 0;
L’inizializzazione è fondamentale in CA differenza di Java, l’inizializzazione a zero non è garantita!
Leggiamo I caratteri fino alla fine del file
while ((c = getchar()) != EOF)if (c >= '0' && c <= '9')++ndigit[c-'0'];
else if (c == ' ' || c == '\n' || c == '\t')++nwhite;
else++nother;
if (c >= '0' && c <= '9') restituisce true se ilcarattere è compreso tra 0 e 9C-’0’ vale 0 se c==‘0’, 1 se c==‘1’, etc.Quindi ndigit[c-’0’] punta all’elemento del vettorecorrispondente alla cifra++ndigit[c’-0’] incrementa il numero di cifre…
Che differenza c’e’ tra ++ndigit[c-’0] e ndigit[c-’0]++?
29
Infine..
Stampiamo il risultato:printf("digits =");for (i = 0; i < 10; ++i)printf(" %d", ndigit[i]);
printf(", white space = %d, other = %d\n",nwhite, nother);
Object-oriented programming…
Avete studiato JavaLinguaggio OOIl funzionamento di un programma avvenivamediante scambio di messaggi tra oggetti
obj
obj
obj obj
obj
op
op
op
op
op
op
op
30
Linguaggio procedurale…
C è un linguaggio proceduraleIl programma è costituito da un insieme di unitàfunzionali dette funzioniFunzioni in Fortran, procedure in Pascal
Una funzione:riceve zero o piu’ parametri in ingressoEsegue un task specificato da una sequenza distatement (come nel caso di un metodo)
Eventualmente invocando altre funzioniInfine, termina
Eventualmente, ritornando un risultato in uscitaEventualmente, modificando i parametri in ingresso
Programmazione procedurale
main()
foo()
bar()
fun()
ff()
31
Esempio#include <stdio.h>
int power(int m, int n);
main(){
int i;for (i = 0; i < 10; ++i)printf("%d %d %d\n", i, power(2,i), power(-3,i));
return 0;}
int power(int base, int n){
int i, p;p = 1;for (i = 1; i <= n; ++i)p = p * base;
return p;}
Dichiarazione funzione power
Definizione funzione main
Definizione funzione power
Call graph
main()
power()
printf()
32
Definizione funzione
tipo_ritorno nome_funzione(parametro1, parametro2,…){statement…
}
Se ometto tipo_ritorno, si assume che sia intInfatti main ritorna int…
Una funzione potrebbe non avere tipo di ritornoIn tal caso come dovrei dichiarare la funzione?
Posso omettere i parametritipo_ritorno funzione(){}
Dichiarazione funzione
In C le funzioni devono essere dichiarate prima dipoter essere usateSiccome power è definita dopo main, ilcompilatore non l’avrebbe trovata durante la compilazione di main
Anche se tale dichiarazione è opzionale nei compilatoriANSI 99Warning visibili solo con -Wall
Quindi, è necessaria una dichiarazionetipo_ritorno nome_funzione(lista_parametri);Nota anche come prototipo della funzione
33
Prototipo funzione
Lista parametri può esseretipo1 nome1, tipo2 nome2…..oppure è lecito anche scriveretipo1, tipo2..e.g. int power(int, int)Ma è meno comprensibile
Return
Sintassireturn espressione;return;
Non ritorna nulla…
Anche la funzione main può ritornare un valoreInfatti è definita come funzione con tipo di ritorno intValore usato dal sistema operativoDiverso da zero → codice di errore
34
Passaggio parametri per valore
Parametri passati alle funzioni tramite variabiliprovvisoriePossono essere usate come variabili locali nellafunzione
E quindi modificate
Ma la variabile passata nella funzione chiamanteresta inalterataVi sono eccezioni
Quando passo un vettore, passo l’indirizzo del primo elementoLe vedremo in seguito
Passaggio parametri - esempio
#include <stdio.h>
int fact(int n);
main(){
int i;for (i = 0; i < 5; ++i)
printf("%d e' il fattoriale di %d\n", fact(i),i);return 0;
}
int fact(int n){
int result=1;while(n>0)
{result*=n;n--;
}return result;
}
i viene stampato dopo aver invocato factMa il parametro n è decrementato dentro factNo problem, il valore di inon cambia in main!
35
Vettori di caratteri
A differenza di Java il C non ha un tipo stringaLe stringhe sono trattate come array di caratterichar msg[10]; /*array di caratteri, lunghezza 10*/
char [] = “Ciao Mondo”/* Inizializzazione con una stringa costante */
Notare l’assenza di dimensione
OAIC
Carattere di fine stringa
Molte funzioni richiedono stringhe (array di caratteri) come inputProblema: come facciamo a conoscere la lunghezza dellastringa?Non esiste una funzione che ci dica la lunghezza di un array (come length in Java!)Inoltre, quando accedo ai singoli elementi, C non mi proibisce diandare oltre il limite!
→ Per convenzione, quando creiamo una stringa in C aggiungiamo un carattere di terminazione ‘\0’ al terminedell’array
Quando assegniamo una costante stringa a un array ciòavviene automaticamente
\0OAIC
36
Stampa di una stringa…
#include<stdio.h>
main(){char str[] = "Ciao Mondo!";printf("%s\n",str);
}
Esercizio
Scriviamo un programma che calcoli la lunghezza di una stringa