Ogni volta che esegui un programma su un terminale, puoi passare alcuni argomenti che sono previsti dal programma, che possono essere utilizzati durante l'esecuzione del programma. Qui, il sistema fornisce una funzione interna per mantenere tutti gli argomenti passati dall'utente durante l'esecuzione del programma. Questi argomenti sono noti come "Argomenti della riga di comando".
In questo tutorial, mapperemo la comprensione degli argomenti della riga di comando con il programma di lavoro per comprenderlo meglio in modo chiaro e nitido. Ma prima di passare al programma, dovremmo sapere come il sistema fornisce la funzionalità degli argomenti della riga di comando. Come sappiamo, ogni programma C deve avere la funzione main() e la funzione di argomenti della riga di comando è fornita dalla funzione main() stessa. Quando viene fornita la dichiarazione di seguito viene utilizzata nel programma, quindi il programma ha la possibilità di utilizzare/manipolare gli argomenti della riga di comando.
int main (int argc, char *argv[])
Qui, il parametro argc è il conteggio degli argomenti totali della riga di comando passati all'eseguibile durante l'esecuzione (incluso il nome dell'eseguibile come primo argomento). Il parametro argv è l'array di stringhe di caratteri di ogni argomento della riga di comando passato all'eseguibile durante l'esecuzione. Se non conosci la programmazione C, dovresti prima capire come funziona l'array C.
Di seguito è riportato il programma di lavoro che utilizza l'argomento della riga di comando.
#include <stdio.h> int main (int argc, char *argv[]) { int i=0; printf("\ncmdline args count=%s", argc); /* First argument is executable name only */ printf("\nexe name=%s", argv[0]); for (i=1; i< argc; i++) { printf("\narg%d=%s", i, argv[i]); } printf("\n"); return 0; }
Di seguito viene emesso quando il programma viene eseguito.
$ ./cmdline_basic test1 test2 test3 test4 1234 56789 cmdline args count=7 exe name=./cmdline_basic arg1=test1 arg2=test2 arg3=test3 arg4=test4 arg5=1234 arg6=56789
Nell'output sopra, possiamo vedere che il conteggio totale degli argomenti è mantenuto internamente dal parametro "argc" di main() che contiene il valore "7" (in cui un argomento è il nome eseguibile e "6" sono argomenti passati al programma). E, tutto i valori degli argomenti sono memorizzati nel parametro "argv" di main() che è un array di stringhe di caratteri. Qui, la funzione main() memorizza ogni valore di argomento come stringa di caratteri. Possiamo vedere, iterando sull'array "argv", possiamo ottenere tutti gli argomenti passati nel programma.
C'è un'altra dichiarazione della funzione main() che fornisce funzionalità aggiuntive per lavorare sulle variabili di ambiente all'interno del programma. Come gli argomenti mantenuti nell'array argv[], la funzione main() ha una funzione interna per mantenere tutte le variabili di ambiente del sistema in array di stringhe di caratteri che possono essere prese come parametro della funzione main(). Di seguito è riportata la dichiarazione.
int main (int argc, char *argv[], char **envp)
Di seguito è riportato il programma di lavoro che utilizza l'argomento della riga di comando insieme alle variabili di ambiente.
#include <stdio.h> int main (int argc, char *argv[], char **env_var_ptr) { int i=0; printf("\ncmdline args count=%d", argc); /* First argument is executable name only */ printf("\nexe name=%s", argv[0]); for (i=1; i< argc; i++) { printf("\narg%d=%s", i, argv[i]); } i=0; while (*env_var_ptr != NULL) { i++; printf ("\nenv var%d=>%s",i, *(env_var_ptr++)); } printf("\n"); return 0; }
L'output del programma sopra è riportato di seguito.
$ ./env test1 test2 cmdline args count=3 exe name=./env arg1=test1 arg2=test2 env var1=>SSH_AGENT_PID=1575 env var2=>KDE_MULTIHEAD=false env var3=>SHELL=/bin/bash env var4=>TERM=xterm env var5=>XDG_SESSION_COOKIE=5edf27907e97deafc70d310550995c84-1352614770.691861-1384749481 env var6=>GTK2_RC_FILES=/etc/gtk-2.0/gtkrc:/home/sitaram/.gtkrc-2.0:/home/sitaram/.kde/share/config/gtkrc-2.0 env var7=>KONSOLE_DBUS_SERVICE=:1.76 env var8=>KONSOLE_PROFILE_NAME=Shell env var9=>GS_LIB=/home/sitaram/.fonts env var10=>GTK_RC_FILES=/etc/gtk/gtkrc:/home/sitaram/.gtkrc:/home/sitaram/.kde/share/config/gtkrc env var11=>WINDOWID=29360154 env var12=>GNOME_KEYRING_CONTROL=/run/user/sitaram/keyring-2Qx7DW env var13=>SHELL_SESSION_ID=f7ac2d9459c74000b6fd9b2df1d48da4 env var14=>GTK_MODULES=overlay-scrollbar env var15=>KDE_FULL_SESSION=true env var16=>http_proxy=http://10.0.0.17:8080/ env var17=>USER=sitaram env var18=>LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36: env var19=>XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0 env var20=>XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0 env var21=>SSH_AUTH_SOCK=/tmp/ssh-kIFY5HttOJxe/agent.1489 env var22=>ftp_proxy=ftp://10.0.0.17:8080/ env var23=>SESSION_MANAGER=local/Sitaram:@/tmp/.ICE-unix/1716,unix/Sitaram:/tmp/.ICE-unix/1716 env var24=>DEFAULTS_PATH=/usr/share/gconf/kde-plasma.default.path env var25=>XDG_CONFIG_DIRS=/etc/xdg/xdg-kde-plasma:/etc/xdg env var26=>DESKTOP_SESSION=kde-plasma env var27=>PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games env var28=>PWD=/home/sitaram/test_progs/cmdline env var29=>socks_proxy=socks://10.0.0.17:8080/ env var30=>KONSOLE_DBUS_WINDOW=/Windows/1 env var31=>KDE_SESSION_UID=1000 env var32=>LANG=en_IN env var33=>GNOME_KEYRING_PID=1478 env var34=>MANDATORY_PATH=/usr/share/gconf/kde-plasma.mandatory.path env var35=>UBUNTU_MENUPROXY=libappmenu.so env var36=>KONSOLE_DBUS_SESSION=/Sessions/1 env var37=>https_proxy=https://10.0.0.17:8080/ env var38=>GDMSESSION=kde-plasma env var39=>SHLVL=1 env var40=>HOME=/home/sitaram env var41=>COLORFGBG=15;0 env var42=>KDE_SESSION_VERSION=4 env var43=>LANGUAGE=en_IN:en env var44=>XCURSOR_THEME=Oxygen_White env var45=>LOGNAME=sitaram env var46=>XDG_DATA_DIRS=/usr/share/kde-plasma:/usr/local/share/:/usr/share/ env var47=>DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-mnJhMvd4jG,guid=435ddd41500fd6c5550ed8d2509f4374 env var48=>LESSOPEN=| /usr/bin/lesspipe %s env var49=>PROFILEHOME= env var50=>XDG_RUNTIME_DIR=/run/user/sitaram env var51=>DISPLAY=:0 env var52=>QT_PLUGIN_PATH=/home/sitaram/.kde/lib/kde4/plugins/:/usr/lib/kde4/plugins/ env var53=>LESSCLOSE=/usr/bin/lesspipe %s %s env var54=>XAUTHORITY=/tmp/kde-sitaram/xauth-1000-_0 env var55=>_=./env env var56=>OLDPWD=/home/sitaram/test_progs $
Nell'output sopra, possiamo vedere che tutte le variabili di ambiente di sistema possono essere ottenute terzo parametro della funzione main() che vengono attraversate nel programma e visualizzate nell'output.
Passare argomenti della riga di comando per programmare e manipolare argomenti
Di seguito è riportato il programma che lavora sugli argomenti della riga di comando.
#include <stdio.h> #include <stdlib.h> int main (int argc, char *argv[]) { int i=0; int d; float f; long int l; FILE *file = NULL; printf("\ncmdline args count=%d", argc); /* First argument is executable name only */ printf("\nexe name=%s", argv[0]); for (i=1; i< argc; i++) { printf("\narg%d=%s", i, argv[i]); } /* Conversion string into int */ d = atoi(argv[1]); printf("\nargv[1] in intger=%d",d); /* Conversion string into float */ f = atof(argv[1]); printf("\nargv[1] in float=%f",f); /* Conversion string into long int */ l = strtol(argv[2], NULL, 0); printf("\nargv[2] in long int=%ld",l); /*Open file whose path is passed as an argument */ file = fopen( argv[3], "r" ); /* fopen returns NULL pointer on failure */ if ( file == NULL) { printf("\nCould not open file"); } else { printf("\nFile (%s) opened", argv[3]); /* Closing file */ fclose(file); } printf("\n"); return 0; }
L'output del programma sopra è riportato di seguito.
$ ./cmdline_strfunc 1234test 12345678 /home/sitaram/test_progs/cmdline/cmdline_strfunc.c cmdline args count=4 exe name=./cmdline_strfunc arg1=1234test arg2=12345678 arg3=/home/sitaram/test_progs/cmdline/cmdline_strfunc.c argv[1] in intger=1234 argv[1] in float=1234.000000 argv[2] in long int=12345678 File (/home/sitaram/test_progs/cmdline/cmdline_strfunc.c) opened
Nell'output sopra, possiamo vedere che gli argomenti della riga di comando possono essere manipolati nel programma; tutti gli argomenti sono ottenuti come stringa di caratteri che può essere convertita in intero, float, lungo come mostrato nel programma. Anche qualsiasi stringa di caratteri se passata come percorso di qualsiasi file che può essere utilizzato dal programma per l'operazione di gestione dei file di quel file. Possiamo vedere nel programma sopra, (/home/sitaram/test_progs/cmdline/cmdline_strfunc.c ) il percorso del file viene passato come argomento della riga di comando che viene utilizzato all'interno del programma per aprire il file e chiudere il file.
API Getopt()
Se esploriamo di più sugli argomenti della riga di comando, abbiamo un'API molto potente:getopt(). Facilita al programmatore l'analisi delle opzioni della riga di comando. Il programmatore può fornire un elenco di opzioni della riga di comando obbligatorie o facoltative a getopt(). Può determinare se l'opzione della riga di comando è valida o non valida in base alle opzioni della riga di comando previste dal programma. Ci sono poche variabili interne specifiche di getopt() come “optarg, optopt, opterr”
- Optarg :contiene il puntatore all'argomento dell'opzione valida da riga di comando
- Opzione :contiene l'opzione della riga di comando se manca l'opzione della riga di comando obbligatoria
- Ottero :impostato su un valore diverso da zero quando viene fornita un'opzione non valida o non viene fornito il valore dell'opzione obbligatoria della riga di comando
Di seguito è riportato un programma di base per comprendere l'analisi delle opzioni della riga di comando.
#include <stdio.h> #include <unistd.h> int main (int argc, char *argv[]) { int opt = 0; char *in_fname = NULL; char *out_fname = NULL; while ((opt = getopt(argc, argv, "i:o:")) != -1) { switch(opt) { case 'i': in_fname = optarg; printf("\nInput option value=%s", in_fname); break; case 'o': out_fname = optarg; printf("\nOutput option value=%s", out_fname); break; case '?': /* Case when user enters the command as * $ ./cmd_exe -i */ if (optopt == 'i') { printf("\nMissing mandatory input option"); /* Case when user enters the command as * # ./cmd_exe -o */ } else if (optopt == 'o') { printf("\nMissing mandatory output option"); } else { printf("\nInvalid option received"); } break; } } printf("\n"); return 0; }
L'output del programma sopra è riportato di seguito con alcune combinazioni di opzioni della riga di comando:
Case1: $ ./cmdline_getopt -i /tmp/input -o /tmp/output Input option value=/tmp/input Output option value=/tmp/output Case2: $ ./cmdline_getopt -i -o /tmp/output Input option value=-o Case3: $ ./cmdline_getopt -i ./cmdline_getopt: option requires an argument -- 'i' Missing mandatory input option Case4: $ ./cmdline_getopt -i /tmp/input -o ./cmdline_getopt: option requires an argument -- 'o' Input option value=/tmp/input Missing mandatory output option Case5: $ ./cmdline_getopt -k /tmp/input ./cmdline_getopt: invalid option -- 'k' Invalid option received
Nel programma sopra, 'i' e 'o' sono considerate opzioni obbligatorie della riga di comando di input e output per il programma che utilizza getopt() API.
Ora avremmo una spiegazione di base di ogni caso eseguito nel programma precedente:
- Nel Caso1, vengono fornite entrambe le opzioni obbligatorie della riga di comando con i relativi argomenti che vengono gestite correttamente nei primi due casi di condizione di commutazione del programma.
- In Case2, il valore dell'opzione di input obbligatoria non viene fornito, ma possiamo vedere che getopt() non è abbastanza intelligente e considerato "-o" come valore dell'opzione della riga di comando "I". Non è un caso di errore per getopt(), ma il programmatore può aggiungere informazioni per gestire tale caso.
- In Case3, solo l'opzione della riga di comando è specificata senza il suo valore e questa è un'opzione obbligatoria, quindi in questo caso getopt() restituirebbe '?' e la variabile "optopt" è impostata su 'i' per confermare che il valore dell'opzione di input obbligatoria è mancante.
- In Case4, manca il valore dell'opzione di output obbligatoria.
- In Case5, viene fornita un'opzione della riga di comando non valida che non è un'opzione della riga di comando obbligatoria o facoltativa. In questo caso, getopt() ha restituito '?' e optopt non è impostato poiché è un carattere sconosciuto non previsto da getopt().