1.13.1.  main, and Command-Line Arguments

[ fromfile: clargs.xml id: clargs ]

main() is a function that is called at program startup. If you want the program to accept command-line arguments, you must define main with its full parameter list.

C and C++ permit some flexibility in the way that arguments are defined in main(), so you may see it defined in a variety of ways:

int main(int argc, char* argv[])
int main(int argCount, char ** argValues)
int main(int argc, char * const argv[])

All the forms above are valid, and they each define two parameters: an int to contain the number of command-line arguments and an array of C-style strings to contain the actual arguments. These parameters contain enough information to reconstruct the command-line arguments passed into the program from the parent process.[15] Example 1.19 is a simple main program that prints its command-line arguments.

Example 1.19. src/clargs/clargs-iostream/clargs.cpp

#include <iostream>
#include <cstdlib>  1

int main (int argc, char* argv[]) {
    using namespace std;
    cout << "argc = " << argc << endl;
    for (int i = 0; i < argc; ++i) {
        cout << "argv# " << i << " is " << argv[i] << endl;
    }
    int num = atoi(argv[argc - 1]);
    cout << num * 2 << endl;
    return 0;
}

1

for atoi()


argv, the argument vector, is an array (Section 21.4) that contains all the command-line strings. In other words, because each individual command-line string is itself an array of char, argv is an array of char arrays. argc, the argument count, is the number of char arrays in argv.

main() needs to return an int to the parent process. In *nix systems, the return value of a process is called its exit status. Presumably, the parent process can use the exit status to decide what to do next.[16] The return value should be 0 if all went well, or a nonzero error code if something went wrong. This can be accomplished in a few different ways.

[Note] Note

Try not to confuse this interpretation of 0 with the bool value false, which is also equal to zero.

If you run this program with command-line arguments, you will see something like this in the output:

clargs> ./clargs spam eggs "space wars" 123
argc = 5
argv# 0 is ./clargs
argv# 1 is spam
argv# 2 is eggs
argv# 3 is space wars
argv# 4 is 123
246

The first argument is the name of the executable. The other arguments are taken from the command-line as strings separated by spaces or tabs. To pass a string that contains spaces as a single argument, you must enclose the string in quotes.

The last argument looks like the number 123. In fact, it is the string representation of that number. If you need to calculate with that number, it would be necessary to use a suitable function to convert the string "123" to the number 123.

Processing Command-Line Arguments with Qt

In example Example 1.20, we have rewritten Example 1.19 to set up and access the command-line arguments using Qt types and avoiding the use of arrays. The two applications produce the same output.

Example 1.20. src/clargs/qt/clargs.cpp

#include <QTextStream>
#include <QCoreApplication>
#include <QStringList>

int main (int argc, char* argv[]) {
    QCoreApplication app(argc, argv);
    QTextStream cout(stdout);
    QStringList arglst = app.arguments();
    cout << "argc = " << argc << endl;
    for (int i=0; i<arglst.size(); ++i) {
        cout << QString("argv#%1 is %2").arg(i).arg(arglst[i]) << endl;
    }
    int num = arglst[argc - 1].toInt();
    cout << num * 2 << endl;
}


Most applications that employ Qt types should define an object of type QCoreApplication or QApplication as early as possible in main(). [17] Section 8.3 discusses the reasons for this and the distinctions between those two types in more detail.

The QCoreApplication app is initialized with the argument count and the argument vector. app silently converts the char arrays in argv to QStrings and stores those strings in a QStringList (Section 4.2.1). You can then access and process the command-line arguments by using app to call the arguments() function. Using higher-level data structures like these eliminates the need to work with char arrays, which reduces the risk of memory corruption. [18]

Notice the use of the QString function toInt().



[15] The process that called main() (e.g., a command-line shell, a window manager, etc)

[16] We discuss programs that control various separate processes in Section 17.1.

[17] Applications that use only types such as QString, QStringList, and QTextStream do not need a QCoreApplication.

[18] First read Section 1.15 then Chapter 21. Bjarne Stroustrup also has some helpful advice on this subject.