Command Line Arguments

Why Programs Need External Input

When you compile and link your program, the compiler produces an executable file. When this executable runs, execution begins at the main() function. Up to this point, we've been declaring main with no parameters:

int main()

But what if your program needs input data before it starts running? Consider a simple text processing tool called WordCounter that analyzes text files. How would it know which file to process?

You could write the program to ask for the filename after it starts:

// Program: WordCounter
#include <iostream>
#include <string>

int main()
{
    std::cout << "Enter filename to analyze: ";
    std::string filename{};
    std::cin >> filename;

    // process the file
    // count words
    // display results
}

While this works for manual use, it creates problems in automation scenarios:

  1. Batch processing: If you want to analyze 100 files, you'd need to type each filename manually
  2. Automated workflows: A web server or script can't programmatically provide input to a waiting program
  3. Integration: Other programs need a way to invoke your program with specific inputs

The solution is command line arguments - optional string parameters passed to your program when it launches by the operating system.

Passing Command Line Arguments

Executable programs can be launched from the command line by name. To run an executable called "FileStats" located in the current directory:

On Windows:

FileStats

On Unix-based systems (Linux, macOS):

./FileStats

To pass command line arguments, list them after the executable name, separated by spaces:

FileStats report.txt

You can pass multiple arguments:

FileStats report.txt output.csv --verbose

IDE Configuration

Most IDEs provide a way to specify command line arguments for testing:

Visual Studio:

  1. Right-click your project in Solution Explorer → Properties
  2. Configuration Properties → Debugging
  3. Enter arguments in the "Command Arguments" field

Code::Blocks:

  • Project → Set program's arguments

Accessing Command Line Arguments

To access command line arguments in your C++ program, use an alternate form of main():

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

Alternative syntax (functionally identical):

int main(int argc, char** argv)

argc (argument count) is an integer containing the number of arguments passed to the program. It's always at least 1 because the first argument is the program name itself.

argv (argument vector) is an array of C-style strings containing the actual argument values. The array length is argc.

Here's a program that displays all command line arguments:

// Program: ShowArgs
#include <iostream>

int main(int argc, char* argv[])
{
    std::cout << "Received " << argc << " arguments:\n";

    for (int i{0}; i < argc; ++i)
    {
        std::cout << i << ": " << argv[i] << '\n';
    }

    return 0;
}

Running ShowArgs data.txt output.txt produces:

Received 3 arguments:
0: C:\Projects\ShowArgs
1: data.txt
2: output.txt

Note: argv[0] contains the path and name of the program itself. The actual user-provided arguments start at argv[1].

We cannot use range-based for loops with argv because range-based for loops don't work with decayed C-style arrays.

Working with Numeric Arguments

Command line arguments are always passed as strings, even if they look like numbers. To use a numeric argument, you must convert it from string to number.

Here's the C++ approach using std::stringstream:

#include <iostream>
#include <sstream>
#include <string>

int main(int argc, char* argv[])
{
    if (argc <= 1)
    {
        if (argv[0])
            std::cout << "Usage: " << argv[0] << " <count>\n";
        else
            std::cout << "Usage: <program> <count>\n";

        return 1;
    }

    std::stringstream converter{argv[1]};

    int count{};
    if (!(converter >> count))
        count = 0; // default value if conversion fails

    std::cout << "Count value: " << count << '\n';

    return 0;
}

Running with input "42":

Count value: 42

The std::stringstream works similarly to std::cin. We initialize it with argv[1] and use operator>> to extract the value into an integer variable.

How the OS Parses Arguments

When you enter a command at the terminal or run a program from an IDE, the operating system parses the command line before launching your program.

Different operating systems have specific parsing rules for special characters:

Simple example - spaces separate arguments:

ShowArgs hello world

Output:

Received 3 arguments:
0: C:\ShowArgs
1: hello
2: world

Double quotes group words into single arguments:

ShowArgs "hello world"

Output:

Received 2 arguments:
0: C:\ShowArgs
1: hello world

Most systems allow escaping quotes with backslashes:

ShowArgs \"hello world\"

Output:

Received 3 arguments:
0: C:\ShowArgs
1: "hello
2: world"

Different operating systems may have additional special characters requiring escaping or quoting.

Design Recommendations

Command line arguments provide flexibility for users and automation. Consider these design patterns:

  1. Make critical inputs optional with prompts: If a required argument isn't provided, prompt the user for it interactively
  2. Provide helpful usage messages: Always check argc and display usage when required arguments are missing
  3. Support both modes: Design programs to work both with command line arguments and interactively

Example:

#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
    std::string filename{};

    if (argc > 1)
    {
        filename = argv[1]; // got filename from command line
    }
    else
    {
        std::cout << "Enter filename: ";
        std::cin >> filename; // prompt user if not provided
    }

    std::cout << "Processing file: " << filename << '\n';
    // process the file

    return 0;
}

This program works when called as ./program data.txt OR when run with no arguments (it will prompt).

Best practice

Make input data that a program requires to operate available as command line arguments. If arguments aren't provided, prompt the user for input. This makes your program flexible for both manual and automated use.

Summary

Command line arguments: Optional string parameters passed to programs when launched by the operating system, enabling automation and integration with other tools.

Passing arguments: List arguments after the executable name, separated by spaces. On Windows: Program arg1 arg2. On Unix: ./Program arg1 arg2.

Accessing in main(): Use alternate main signature: int main(int argc, char* argv[]) or int main(int argc, char** argv).

argc (argument count): Integer containing the number of arguments. Always at least 1 because argv[0] contains the program name.

argv (argument vector): Array of C-style strings containing argument values. Length is argc. First element (argv[0]) is the program path/name; actual user arguments start at argv[1].

Arguments are strings: All command line arguments are passed as strings, even if they look like numbers. Convert to other types using std::stringstream or similar conversion functions.

OS parsing rules: Operating systems parse command lines before launching programs. Double quotes group words into single arguments. Backslashes escape special characters. Specific rules vary by OS.

IDE configuration: Most IDEs provide settings to specify command line arguments for testing without running from terminal.

Design recommendations:

  • Make critical inputs available via command line for automation
  • Provide helpful usage messages when required arguments are missing
  • Support both command line and interactive modes
  • Prompt for missing required arguments rather than failing silently

Command line arguments enable programs to work in both interactive and automated contexts, making them more versatile and easier to integrate with scripts, batch processes, and other programs.