Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 5

Command-Line Argument Parsing with argc and argv

Recommended resources

Hello! Welcome to your fifth lesson on C programming.

In our last lesson, we explored how functions work in C, focusing on the crucial concept of pass-by-value. You learned that all function arguments are copies and that to modify a caller's data, we must explicitly pass a pointer to it. This understanding of functions, memory, and pointers is the bedrock for everything that follows.

Today, we'll apply this knowledge to a special function: main. We will explore how a C program receives input directly from the command line when it's launched. The learning outcome for this lesson is to parse basic command-line arguments using argc and argv to create simple interactive tools. This is your first step towards building the powerful command-line utilities, compilers, and system tools that are central to your goals.

The main Function's Special Signature

You've been writing int main(void) or just int main(), but main has an alternative, more powerful signature:

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

This form allows the operating system's shell (like bash) to pass information from the user directly into your program when it starts. Let's break down these two parameters:

  • int argc (argument count): An integer that holds the number of command-line arguments supplied. This count always includes the name of the program itself, so argc is at least 1.
  • char *argv[] (argument vector): This is the "argument vector." It's an array of strings. Since strings in C are pointers to characters (char *), argv is an array of character pointers. Each element of this array is one of the command-line arguments.

Here's a visual breakdown:

ArgC and ArgV in C (main) Diagram
This diagram shows how arguments provided on the command line are stored. The program's name is always `argv[0]`, and subsequent arguments fill the array `argv[1]`, `argv[2]`, and so on. `argc` stores the total count.

Accessing and Printing Arguments

Since argv is an array and argc tells us its size, we can easily loop through it to see what was passed to our program.

The following video provides a clear, practical demonstration of argc and argv and how to iterate through them.

What are command line arguments (argc and argv)?

The video 'What are command line arguments (argc and argv)?' from CodeVault clearly introduces these concepts.

Watch the first four and a half minutes (from 00:00 to 04:47). Pay attention to how argc is used as the boundary for the for loop and how argv[i] is used to access each string argument. The demonstration of running the program from a real command prompt is particularly useful.

As the video shows, a typical program to display all arguments looks like this:

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("Total number of arguments: %d\n\n", argc);

    for (int i = 0; i < argc; i++) {
        printf("Argument %d: %s\n", i, argv[i]);
    }

    return 0;
}

If you compile this program to an executable named my_program and run it from your terminal like this:

./my_program hello world 123

The output will be:

Total number of arguments: 4

Argument 0: ./my_program
Argument 1: hello
Argument 2: world
Argument 3: 123

Notice how the shell splits the command at the spaces to create the separate strings in the argv array.

Test your understanding!

Modify the code above to print only the arguments provided by the user, skipping the program's own name. For the command ./my_program hello world, it should only print "hello" and "world".

Show answer

You can achieve this by starting the loop from index 1 instead of 0.

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("User-provided arguments:\n");

    // Start loop at 1 to skip the program name
    for (int i = 1; i < argc; i++) {
        printf("%s\n", argv[i]);
    }

    return 0;
}

A Deeper Look at argv's Memory Structure

Given your interest in how things work under the hood, let's look closer at char *argv[]. This syntax can also be written as char **argv, which means "a pointer to a pointer to a character."

This sounds complex, but it makes sense:

  1. argv is a pointer that points to the beginning of an array.
  2. Each element in that array (e.g., argv[0], argv[1]) is also a pointer.
  3. Each of those pointers points to the first character of a null-terminated string stored somewhere else in memory.

This video offers a great visual model of this memory layout.

All you need to know about the command line arguments argc and *argv[ ]

The video 'All you need to know about the command line arguments' by Oceano has an excellent visual explanation of argv's structure in memory.

Watch the section from 02:57 to 05:08. The diagram clearly shows argv as an array of pointers, with each pointer pointing to a distinct string. This visual will help solidify the concept of a 'pointer to a pointer'.

Understanding this structure is key to mastering C, as this pattern of using pointers to manage collections of data is very common.


From Strings to Numbers: Building a Simple Tool

Command-line arguments are powerful, but they have one major catch: they are always passed as strings. If you want to perform arithmetic, you must first convert the string representation of a number (e.g., "123") into an actual integer type (e.g., 123).

Let's build a tool that multiplies numbers given on the command line. This requires conversion.

There are two common functions for this in C:

  1. atoi (ASCII to Integer): Simple, but not robust. It's defined in <stdlib.h>. If you give it a string that isn't a number (like "hello"), it returns 0. This is problematic because you can't tell if the user entered "0" or invalid text.
  2. strtol (String to Long): More complex, but far more powerful and safe. It's the professional choice. It can tell you if a conversion failed and where it stopped parsing.

To start, let's see a practical example that uses strtol.

What are command line arguments (argc and argv)?

Let's return to the CodeVault video, which now demonstrates building a simple multiplication tool.

Watch the section from 04:47 to 09:36. The author explains why a numeric conversion is necessary and introduces strtol. Note the three arguments to strtol: the string to convert, a pointer for error checking (passed as NULL here for simplicity), and the numeric base (10 for decimal).


Professional-Grade Conversion with strtol

The example in the video uses strtol in a simple way. To write truly robust code—the kind expected in production systems or at a top-tier tech company—you need to use strtol's full error-checking capabilities.

This involves checking two things:

  1. endptr: strtol can update a pointer you provide to show you where it finished parsing. If it couldn't parse anything, endptr will still point to the start of the string. If it contains leftover characters (like in "123xyz"), endptr will point to the 'x'.
  2. errno: This is a global variable from <errno.h> that C library functions use to report errors. If the number is too big or too small to fit in a long, strtol will set errno to ERANGE.

Let's examine how to use these features to write a truly solid conversion function.

How do I convert a number from the command line to an integer using strtol in C?

This Stack Overflow answer provides an excellent, concise example of how to use strtol with full error checking. This is what professional C code looks like.

Read the first answer provided by user 'chux'. First, review the code block in the section that starts 'Good strtol() usage involves...'. Notice how it checks errno and endptr to handle multiple failure cases. Then, review the section below it that explains the function prototype: long int strtol(const char *str, char **endptr, int base). This will clarify what each part does.

This level of rigor—checking arguments, handling conversion errors—is what separates beginner code from professional, reliable C programs.


Conclusion

You've now learned how to make your C programs interactive by accepting input from the command line. This is a fundamental skill for building everything from simple utilities to complex applications like compilers and servers.

Key Takeaways:

  • The main function can be declared as int main(int argc, char *argv[]) to receive command-line arguments.
  • argc is the count of arguments, and argv is an array of strings (char *) containing them.
  • argv[0] is always the path to the program executable. User arguments start at argv[1].
  • All arguments are passed as strings. For numeric operations, you must convert them.
  • strtol is the robust, professional function for string-to-number conversion, offering superior error handling compared to the simpler atoi.

In our next lesson, we will formalize error handling. We briefly saw errno today, and next time we will dive deep into checking function return values and using perror and errno to report errors gracefully. This is another essential skill for writing reliable software.



Practice Exercises

Now it's time to build some simple tools yourself. This will solidify your understanding of parsing command-line arguments.

  1. Echo Tool: Write a program that prints all of its command-line arguments to the screen, but with each argument on a new line. The program name should not be printed.

    • Example: ./echo one two three
    • Output:
      one
      two
      three
      
  2. Reverse Echo: Write a program that prints its command-line arguments in reverse order, again skipping the program name.

    • Example: ./reverse one two three
    • Output:
      three
      two
      one
      
  3. Summing Tool: Write a program that takes any number of integer arguments and prints their sum. Use strtol for conversion. If an argument is not a valid integer, print an error message to stderr (e.g., fprintf(stderr, "Error: '%s' is not a valid number.\n", argv[i]);) and skip it.

    • Example: ./sum 10 20 five 30
    • Output:
      Error: 'five' is not a valid number.
      Sum: 60
      
  4. Greeter: Write a program that expects exactly one command-line argument: a name. If the name is provided, it should print "Hello, <name>!". If the wrong number of arguments is given, it should print a usage message to stderr.

    • Example 1: ./greet_user
    • Output: Usage: ./greet_user <name>
    • Example 2: ./greet_user World
    • Output: Hello, World!
  5. Simple Calculator: Create a command-line calculator that takes exactly three arguments: two integers and an operator (+, -, *, /).

    • Check that argc is exactly 4. If not, print a usage message.
    • Use strtol to parse the first and third arguments as numbers.
    • The second argument is the operator. Check if it's a single character: +, -, *, or /.
    • Perform the calculation and print the result.
    • Include a check for division by zero.
    • Example: ./calc 30 / 3
    • Output: 30 / 3 = 10