Informatica 2 – modulo C · • In programmazione moderna, il primo meccanismo di scomposizione...
Transcript of Informatica 2 – modulo C · • In programmazione moderna, il primo meccanismo di scomposizione...
Informatica 2 – modulo CMassimo Callisto De Donato
www.cs.unicam.it/massimo.callisto
LEZIONE 6 – FUNZIONI
Università degli studi di CamerinoScuola di scienze e tecnologia - Sezione Informatica
Le funzioni in generale• Le funzionalità richieste ai computer tendono ad essere man mano sempre più
complesse.
• Ogni programma tende inevitabilmente ad essere sempre più grandi e difficile da gestire.
• Si rende necessario sfruttare meccanismi capaci di scomporre i programmi più piccoli da organizzare, scrivere e testare.
• Vantaggio: i programmi di grandi dimensioni non sono altro che composizione di programmi più piccoli già collaudati e testati.
• In programmazione moderna, il primo meccanismo di scomposizione è rappresentato dalle funzioni (note anche come sottoprogramma, procedura, etc.)
Le funzioni in generale• Programmazione modulare: il blocco monolitico del programma (main) in
cui ci muoviamo (con iterazioni/condizioni) viene snellito ed il progettista affida ad un sottoprogramma un determinato compito.
• Esempi: calcolare il valore assoluto, calcolare la radice quadrata, etc.
• Riusabilità del codice: i sottoprogrammi possono essere riutilizzati ogni volta che sia necessario svolgere quel preciso compito evitando di dover riscrivere ogni volta le stesse cose.
• Chiaro che alle funzioni predefinite del linguaggio che usiamo, possiamo associare funzioni create ad-hoc da richiamare in modo opportuno.
Le funzioni in C• In C i sottoprogrammi sono dette funzioni il cui concetto è molto simile a quello di
funzione matematica:– Ogni funzione prende in input dei valori (dominio) e restituisce dei valori (tipo di ritorno o
codominio della funzione).
• Dal punto di vista informatico, una funzione è come ad una scatola nera (black-box) che a determinati valori in ingresso fa corrispondere un valore in uscita.
• Esempio: int abs(int i), double sqrt(double x), int
atoi(const char *str), ...
• Chiaro che una funzione deve essere usata in base a come è stata definita a meno di casting controllati (es. float in sqrt).
• Scrivere delle funzioni proprie (definite dal’utente) richiede che questa scatola venga “aperta” (white-box) e definirne esplicitamente il comportamento.
Esempio: uso di funzioni standard#include <stdio.h>
main ()
{
double a, b;
printf("Inserisci un numero: ");
scanf("%f", &a);
b = a*a*a;
printf("\nValore di b al cubo (%f) rispetto ad a (%f)\n", b, a);
system("pause");
}
Esempio: la prima funzione#include <stdio.h>
double cubo(float valore); // Dichiaro il PROTOTIPO della funzione
main ()
{
double a, b;
printf("Inserisci un numero: ");
scanf("%f", &a);
b = cubo(a);
printf("Valore di b al cubo (%f) rispetto ad a (%f)\n", b, a);
system("pause");
}
double cubo(double valore){ // Definisco la funzione
double temp = valore * valore * valore;
return valore;
}
Esempio: la prima funzione (2)#include <stdio.h>
/* In questo caso, definizione e dichiarazione coincidono.
Quindi prima del main non mettiamo nessun prototipo. */
double cubo(double valore){ // Definisco la funzione
double temp = valore * valore * valore;
return valore;
}
main ()
{
double a, b;
printf("Inserisci un numero: ");
scanf("%f", &a);
b = cubo(a);
printf("Valore di b al cubo (%f) rispetto ad a (%f)\n", b, a);
system("pause");
}
Le funzioni in C: definizione• La dichiarazione permette di introdurre un nuovo nome di funzione in modo che
questa possa essere utilizzata all’interno del programma.
• La dichiarazione serve a dire al compilatore come è fatta la funzione e come deve essere usata. Un esempio di dichiarazione è:
double cubo (float v);
Con cui abbiamo specificato che:
– cubo è il nome di una funzione da usare nel codice
– restituisce un valore e quel valore è di tipo double
– accetta in ingresso un solo valore e quel valore è di tipo float.
• Questa dichiarazione va messa obbligatoriamente prima del main (a patto che, come prima, la dichiarazione non corrisponda con la definizione).
• La definizione, ovvero il corpo della funzione, può trovarsi altrove (anche su altri file). Nel caso di prima è stato messo dopo la chiusura del main.
Le funzioni in C: definizione
• Sintassi della dichiarazione di una funzione:
tipo_ritorno nome_funzione (tipoPar_1, …, tipoPar_n);
• Nella dichiarazione, tipoPar_1 può essere definito con il tipoPar_1 nome oppure solo con tipoPar_1:
double cubo (float v);
double cubo (float);
• Le due righe di sopra sono del tutto equivalenti. Tuttavia i nomi sono utili per la leggibilità del codice.
• Per i nomi delle funzione valgono le stesse regole viste per i nomi delle variabili.
Le funzioni in C: dichiarazione
• La dichiarazione della funzione (il corpo) può essere messa: prima del main (senza definizione), alla fine del main, su un altro file.
• Sintassi generica della definizione:
tipo_ritorno nome_funzione (tipoPar_1 par1, … tipoPar_n par_n){
dichiarazione di variabili locali
sequenza istruzioni
return valore;
}
• I parametri in ingresso sono detti anche parametri formali. Il valore di ritorno è opzionale.
• Nota che è necessario specificare sia il tipo che il nome di ciascun parametro. Il primo caso è sbagliato:tipo_ritorno nome_funzione (tipoPar_1, … tipoPar_n){
tipo_ritorno nome_funzione (tipoPar_1 par1, … tipoPar_n){
Esempio di funzione: esempi uguali#include <stdio.h>
int pari(int);
main ()
{
int x;
printf("Inserisci un numero: ");
scanf("%d", &x);
if (pari(x))
printf(“Numero pari\n");
else
printf(“Numero dispari\n");
system("pause");
}
int pari(int a)
{
if (a%2 == 0 )
return 1;
else
return 0;
// potevamo scrivere
// return (a % 2) ? 0 : 1;
// oppure
// return !(a % 2);
}
#include <stdio.h>
int pari(int a)
{
if (a%2 == 0 )
return 1;
else
return 0;
// potevamo scrivere
// return (a % 2) ? 0 : 1;
// oppure
// return !(a % 2);
}
main ()
{
int x;
printf("Inserisci un numero: ");
scanf("%d", &x);
if (pari(x))
printf(“Numero pari\n");
else
printf(“Numero dispari\n");
system("pause");
}
Esempio di funzione#include <stdio.h>
#define DIM_INT 16
void stampa_bin(int);
main ()
{
char resp[2];
int num;
do {
printf("\nInserisci un intero: ");
scanf("%d", &num);
printf("\nRappresentazione binaria: ");
stampa_bin(num);
printf("\nVuoi continuare (si/no): ");
scanf("%s", resp);
} while((resp[0]=='s') || (resp[0]=='S'));
}
void stampa_bin(int n){
int bin[DIM_INT];
int i,j;
if ((n<0) || (n >= 65536)){
printf("numero non rappresentabile\n");
return 0;
}
// Metodo delle divisioni successive
i=0;
do {
bin[i] = n%2;
n= n/2;
i++;
}while (n>0);
for (j=i-1; j>=0; --j)
printf("%d", bin[j]);
}
Esempio di funzione#include <stdio.h>
#include <math.h>
#define YES 1
#define NO 0
int is_prime(int);
int primes(int);
main ()
{
int n, num;
float x, y;
printf("Inserisci un intero: ");
scanf("%d", &n);
printf("\nNumeri primi tra 1 e %d:\n", n);
num = primes(n);
printf("\n\n");
system("pause");
}
int is_prime(int n)
{
int max, i;
if (n >= 1 && n <= 3) return YES;
if (!(n%2)) return NO;
/* basta controllare tra 3 e radice di n*/
max = sqrt((double) n);
for (i=3; i <=max; i+=2)
if (!(n%i)) return NO;
return YES;
}
int primes(int n)
{
int count, i;
count = 0;
for (i=1; i <=n; i++){
if (is_prime(i)){
printf("%5d", i);
count++;
}
}
return count;
}
Le funzioni in C: no polimorfismo• In diversi linguaggi supportano il polimorfismo (es.: C++, Java), ovvero
definire funzioni con lo stesso nome ma parametri diversi. In C questo non è ammesso.
• Ad esempio, le seguenti funzioni usate all’interno di uno stesso programma darebbero luogo ad un errore:
double cubo(float c){
return (c * c * c);
}
float cubo(int c){
return (c * c * c);
}
• Quindi avere l'accortezza di mantenere nomi diversi per funzioni diverse. Inoltre il nome dovrebbe essere indicativo su ciò che fa la funzione.
Le funzioni in C: il return• Ad ogni funzione associamo il tipo (come avviene per le variabili). Il tipo in questo
caso è determinato dal valore di ritorno (il tipo di valore calcolato dalla funzione).
• Il tipo (ed il vaore valore) di ritorno viene determinato dalla return:return (espressione); oppure return espressione;
• La funzione termina appena si esegue una return (oppure alla chiusura della ‘}’ se non c'è).
– Possiamo avere più return all'interno della funzione.
– Se definiamo un tipo di ritorno ma per qualche ragione non c’è un ritorno di valore il comportamento diventa non predicibile.
int pari (int a)
{
if (a%2 == 0) return 1;
else return 0;
}
int pari (int a)
{
// uso di espressione
return ((a%2 == 0) ? 1 : 0);
}
int pari (int a)
{
// uso di espressione
return (!(a%2) ? 1 : 0);
}
Le funzioni in C: il valore nullo• Spesso capita di creare funzioni che adempiano ad un certo compito e
terminano senza restituire un valore.
• In questi casi si può usare la parola chiave void per dire “nessun valore”.
• Ad esempio, la funzione è una routine di gestione degli errori personalizzati (nota l’uso del return)
void myEerror(char a){
switch(a){
case „A‟:
printf(“error 1”);
return;
break;
case „B‟:
printf(“error 2”);
break;
…
}
// Questo è opzionale
return;
}
main(){
…
if(condizioneA)
myError(„A‟);
else if(condizioneX)
myError(„X‟);
…
}
Le funzioni in C: esercizio
• Definire una funzione che converta un valore inteso come temperatura espressa in gradi Celsius nel corrispettivo valore Fahrenheit. Scrivere anche la funzione opposta.
• Formule di conversione:
– [°C] = ([°F] - 32) × 5/9
– [°F] = [°C] × 9/5 + 32
• Se volessimo usare delle costanti simboliche? Dove e come?
Le funzioni in C: esercizio• Definire due funzioni toUpperC() e toLowerC() che prese in input un
carattere ritorni la sua versione, rispettivamente, minuscola e maiuscola.
char toUpperC(char);
char toLowerC(char);
• Riscrivere il tutto con una singola funzione toUppurLowerC() e che usi le costanti simboliche per definire l’operazione da eseguire sul carattere.
char toUppurLowerC(char C, boolean scelta); //(??)
• Re-implementare il programma per le stringhe palindrome e per la comparazione utilizzando le funzioni riportate sopra.
• Inoltre, i programmi dovranno offrire la scelta se fare una comparazione case-sensitive oppure no. La scelta ovviamente deve essere implementata con una funzione
Stringhe: palindrome (vecchia versione)#include<stdio.h>
#define LEN 100
main ()
{
char stringa[LEN];
int i, j;
int len, palindroma = 1;
printf("Inserisci una frase: ");
scanf("%s", stringa);
for(i=0; stringa[i] != '\0'; i++){}
len = i;
i--;
j = 0;
while(palindroma && (j < (len/2))){
if (stringa[i] != stringa[j])
palindroma = 0;
j++;
i--;
}
if (palindroma)
printf("palindroma\n");
else
printf("non palindroma\n");
}
Stringhe: comparazione (vecchia versione)#include <stdio.h>
#define LEN 100
main ()
{
int i, flag;
char s1[LEN], s2[LEN];
/* immissione stringhe */
printf("Inserisci le due stringhe separate da spazio\n");
scanf("%s %s", s1, s2);
i=0;flag = 0;
while ((s1[i] !='\0') && (s2[i] != '\0')){
if(s1[i] != s2[i]){
flag = (s1[i] < s2[i]) ? -1: 1;
break;
}
i++;
}
if (flag == -1) printf("%s e' minore di %s\n", s1, s2);
else if (flag == 1) printf("%s e' maggiore di %s\n", s1, s2);
/* se flag=0, allora o entrambe le stringhe sono arrivate a '\0',
oppure qualcuna è arrivata prima dell'altra. */
else if (!flag){
if ( (s1[i] == '\0') && (s2[i] == '\0') )
printf("Le due stringhe %s e %s sono uguali\n", s1, s2);
else if (s1[i] == '\0')
printf("%s e' minore di %s\n", s1, s2);
else
printf("%s e' maggiore di %s\n", s1, s2);
}
} // Il controllo è case-sensitive… Per farne uno non case-sensitive?
Le funzioni in C: i parametri• Abbiamo visto che ogni funzione può essere definita con dei dati in ingresso (i parametri):
tipo_ritorno nome (tipoPar_1 par1, … tipoPar_n par_n);
• Nell'invocazione (uso effettivo della funzione) sostituiamo a par_1,…, par_n i valori
effettivi (parametro attuali).
• Tali valori possono essere una qualsiasi espressione che fornisca un valore di quel tipo:
nome (espr_1, ..., espr_n)
• Ciascun parametro attuale (il risultato dell'espressione) viene assegnato al corrispondente
parametro formale.
#include <stdio.h>
int fun1 (int, int, int);
main()
{
int x;
x = fun1((3 + 5), abs(-9), !((42%2)<1));
printf("Val x: %d\n", x);
} // x==y alla fine?
int fun1(int a, int b, int c)
{
int y = a + b + c;
printf("Val y: %d\n", y);
return y++;
}
Le funzioni in C: altro esempio/* Che stampiamo?? */
#include <stdio.h>
int fun1 (int, int, int);
main()
{
int x;
x = fun1((3 + 5), abs(-9), !((42%2)<1));
printf("Val x: %d\n", x);
x = fun1((3 + 5), abs(-9), !((42%2)<1));
printf("Val x: %d\n", x);
} // x==y alla fine?
int fun1(int a, int b, int c)
{
int y;
printf("Val1 y: %d\n", y);
y = a + b + c;
printf("Val2 y: %d\n", y);
return y++;
}
Le funzioni in C: parametri formali ed attuali
• Abbiamo parlato di parametri formali e parametri attuali.
– Parametri formali: i parametri specificati nella funzione
– Parametri attuali: i parametri usati nel momento in cui la funzione viene invocata
• Il legame che c'è nel passaggio tra i due tipi di parametri sono:
– passaggio per valore: passiamo il valore contenuto nel parametro attuale
– passaggio per riferimento: passiamo effettivamente il parametro attuale
• Nel primo caso, se la funzione altera il parametro formale, il parametro attuale rimane invariato. Nel secondo caso, le eventuali modifiche si riflettono sull’altro.
• In C si usa solo il passaggio per valore (vedremo che i puntatori simulano il secondo caso).
Le funzioni in C: parametri formali ed attuali#include <stdio.h>
int fattoriale (int);
main()
{
int x = 5, i, fact = 1;
for(i = x; i >= 0; i--){
if(!i)
break;
fact *= i;
}
printf("Fattoriale di x: %d\n", fact);
printf("Fattoriale di x: %d\n", fattoriale(x));
system("PAUSE");
}
int fattoriale(int a)
{
if(!a) return 1;
return (a * fattoriale(a - 1));
}
Le funzioni in C: parametri formali ed attuali/* Che stampiamo? */
#include <stdio.h>
int fun1 (int);
int fun2 (int);
main(){
int x = 3;
printf("Val x: %d\n", x);
x = fun1(++x);
printf("Val x: %d\n", x);
}
int fun1(int x){
int y;
y = fun2(x);
printf("Val y, x: %d, %d\n", y, x);
return y + y + 4;
}
int fun2(int x){
printf("Val x2: %d\n", x);
printf("Val x2_1: %d\n", x++);
printf("Val x2_2: %d\n", x);
return x - 1;
}
Le funzioni in C: parametri formali ed attuali
• Abbiamo detto che il passaggio di parametri per valore intende che le modifiche sui parametri attuali non si ripercuotono su quelli formali:
main(){ void func(int a){
int a = 3; a++;
while(1) }
if(a==5) break;
else func(a);
}
• Avviene perché la visibilità delle variabili è locale alla funzione in cui sono dichiarate. Es.: la variabile a della funzione main è locale alla main ed è diversa dalla variabile a di func. Il seguente codice è scorretto:
#include <stdio.h>
void func(void);
main(){
int a = 3;
while(1)
if(a==5) break;
else func();
}
void func(void){
a++;
}
Le funzioni in C: variabili globali
• Per dare alle variabili una visibilità nell’intero programma (estende a tutto il file) definiamo le variabili globali.
Le funzioni in C: variabili globali/* ??? */
#include <stdio.h>
void func(void);
int a; // sono globale ma l‟inizializzazione?
main(){
int a = 3;
while(1)
if(a==5) break;
else func();
}
void func(void){
printf("a: %d", a);
return a++;
}
Le funzioni in C: variabili globali/* Ora: inizializzazione + fine */
#include <stdio.h>
void func(void);
int a = 3; // sono globale
main(){
//int a = 3; // giusto per far finire il programma
while(1)
if(a==5) break;
else func();
}
void func(void){
printf("a: %d", a);
return a++;
}
Le funzioni in C: i parametri• Dato un generico programma, le variabili si possono distinguere in base
alla loro visibilità:
– Ambiente globale: costituito dalle dichiarazioni/definizioni che compaiono nella parte di dichiarazioni globali.
– Ambiente locale a una funzione: l’insieme delle dichiarazioni/definizioni che compaiono nella parte dichiarazioni della funzione, più i suoi parametri formali.
• Ogni dichiarazione introduce un nome in un determinato ambito di definizione detto scope.
• E' ammesso che ci siano variabili con lo stesso nome che appaiano in scope diversi.
• Con le variabili globali, variabili con lo stesso nome hanno lo stesso scope. In tal caso, lo scope delle variabili locali nasconde quello della variabili globali.
Le funzioni in C: scope/* ?? */
#include <stdio.h>
int x = 13;
void f();
main ()
{
int i;
printf(“main: x = %d\n", x);
f();
printf("main: x = %d\n", x);
system("pause");
}
void f()
{
int x = 4;
printf("blocco f: x = %d\n", x++);
}
Le funzioni in C: passaggio di array
• Ad una funzione possiamo anche passare gli array. La sintassi è la seguente
ritorno nome_funzione(tipo array[]);
• Se la dimensione max non è stata definita globalmente (es.: #define MAX_LEN 100) dobbiamo passare anche la dimensione massima:
ritorno nome_funzione(tipo array[], int dim_max);
• Attenzione! Gli array sono passati per riferimento. Significa che se la funzione modifica l’array allora la modifica si riflette nella funzione chiamante.
Le funzioni in C: passaggio di array/* ?? */
#include <stdio.h>
void stampa_vettore(int v[], int len);
void aumenta(int v[], int len);
main()
{
int x[] = {1,2,3,4};
stampa_vettore(x, 4);
aumenta(x, 4);
stampa_vettore(x, 4);
}
void aumenta(int v[], int len)
{
int i;
for(i = 0; i < len;)
v[i++]++;
}
void stampa_vettore(int v[], int len){
int i;
for(i = 0; i < len ; i++)
printf("%d, ", v[i]);
printf("\n");
}
Le funzioni in C: passaggio di array (multi)
• Possiamo anche passare array multidimensionali.
• In questo caso DOBBIAMO specificare le dimensioni successive alla prima:
ritorno nome_funzione(tipo array[][DIM2_MAX][DIM3_MAX]);
• E’ evidente che dobbiamo definire qualche variabile globale o costante per le varie dimensioni successive alla prima.
• Ad esempio una cosa del genere non funziona:
ritorno nome_funzione(tipo array[][int dim2][int dim3]);
• Attenzione! Gli array sono passati per riferimento. Significa che se la funzione modifica l’array allora la modifica si riflette nella funzione chiamante.
Le funzioni in C: passaggio di array (multi)/* ?? */
#include <stdio.h>
#define MAX_COL_LEN 3
void stampa_vettore(int v[], int len);
void aumenta(int v[], int len);
void stampa_vettore_multi(int v[][MAX_COL_LEN]);
main()
{
int i, j;
int x[] = {1,2,3,4};
int xx[4][MAX_COL_LEN];
for(i = 0; i < 4; i++)
for(j = 0; j < MAX_COL_LEN;)
xx[i][j++] = i;
stampa_vettore(x, 4);
aumenta(x, 4);
stampa_vettore(x, 4);
stampa_vettore_multi(xx);
}
void aumenta(int v[], int len)
{
int i;
for(i = 0; i < len;)
v[i++]++;
}
void stampa_vettore(int v[], int len){
int i;
for(i = 0; i < len ; i++)
printf("%d, ", v[i]);
printf("\n");
}
void stampa_vettore_multi(int
v[][MAX_COL_LEN]){
int i, j;
for(i = 0; i < 4; i++){
printf("\n");
for(j = 0; j < MAX_COL_LEN; j++)
printf("%d, ", v[i][j]);
}
}
Se volessimo riusare la funzione stampa_vettore invece del for?
Le funzioni in C: passaggio di array (multi)/* ?? */
#include <stdio.h>
#define MAX_COL_LEN 3
void stampa_vettore(int v[], int len);
void aumenta(int v[], int len);
void stampa_vettore_multi(int v[][MAX_COL_LEN]);
main()
{
int i, j;
int x[] = {1,2,3,4};
int xx[4][MAX_COL_LEN];
for(i = 0; i < 4; i++)
for(j = 0; j < MAX_COL_LEN;)
xx[i][j++] = i;
stampa_vettore(x, 4);
aumenta(x, 4);
stampa_vettore(x, 4);
stampa_vettore_multi(xx);
}
void aumenta(int v[], int len)
{
int i;
for(i = 0; i < len;)
v[i++]++;
}
void stampa_vettore(int v[], int len){
int i;
for(i = 0; i < len ; i++)
printf("%d, ", v[i]);
printf("\n");
}
void stampa_vettore_multi(int
v[][MAX_COL_LEN]){
int i;
for(i = 0; i < 4; i++)
stampa_vettore(v[i], MAX_COL_LEN);
}
Esercizio
• Scrivere una funzione swap() che presi in
input due valori interi a e b li scambi.
• Riusciamo a fare qualcosa in più ora?
Le funzioni in C: variabili statiche
• Una variabile statica è una normale variabile locale ad
una funzione.
• Viene inizializzata una sola volta (la prima volta che
viene richiamala la funzione genitore) ed il suo valore
resta inalterato quando si esce dalla funzione.
• A chiamate successive alla stessa funzione, la variabile
statica ha ancora il valore assegnatogli in precedenza.
• Sintassi: static tipo nome;
Le funzioni in C: variabili statiche/* ?? */
#include <stdio.h>
void func();
int a2 = 99;
main(){
int i;
for (i=0; i<5; ++i)
func();
printf("a2: %d \n", a2);
}
void func(){
int a1 = 0;
static int a2 = 0;
printf("a1: %d, a2: %d \n", ++a1, ++a2);
}
Le funzioni in C: altro esempio/* Che stampiamo?? */
#include <stdio.h>
int fun1 (int, int, int);
main()
{
int x;
x = fun1((3 + 5), abs(-9), !((42%2)<1));
printf("Val x: %d\n", x);
x = fun1((3 + 5), abs(-9), !((42%2)<1));
printf("Val x: %d\n", x);
} // x==y alla fine?
int fun1(int a, int b, int c)
{
static int y;
printf("Val1 y: %d\n", y);
y = a + b + c;
printf("Val2 y: %d\n", y);
return y++;
}
Esercizio
• Fare un programma calcolatrice che:
– Realizzi le 4 operazioni fondamentali su interi oltre che il modulo, radice quadrata, dice se è primo;
– Ogni operazione è una funzione;
– Usi solo la funzione getchar() per l’input e caratteri non ammessi vengono ignorati;
– Usi una funzione buildOp() che ri-costruisca la cifra intera a partire dalla sequenza di caratteri letti in input;
Le funzioni in C: una nota sul main()
• Abbiamo sempre usato la funzione main() dicendo che
identifica l’entry-point e la sua presenza è obbligatoria.
• L’uso è implicito ma anche la funzione main ha un
prototipo (in realtà 3):
int main(void);
int main(int argc, char *argv[]);
int main(int argc, char *argv[], char *envp[]);
Le funzioni in C: una nota sul main()int main(int argc, char *argv[], char *envp[]);
• int argc: rappresenta il numero di parametri passati al programma all’avvio, compreso il nome stesso.
• char *argv[]: lista degli argomenti passati in forma testuale (stringhe), compreso il nome del programma stesso.
• char *envp[]: rappresenta la lista delle variabili ambiente disponibili nel sistema operativo.
• Valore di ritorno int: serve a comunicare all’OS (o chi ha invocato il nostro programma) la condizione di terminazione. Es. possiamo assumere che:
– 0 - il programma dice che tutto è andato bene, – -1 - il programma dice che qualcosa è andato male.
Esempio di main() con argomenti#include <stdio.h>
int main (int argc, char *argv[])
{
int count;
// argc è sempre > 0 argv[0] è sempre corretto
printf ("Nome del programma '%s'\n",argv[0]);
printf ("Argomenti passati al programma:\n");
if (argc > 1)
for (count = 1; count < argc; count++)
printf("argv[%d] = %s\n", count, argv[count]);
else
printf("Nessun parametro passato.\n");
return 0;
}
/* nota che argc e argv sono nomi che si usano per convenzione. Potevamo
anche usare altri nomi. */
Esempio di main() con argomenti e variabili di ambiente
#include <stdio.h>
int main (int argc, char *argv[], char *envp[])
{
int count;
printf ("Nome del programma '%s'\n",argv[0]);
printf ("Argomenti passati al programma:\n");
if (argc > 1)
for (count = 1; count < argc; count++)
printf("argv[%d] = %s\n", count, argv[count]);
else
printf("Nessun parametro passato.\n");
// envp ha l‟elementi i-esimo == „\0‟ quando finisce
for(count = 0; envp[count] != '\0'; count++)
printf("Variabile envp[%d]: %s\n", count, envp[count]);
return 0;
}
Esercizio
• Modificare il programma della calcolatrice in modo tale che:
– Il programma si auto-configuri all’avvio per attivare o meno una funzione myLog() di logging su buildOp();
– myLog(), se attiva, stampa su schermo possibili errori di input (e.s. immissione di un carattere invece che numero);
– L’auto-configurazione si ottiene passando il relativo parametro di input log=1 (log attivo) oppure log=0 (log inattivo) all’avvio del programma nella forma (x = 1, 0): > nome_programma log=x
– Nota che log=valore corrisponde ad una stringa. Affinché myLog() interpreti valore, la stringa log=valore va spezzata su ‘=‘ e la parte finale valore deve essere convertita nel rispettivo valore decimale 0 oppure 1.