Laboratorio di Programmazione.
AA 2005/06.
Esercitazione n. 2
Scopo di questa sessione è di continuare
ad esercitarsi con l' interprete di comandi
(bash) in ambiente UNIX, apprendere il ciclo basilare
di scrittura di semplici programmi C, loro
compilazione ed esecuzione. I programmi si limitano a leggere un input
e mostrare l' output, eventualmente dopo semplici elaborazioni
Già così si dispone di un potente strumento di calcolo.
- Creare una directory di nome Labo2 e ridefinirla come
directory di default (comando cd, v. esercitazione n.1).
- Nella directory Labo2 creare una sottodirectory di
nome dir e scrivervi 5 files con nomi a piacere.
Usare quindi i seguenti comandi di shell (bash):
cd ~/Labo2/dir # cambia la working directory
ls -l # lista tutti files presenti
n=0 # azzera la variabile n (contatore)
elenco_files=* # il carattere speciale * viene sostituito dai
# nomi di tutti i files presenti nella directory
# corrente
for nome in $elenco_files # itera su tutti i nomi dei files (ogni volta
# la variabile "nome" assume un diverso valore)
do
if ( [ ! -d $nome ] ) # quel che segue fino a fi viene eseguito solo
then # se il file di nome $nome NON (!) e'una dir
n=$[$n+1] # il contatore viene incrementato
mv $nome $nome.$n # si cambia nome a ciascun file aggiungendo al vecchio nome un intero progressivo
fi
done # fine del blocco da iterare
pwd # scrive la dir corrente
a=4 # attribuisce 4 come valore della variabile a
echo $[$a*2] # valuta il prodotto del valore di a per 2 e lo mostra su schermo
- Quale e' la directory corrente dopo aver eseguito i
comandi precedenti (pwd)?
Inserire le
linee precedenti in un file di nome script
nella directory di default, dare in permesso di esecuzione a quel file
( chmod u+x script ) ed
eseguirlo dalla directory di default
(./script
ricordare di premettere ./ come indicazione che il file da
eseguire risiede nella directory corrente). L' output e'
uguale ? Quale e' la
directory corrente dopo l'esecuzione dello script ?
- Creare mediante l' editor un file di testo di nome primo.c
(nella directory Labo2) contenente il seguente programma C
che legge un carattere in input dalla tastiera e lo mostra su schermo.
#include <stdio.h>
int main()
{
char inputchar; /* input è il nome di una variabile di tipo carattere*/
scanf("%c",&inputchar); /* istruzione di lettura da stdin */
printf(" %c \n",inputchar); /* istruzione di scrittura su stdout */
return 0;
}
Verificare con in comando ls quali sono i files presenti nella
directory. Compilare il programma con il comando
gcc -std=c99 -pedantic primo.c
Verificare con il comando
man gcc
qual
è il significato dei
modificatori.
- Verificare di nuovo mediante il comando
ls -l
quali sono e quanto sono grandi i files
presenti.
- Cambiare il nome del file a.out in primo.x.
- Eseguire il file primo.x digitandone il nome
preceduto da ./ (che è il modo per indicare che il file in
questione
risiede nella directory corrente), Es: ./primo.x,
e premendo "invio". Attenzione, quando il programma viene eseguito, la
prima
istruzione "aspetta" silenziosamente un input da tastiera. L' input
termina
quando si preme il tasto "invio".
- Modificare il programma precedente in modo che scriva su
schermo un' informazione sul fatto che e' in attesa di input. Per
ottenere questo, occorre inserire prima dell' istruzione scanf una printf(" scritta "); . Scrivere
la versione modificata su un secondo file di nome secondo.c, ricompilare
ed eseguire.
ATTENZIONE: si puo' fare in modo che il compilatore generi il
file eseguibile direttamente con un nome assegnato (invece del default
a.out) mediante l' istruzione
gcc -std=c99 -pedantic -o secondo.x secondo.c
- Eseguire il programma primo.x in modo che l' output,
invece di essere visualizzato sullo schermo, sia scritto su un file. A
tale scopo si può utilizzare il meccanismo della ri-direzione
dell' output (Attenzione, tutto l'
output verrà ridiretto!):
./primo.x > file_out
- Modificare il programma primo.c in modo che la variabile
input invece di essere di tipo carattere (char) sia di tipo reale
(float). Le modifiche da fare sono: i) cambiare "char input;" in "float
input;" nonché cambiare i %c nella scanf e printf in %f.
Ricompilare ed eseguire di nuovo (scrivendo su un diverso file, p.es;
file_out2). Confrontare le dimensioni del file
con quelle di quello ottenuto col programma che lavorava col tipo dati
"carattere" (guardare alle dimensionei del file come riportate dal
comando ls -l ).
- (opzionale) Dissezione dei 3
stadi del compilatore C
gcc e' un comando che gestisce le tre fasi
necessarie
per
passare dal codice sorgente (C) al codice macchina:
PRECOMPILAZIONE - COMPILAZIONE - LINKING.
E' possibile spezzare le tre fasi mediante la seguente sequenza di
comandi:
cpp primo.c primo.i
cpp e'il preprocessore che legge il file primo.c per generare il file
sorgente C, primo.i,
in cui le direttive del
proprocessore sono state eseguite.
gcc -c primo.i
viene generato da primo.i (senza più passare per il
preprocessore) un file primo.o
che contiene le istruzioni macchina relative al solo sorgente e quindi
non eseguibili (provare ad eseguire primo.o).
gcc primo.o
viene generato il file a.out
contenente le istruzioni macchina in forma eseguibile.
I seguenti punti sono suggeriti come esercizi da svolgere autonomamente:
- Scrivere un programma C che risolva l' equazione generica di
primo grado a coefficienti reali ( ax+b = 0, nell' ipotesi che a
sia diverso da zero). Compilare ed eseguire il
programma con input diversi e verificare i risultati ottenuti.
Nella lettura e scrittura di dati corrispondenti a numeri reali,
le istruzioni scanf
e
printf richiedono un descrittore di conversione %f (o %e) invece di %c,
come
nel programma primo.c, o di %d, come nel caso di lettura e scrittura di
interi.
- Scrivere un programma che legga un valore di x (reale) e calcoli
il valore della funzione 1/x. Utilizzare il programma per
studiare il limite della funzione per x -> 0. Che succede ?
(Suggerimento: per immettere valori reali molto grandi o
molto
piccoli e' preferibile usare la notazione scientifica per le costanti:
2.3
1035 in C si scrive 2.3e35, 7 10-23 diviene 7e-23)