Argomenti del main() spiegati semplici semplici

Praticamente per tutta la durata del corso di Programmazione 1 c’è stato detto che “main deve restituire un int e alla fine del programma dobbiamo scrivere return 0”, ma senza dirci esattamente perché. In questo post spiegherò brevemente cosa significa quell’int e come si passano gli argomenti al main.

Quando avviamo un programma, per esempio dalla linea di comando, e il lavoro del programma termina, il programma comunica al sistema operativo se l’esecuzione è terminata normalmente oppure no. Questo viene fatto restituendo un valore numerico intero, detto codice di uscita, al sistema operativo. In Windows, possiamo vedere l’ultimo codice di uscita restituito usando il comando cmd

echo %ERRORLEVEL%

mentre in Linux lo si fa usando

echo $?

L’int del main è esattamente il codice di uscita che viene restituito al sistema operativo quando si usa un return all’interno del main o si usa la funzione exit().

Oltre, ad avere un valore di ritorno, main può anche avere dei parametri. Prendiamo, per esempio, questo codice:

#include <iostream>

using namespace std;

int main(int argc, char **argv)
{
    for (int i = 0; i < argc; i++) {
        cout << "Argomento " << i << " - " << argv[i] << endl;
    }
    cout << "Premi un tasto per continuare...";
    getchar();
    return 0;
}

Se compiliamo questo codice e lo eseguiamo, notiamo che il programma manda a video tutto quello che scriviamo per avviarlo. Per esempio

Spieghiamo ora cosa sono i parametri che abbiamo passato al main:

  • argc (argument counter), un intero usato come contatore degli argomenti;
  • argv (argument vector), un array di puntatori a char (cioè un array di stringhe) in cui sono contenuti i vari argomenti del programma, uno per elemento dell’array. Il suo primo elemento è sempre il nome del programma.

Iterando argv (per esempio con un ciclo for) possiamo leggere quali argomenti abbiamo passato al programma.

Il problema di iterare gli argomenti in questo modo è che scansionare gli argomenti di un programma manualmente è un’attività noiosa e che conduce facilmente a errori. Per esempio, nel caso di SRT Validation è possibile passare al programma 6 tipi di argomento diversi. Il codice che ho scritto per questo scopo è

if ((argc == 1) || (static_cast<std::string>(argv[1]) == "-h"))
        {
            std::cout << "Usage:" << std::endl
                << "srt-validation [-h] FILENAME [-p|-a] [-l #] [-c #]" << std::endl
                << std::endl
                << "Arguments:" << std::endl << std::endl
                << "-h\thelp\nPrint this help message and exit. Must be the first argument passed to the program. All subsequent arguments are ignored." << std::endl << std::endl
                << "FILENAME\nThe name of the SRT file to analyze, including extension." << std::endl << std::endl
                << "-p\tperformance\nRun the analysis in performance mode. Each subtitle will be checked against the following one. This argument is incompatible with -a." << std::endl << std::endl
                << "-a\taccurate\nRun the analysis in accurate mode. Each subtitle will be checked against ALL following subtitles. This argument is incompatible with -p." << std::endl << std::endl
                << "-l #\tline length\nSet how many lines are allowed per subtitle. Default is 2." << std::endl << std::endl
                << "-c #\tcharacters per line\nSet how many characters are allowed per subtitle. Default is 42.";
            exit(err::ok.id);
        }

        //Scan the entire array of C strings and sets various things.
        for (int i = 1; i < argc; i++)
        {
            std::string currentArg = argv[i];
            if (currentArg == "-p") {
                //...
            }
            else if (currentArg == "-a") {
                //...
            }
            else if (currentArg == "-l") {
                //...
            }
            else if (currentArg == "-c") {
                //...
            }
            else {
                filename = currentArg;
            }
        }

Non è esattamente bello a vedersi. E’ per questo che per gestire gli argomenti passati al main si dovrebbero usare delle librerie apposite, come boost::program_options.

Leave a Comment

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *