argc, argv, getopt acquisizione e gestione di argomenti e opzioni da linea di comando
utilizzo user@mac:./calcola dati.txt risultati.txt Si esegue il programma calcola, passando come informazione il nome di due file: dati.txt (dove sono contenuti i dati da elaborare) e risultati.txt (dove salvare i risultati)! user@mac:./fattoriale 7 Si esegue il programma fattoriale, che calcola il fattoriale del valore indicato come parametro (7 nell esempio) il programma non interagisce con l utente, ma riceve tutte le informazioni necessarie scanf gets all avvio
argc e argv int main(int argc, char * argv[]) {... gli argomenti return 0; ricevuti in ingresso } numero di argomenti ricevuti in ingresso
argc e argv il primo argomento che si riceve è SEMPRE il nome del programma (completo di percorso...) la prima stringa digitata sulla riga di comando quindi è SEMPRE argc >= 1 user@mac:./listaargomenti uno due tre quattro quanto varrà argc?
esempio #include <stdio.h>! int main(int argc, char * argv[]) { int i;! } for(i = 0; i < argc; i++) printf("argomento %d: %s\n", i, argv[i]); printf("totale: %d argomenti\n", argc); return 0;
esempio - esecuzione user@mac:./listaargomenti uno due tre quattro argomento 0:./listaargomenti argomento 1: uno argomento 2: due argomento 3: tre argomento 4: quattro totale: 5 argomenti user@mac:
argc e argv int main(int argc, char * argv[]) {... return 0; } gli argomenti ricevuti in ingresso sono tutte stringhe char * argv[] di stringhe array
argc e argv gli argomenti sono acquisiti come stringhe, se rappresentano un informazione (un valore intero ad esempio) diversa vanno convertiti user@mac:./contacaratteri miofile.txt il secondo parametro è di fatto una stringa, potrà essere usato così user@mac:./fattoriale 27 il secondo parametro è un intero, andrà convertito
argc e argv int main(int argc, char * argv[]) { char * nomefile, c; FILE * fp; int n; nomefile = argv[1]; if(fp = fopen(nomefile, "r")){ n = 0; fscanf(fp, "%c", &c); while(!feof(fp)){ n++; fscanf(fp, "%c", &c); } fclose(fp); printf("%d\n", n); } else printf("file non accessibile %s\n", nomefile); return 0; }
esempio completo / 1 #include <stdio.h> #include <stdlib.h> #include <string.h>! #define SEP '/'! void showprogmissingarg(char *); void showprogusage(char *);
esempio completo / 2 int main(int argc, char * argv[]) { char * nomefile, * eseguibile, c; FILE * fp; int n, l, i, found; /* argv[0]: nome dell'eseguibile con il percorso... */ l = strlen(argv[0]); for(i = l, found = 0; i >= 0 &&!found; i--) if(argv[0][i] == SEP) found = 1; if(i < 0) eseguibile = argv[0]; else eseguibile = &(argv[0][i+2]);
esempio completo / 3 if(argc!= 2){ showprogmissingarg(eseguibile); showprogusage(eseguibile); exit (1); }
esempio completo / 4! nomefile = argv[1]; if(fp = fopen(nomefile, "r")){ n = 0; fscanf(fp, "%c", &c); while(!feof(fp)){ n++; fscanf(fp, "%c", &c); } fclose(fp); printf("%d\n", n); } else printf("file non accessibile %s\n", nomefile);
esempio completo / 5 void showprogmissingarg(char * progname) { printf("%s: argomento mancante\n", progname); return; }! void showprogusage(char * progname) { printf("uso: %s NOMEFILE\n", progname); return; }
esempio - esecuzione user@mac:./contacaratteri contacaratteri: argomento mancante Uso: contacaratteri NOMEFILE user@mac:./contacaratteri./miofile.txt 60 user@mac:
argv:conversione di tipo int string2integer(char *);! int main(int argc, char * argv[]) { int fatt, n; n = string2integer(argv[1]); if(n > 0){ for(fatt = 1; n > 1; n--) fatt = fatt *n; printf("%d\n", fatt); } else printf("uso: fattoriale NUM_NON_NEGATIVO\n"); return 0; }
string2integer int string2integer(char * numero){ int valore; int ncifre, i, po, numinit, sign; ncifre = strlen(numero); if(numero[0] == NEG){ numinit = 1; sign = -1; } else { numinit = 0; sign = 1; } for(i = ncifre-1, po = 1, valore = 0; i >= numinit; i--, po = po*base) valore = valore + (numero[i] - '0')*po; return sign*valore; }
atoi int main(int argc, char * argv[]) { int fatt, n; n = atoi(argv[1]); if(n > 0){ for(fatt = 1; n > 1; n--) fatt = fatt *n; printf("%d\n", fatt); } else printf("uso: fattoriale NUM_NON_NEGATIVO\n"); return 0; }
argomenti user@mac:./calcola dati.txt risultati.txt l ordine con cui vengono scritti gli argomenti è importante la flessibilità è limitata (bisogna ricordarsi l ordine giusto) alcuni argomenti potrebbero essere facoltativi (opzioni)
opzioni specifica di opzioni nell esecuzione del programma user@mac:./contacaratteri miofile.txt -a conta i caratteri presenti in un file: solamente quelli alfanumerici user@mac:./contacaratteri miofile.txt -M conta i caratteri presenti in un file: solamente i caratteri alfanumerici maiuscoli
opzioni user@mac:./frequency -h Usage: frequency [options] INPUTFILE -h --help Displays this information -a --alpha Use only alphanumerical -t --threshold VALUE The threshold for results -o --output FILENAME Write output to file -v --verbose Print verbose messages
opzioni gestione manuale: acquisizione ed analisi di tutti i valori presenti in argv coppia opzione - valore -t --threshold VALUE utilizzo di sottoprogramma di libreria: getopt
getopt int main (int argc, char* argv[]){... /* stringa che specifica opzioni brevi valide */ const char* short_options = "hat:o:v"; /* che descrive le opzioni lunghe */ const struct option long_options[] = { { "help", 0, NULL, 'h' }, { "alpha", 0, NULL, 'a' }, { "threshold", 1, NULL, 't' }, { "output", 1, NULL, 'o' }, { "verbose", 0, NULL, 'v' }, { NULL, 0, NULL, 0} /*req. end of array */ };
getopt int main (int argc, char* argv[]){... l opzione NON è seguita da un valore /* stringa che specifica opzioni brevi valide */ const char* short_options = "hat:o:v"; /* che descrive le opzioni lunghe */ const struct option long_options[] = { { "help", 0, NULL, 'h' }, l opzione prevede un valore opzione lunga }; { "alpha", 0, NULL, 'a' }, { "threshold", 1, NULL, 't' }, { "output", 1, NULL, 'o' }, { "verbose", 0, NULL, 'v' }, opzione breve { NULL, 0, NULL, 0} /*req. end of array */
getopt /* program management */ int next_option; int blnalpha; /* working only on alphanumerical */ int threshold; /* show only above threshold */ char * input_filename = NULL; char * output_filename = NULL; int verbose; /* whether to display verbose messages. */!
getopt_long while ((next_option = getopt_long (argc, argv, short_options, long_options, NULL)!= -1) { /* gets the next option on the command line */ if(next_option == h ){ /* display help */ print_usage(stdout, 0); } else if (next_option == ) {... } else { /* unexpected option */ abort(); } }
getopt_long blnalpha = 0; threshold = 0; while ((next_option = getopt_long (argc, argv, short_options, long_options, NULL))!= -1) { if(next_option == 'h'){ /* -h or --help */ print_usage (stdout, 0); } else if(next_option == 'a') { /* -a or --alpha */ blnalpha = 1; } else if (next_option == 't') { /* -t or --threshold */ threshold = atoi(optarg); }
getopt_long } } else if(next_option == 'o'){ /* -o or --output */ output_filename = optarg; } else if (next_option == 'v'){ /* -v or --verbose */ verbose = 1; } else if (next_option == '?'){ /* The user gave an invalid option. */ print_usage (stderr, 1); } else /* unexpected situation */ abort();
print_usage void print_usage (FILE* stream, int exit_code) { fprintf (stream, "Usage: %s [options] INPUTFILE\n", program_name); } fprintf (stream, " -h --help Displays this information " " -a --alpha Use only alphanumerical " " -t --threshold VALUE The threshold for results " " -o --output FILENAME Write output to file " " -v --verbose Print verbose messages.\n"); exit (exit_code);
getopt while ((next_option = getopt (argc, argv, "hat:o:v"))!= -1) { /* gets the next option on the command line */ if(next_option == h ){ /* display help */ print_usage(stdout, 0); } else if (next_option == ) {... } else { /* unexpected option */ abort(); } }
sorgenti organizzati in file e Makefile organizzazione modulare del codice
organizzare il codice utilizzo di file diversi, contenenti sottoprogrammi di utilità, ri-utilizzabili anche in altre occasioni sottoprogrammi sulla gestione e manipolazione di liste sottoprogrammi di utilizzo comune (fattoriale, numero di combinazioni, permutazioni,...)
file di sottoprogrammi file contenente i prototipi: header file (.h) file contenente i sottoprogrammi: file sorgente (.c) esempio: spazio2d.h spazio2d.c
utilizzo #include <stdio.h> #include spazio2d.h" #define N 1000! int main(int argc, char * argv[]) { punto_t v[n];! tipo definito in spazio2d.h... leggipunti(v, N);... specificare il percorso prototipo specificato in spazio2d.h codice sottoprogramma in spazio2d.c
spazio2d.h #include <stdio.h>! typedef struct _punto { float x, y; /* coordinate */ int val; /* valore */ } punto_t;! void leggipunti(punto_t[], int); float distanza(punto_t *, punto_t *);...
spazio2d.c #include "spazio2d.h" /** leggipunti: acquisisce n punti da stdin * e li memorizza in dati **/ void leggipunti(punto_t dati, int n) { } int i; for(i = 0; i < n; i++) scanf( %f%f%d, &dati->x, &dati->y, &dati->val); return;
compilazione file sorgente file oggetto file eseguibile nel caso di un unico file, si produce direttamente il file eseguibile gcc file_sorgente.c -o eseguibile con più file per ognuno si crea il file oggetto gcc -c file_sorgente.c -o file_oggetto.o facendo il link di tutti i file oggetto si crea il file eseguibile
compilazione sorgente codice oggetto user@mac: gcc -Wall -c spazio2d.c -o spazio2d.o è necessario indicare il file.c che si vuole compilare e tutti i file header di interesse user@mac: gcc -Wall -c spazio2d.c -o spazio2d.o -I. cerca nella directory. i file header di interesse
compilazione sorgente codice oggetto user@mac: gcc -Wall -c utilities.c -o utilities.o -I. user@mac: ls spazio2d.c spazio2d.h spazio2d.o utilities.c utilities.h utilities.o main.c
compilazione sorgente codice oggetto user@mac: gcc -Wall -c utilities.c -o utilities.o -I. user@mac: gcc -Wall -c main.c -o main.o -I. user@mac: ls spazio2d.c spazio2d.h spazio2d.o main.c main.o utilities.c utilities.h utilities.o
compilazione codici oggetto eseguibile user@mac: gcc -o myprog spazio2d.o utilities.o main.o -I. -lm oppure: codici oggetto + main.c eseguibile user@mac: gcc -o myprogr main.c spazio2d.o utilities.o -I. -lm
make & Makefile modo semplice per organizzare la compilazione il comando di utilità make legge il file Makefile ed esegue le operazioni di compilazione specificate Makefile specifica quali file compilare, ordine, dipendenze ed opzioni
nome della regola Makefile - v1 myprog: main.c spazio2d.c utilities.c! TAB! gcc -Wall -o myprog main.c spazio2d.c utilities.c -I. -lm > make se non si specifica nulla, viene eseguita la prima regola del file nome_regola : file da cui dipende tutti i.c da compilare se cambia un file di quelli elencati, è necessario rieseguire la compilazione
Makefile - v2 CC = gcc CFLAGS = -I. -Wall LDFLAGS = -lm! myprog: spazio2d.o utilities.o main.o $(CC) -o myprog main.o spazio2d.o utilities.o $(LDFLAGS) clean: rm *.o myprog! ancora una unica regola per la compilazione regola per eliminare i file creati, eseguibile incluso
Makefile - v3 CC = gcc INCLUDE = -I. CXXFLAGS = -Wall LDFLAGS = -lm OBJS! all: myprog myprog: $(OBJS) = spazio2d.o utilities.o $(CC) $(CXXFLAGS) $(OBJS) -o myprog main.c $(INCLUDE) $(LDFLAGS) spazio2d.o : spazio2d.c $(CC) $(CXXFLAGS) -o spazio2d.o -c spazio2d.c $(INCLUDE) utilites.o : utilities.c $(CC) $(CXXFLAGS) -o utilities.o -c utilities.c $(INCLUDE)
Makefile - v4 CC = gcc INCLUDE = -I. CXXFLAGS = -Wall LDFLAGS = -lm OBJS = spazio2d.o utilities.o main.o! all: myprog $(OBJS)! %.o : %.c $(CC) $(CXXFLAGS) -c -o $@ $< $(INCLUDE)! myprog: $(OBJS) $(CC) $(CXXFLAGS) -o $@ $^ $(INCLUDE) $(LDFLAGS)!