La gestione dei parametri argc e argv in C/C++

Solitamente i programmi realizzati dagli alunni contengono delle piccole interfacce testuali per gestire l'input/output. Ma un programma exe può essere eseguito anche passando direttamente all'avvio dei parametri. Vediamo come funziona.

Forse poco utilizzato didatticamente, ma pur sempre utile anche per approfondire l'uso dei vettori e la gestione dei char con il mondo ostico di * e &.

L'idea alla base di questo articolo è: voglio eseguire il file pippo.exe da console di windows o linux  passando dei parametri nella forma:

pippo.exe 13 a 27 

o su linux

./pippo 13 a 27

in modo tale che poi il software scritto dentro pippo possa usare questi valori passati per eseguire le proprie funzionalità.

Innanzi tutto, lo studente più attento può aver fatto caso che alcuni IDE quando creano la funzione int main, mettono sempre dei parametri int argc, char *argv[], che spesso il docente si limita a segnalare di copiarli ed incollarli senza badare troppo al loro significato. In realtà sono parametri opzionali, la funzione main può anche essere scritta semplicemente int main () senza null'altro. Se invece vogliamo passare dei parametri dobbiamo scriverli necessariamente e finalmente possiamo capire la loro funzionalità. Quanto scriviamo è equivalente per il C e il C++.

Il parametro argc contiene il numero intero di quanti parametri vengono passati. La cosa strana è che un parametro viene passato sempre di default ed è proprio il nome del programma, nel nostro caso pippo. Nell'esempio sopra in particolare ./pippo 13 a 27, risulterà argc uguale a 4, il primo appunto il nome del programma e poi i tre passati esplicitamente, 13 il carattere a, 27. A questo punto non resta che svelare argv, ma credo sia intuibile che siamo di fronte ad un vettore che immagazzinerà sotto forma di caratteri i parametri passati, che siano numeri o lettere, saranno salvati sempre sotto forma di caratteri. Qui il lettore che ha un po' di esperienza di assembler potrebbe già sbuffare: si sono tutti caratteri della tabella ascii, anche i numeri in realtà sono dei caratteri o meglio, le singolo cifre possono essere intese come dei caratteri. Diamo un'occhiata qui sotto.

Ascii Table

Forse a chi non ha confidenza può risultare strano, ma la codifica di un numero da 0 a 9, corrisponde al numero identificativo da 48 a 57. Quindi una cifra ha praticamente un offset di 48, ovvero se mi passano il carattere 0, questo viene codificato con 48, quindi numeroreale=48 - 48=0. Analogamente, se abbiamo il carattere  7 codificato con 55, numeroreale= 55 -48 = 7

Ecco che quindi abbiamo uno strumento per trattare i parametri immessi: se li converto in intero e scopro che è una codifica tra 48 e 57, allora tolgo l'offset per trattarlo da numero, altrimenti sarà un carattere vero e proprio, quindi userò il suo indice rispetto alla mappa.

Vediamo un esempio: voglio sommare i parametri in ingresso al nostro programma. Si tratta di scorrere il nostro vettore argv sfruttando la capienza argc. E qui ora l'operazione critica. Dobbiamo trovare quale sia il numero corrispondete al carattere ascii inserito. Possiamo ricorrere a funzioni specifiche ma è decisamente più semplice per un alunno ricordare il cast parametro = (int) *argv[i]; A questo punto, tralasciando il warning i fase di compilazione, possiamo usare la variabile intera per fare tutte le nostre congetture o filtri. Qui, come anticipato,  trattiamo i numeri il cui indice è compreso tra 48 e 57, a cui sottraiamo 48 come offset introdotto dalla codifica ascii. E il gioco è fatto, basta sommare numeri e lettere e ottenere una simpatica somma alternativa di numeri e numeri corrispondenti ai caratteri. L'ultimo if è semplicemente una finezza per indicare e stampare eventualmente il carattere risultante dalla somma, a patto  che sia minore/uguale di 127, dimensione massima della tabella ascii o fino a 255 se nel suo formato esteso.

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char *argv[] )  {

    int i;
    int somma = 0;
    int parametro = 0;

    //argc contiene quanti parametri vengono passati e la dimensione del vettore argv
    //Il primo è sempre scontato il nome del programma
    printf("Sono stati passati %d\ parametri \n", argc - 1);

    if( argc >= 2 )
    {

      for (i=1; i < argc; i++) //parto da 1, il parametro argv[0] è il nome del programma
      {
        printf("Parametro %d passato: %s\n", i,argv[i]);
        parametro = (int) *argv[i];

        if (parametro>=48 && parametro<= 57)
        {
            somma += parametro - 48;
        }
        else
        {
            somma += parametro;
        }
      }

      printf ("somma %d\n\n", somma);

      //se il carattere risultante dalla somma è ancora nella tabella ascii
      //di 127 simboli, allora lo stampo
      if (somma <= 127)
      {
        printf("%c\n\n",somma);
      }

    }
    else
    {
        printf("Nessun parametro passato! \n");
    }

    getchar();
    return 0;
}