Back to COMP1511 返回 COMP1511

Command Line Arguments 命令行参数

Core Notes for COMP1511 Command Line Arguments

课程概述 | Course Overview

命令行参数让C程序能够接收外部输入,使程序更加灵活和实用。掌握命令行参数处理是编写专业级C程序的基础技能:

  • 理解 argc 和 argv 的含义和用法
  • 学会解析和验证命令行输入
  • 掌握常见的参数模式和约定
  • 实现robust的错误处理
  • 构建可配置的命令行工具

1. 什么是命令行参数?

命令行参数是程序启动时从命令行传递给程序的数据。它们让用户可以在不修改源代码的情况下改变程序的行为。

$ ./my_program file.txt -n 10 --verbose
↑ 这个命令包含了多个参数

参数分解:

  • ./my_program:程序名(argv[0])
  • file.txt:第一个参数(argv[1])
  • -n:选项标志(argv[2])
  • 10:选项值(argv[3])
  • --verbose:长选项(argv[4])

main函数的完整形式:

int main(int argc, char *argv[]) {
    // argc: argument count(参数个数)
    // argv: argument vector(参数向量/数组)

    printf("程序接收到 %d 个参数\n", argc);

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

    return 0;
}

2. 深入理解 argc 和 argv

2.1 argc(Argument Count)

argc 是一个整数,表示传递给程序的参数总数,包括程序名本身

// 示例:./program hello world
// argc = 3(程序名 + 2个参数)

int main(int argc, char *argv[]) {
    printf("参数总数: %d\n", argc);  // 输出: 参数总数: 3

    if (argc < 2) {
        printf("用法: %s <参数1> [参数2] ...\n", argv[0]);
        return 1;  // 错误退出
    }

    return 0;
}

2.2 argv(Argument Vector)

argv 是一个字符串数组,每个元素都是一个指向C字符串的指针。

命令:./calculator 15 + 25

argv[0]
"./calculator"
argv[1]
"15"
argv[2]
"+"
argv[3]
"25"

argc = 4

重要提示:

所有命令行参数都是字符串!即使输入数字,也需要使用 atoi()atof() 等函数转换为数值类型。

3. 参数解析与处理

3.1 基本参数遍历

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

int main(int argc, char *argv[]) {
    printf("程序名: %s\n", argv[0]);
    printf("参数个数: %d\n", argc - 1);  // 减去程序名

    // 遍历所有参数(跳过程序名)
    for (int i = 1; i < argc; i++) {
        printf("参数 %d: %s\n", i, argv[i]);
    }

    return 0;
}

3.2 字符串到数字的转换

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

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("用法: %s <数字1> <数字2>\n", argv[0]);
        return 1;
    }

    // 转换字符串为整数
    int num1 = atoi(argv[1]);
    int num2 = atoi(argv[2]);

    printf("%d + %d = %d\n", num1, num2, num1 + num2);

    return 0;
}

3.3 参数验证

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

// 检查字符串是否为有效数字
int is_valid_number(const char *str) {
    if (str == NULL || *str == '\0') {
        return 0;  // 空字符串
    }

    // 允许负号
    if (*str == '-') {
        str++;
    }

    // 检查每个字符是否为数字
    while (*str) {
        if (!isdigit(*str)) {
            return 0;
        }
        str++;
    }

    return 1;
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        printf("用法: %s <数字>\n", argv[0]);
        return 1;
    }

    if (!is_valid_number(argv[1])) {
        printf("错误: '%s' 不是有效数字\n", argv[1]);
        return 1;
    }

    int number = atoi(argv[1]);
    printf("您输入的数字是: %d\n", number);
    printf("它的平方是: %d\n", number * number);

    return 0;
}

4. 常见参数模式

4.1 选项标志处理

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int verbose = 0;    // 详细输出标志
    int help = 0;       // 帮助标志
    char *filename = NULL;

    // 解析选项
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
            verbose = 1;
        } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
            help = 1;
        } else if (argv[i][0] != '-') {
            // 不以 '-' 开头的参数视为文件名
            filename = argv[i];
        } else {
            printf("未知选项: %s\n", argv[i]);
            return 1;
        }
    }

    if (help) {
        printf("用法: %s [选项] <文件名>\n", argv[0]);
        printf("选项:\n");
        printf("  -v, --verbose  详细输出\n");
        printf("  -h, --help     显示帮助\n");
        return 0;
    }

    if (filename == NULL) {
        printf("错误: 请指定文件名\n");
        return 1;
    }

    if (verbose) {
        printf("处理文件: %s\n", filename);
    }

    // 处理文件的代码...
    printf("文件 '%s' 处理完成\n", filename);

    return 0;
}

4.2 带值的选项

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

int main(int argc, char *argv[]) {
    int count = 1;      // 默认计数
    char *output = NULL; // 输出文件

    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-n") == 0) {
            // 下一个参数应该是数字
            if (i + 1 < argc) {
                count = atoi(argv[i + 1]);
                i++;  // 跳过已处理的参数
            } else {
                printf("错误: -n 选项需要一个数值\n");
                return 1;
            }
        } else if (strcmp(argv[i], "-o") == 0) {
            // 下一个参数应该是输出文件名
            if (i + 1 < argc) {
                output = argv[i + 1];
                i++;  // 跳过已处理的参数
            } else {
                printf("错误: -o 选项需要一个文件名\n");
                return 1;
            }
        }
    }

    printf("重复次数: %d\n", count);
    if (output) {
        printf("输出文件: %s\n", output);
    } else {
        printf("输出到标准输出\n");
    }

    return 0;
}

5. 实际应用示例

5.1 简单计算器

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

int main(int argc, char *argv[]) {
    if (argc != 4) {
        printf("用法: %s <数字1> <操作符> <数字2>\n", argv[0]);
        printf("操作符: +, -, *, /\n");
        return 1;
    }

    double num1 = atof(argv[1]);
    char *operator = argv[2];
    double num2 = atof(argv[3]);
    double result;

    if (strcmp(operator, "+") == 0) {
        result = num1 + num2;
    } else if (strcmp(operator, "-") == 0) {
        result = num1 - num2;
    } else if (strcmp(operator, "*") == 0) {
        result = num1 * num2;
    } else if (strcmp(operator, "/") == 0) {
        if (num2 == 0) {
            printf("错误: 除数不能为零\n");
            return 1;
        }
        result = num1 / num2;
    } else {
        printf("错误: 不支持的操作符 '%s'\n", operator);
        return 1;
    }

    printf("%.2f %s %.2f = %.2f\n", num1, operator, num2, result);

    return 0;
}

// 使用示例:
// $ ./calculator 15.5 + 8.3
// 15.50 + 8.30 = 23.80

5.2 文件处理工具

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

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("用法: %s [选项] <文件名1> [文件名2] ...\n", argv[0]);
        printf("选项:\n");
        printf("  -c  统计字符数\n");
        printf("  -l  统计行数\n");
        printf("  -w  统计单词数\n");
        return 1;
    }

    int count_chars = 0, count_lines = 0, count_words = 0;
    int file_start = 1;  // 文件名开始的索引

    // 解析选项
    for (int i = 1; i < argc && argv[i][0] == '-'; i++) {
        if (strcmp(argv[i], "-c") == 0) {
            count_chars = 1;
        } else if (strcmp(argv[i], "-l") == 0) {
            count_lines = 1;
        } else if (strcmp(argv[i], "-w") == 0) {
            count_words = 1;
        } else {
            printf("未知选项: %s\n", argv[i]);
            return 1;
        }
        file_start++;
    }

    // 如果没有指定选项,默认统计所有
    if (!count_chars && !count_lines && !count_words) {
        count_chars = count_lines = count_words = 1;
    }

    // 处理每个文件
    for (int i = file_start; i < argc; i++) {
        FILE *file = fopen(argv[i], "r");
        if (file == NULL) {
            printf("错误: 无法打开文件 '%s'\n", argv[i]);
            continue;
        }

        int chars = 0, lines = 0, words = 0;
        int in_word = 0;
        int c;

        while ((c = fgetc(file)) != EOF) {
            chars++;

            if (c == '\n') {
                lines++;
            }

            if (c == ' ' || c == '\t' || c == '\n') {
                in_word = 0;
            } else if (!in_word) {
                words++;
                in_word = 1;
            }
        }

        fclose(file);

        printf("%s: ", argv[i]);
        if (count_lines) printf("%d 行 ", lines);
        if (count_words) printf("%d 单词 ", words);
        if (count_chars) printf("%d 字符", chars);
        printf("\n");
    }

    return 0;
}

6. 最佳实践与常见错误

最佳实践:

  • 始终检查 argc 的值,确保有足够的参数
  • 提供清晰的用法信息和错误消息
  • 验证输入参数的有效性
  • 支持常见的选项约定(-h 帮助,-v 详细)
  • 处理边界情况(如除零、文件不存在等)

常见错误:

  • 忘记检查 argc,导致访问不存在的 argv 元素
  • 直接使用 atoi() 而不验证输入是否为数字
  • 没有处理文件打开失败的情况
  • 选项解析时没有检查是否有足够的参数
  • 错误信息不够清晰,用户不知道如何修正

错误处理模板:

int main(int argc, char *argv[]) {
    // 1. 检查参数个数
    if (argc < 2) {
        fprintf(stderr, "用法: %s <参数>\n", argv[0]);
        return 1;
    }

    // 2. 验证参数有效性
    if (!is_valid_input(argv[1])) {
        fprintf(stderr, "错误: 无效输入 '%s'\n", argv[1]);
        return 1;
    }

    // 3. 进行实际处理,捕获错误
    if (process_input(argv[1]) != 0) {
        fprintf(stderr, "错误: 处理失败\n");
        return 1;
    }

    return 0;  // 成功
}

7. 高级主题

7.1 使用 getopt() 解析选项

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>  // for getopt

int main(int argc, char *argv[]) {
    int opt;
    int verbose = 0;
    char *output_file = NULL;
    int count = 1;

    // 解析选项:v 无参数,o: 需要参数,n: 需要参数
    while ((opt = getopt(argc, argv, "vo:n:h")) != -1) {
        switch (opt) {
            case 'v':
                verbose = 1;
                break;
            case 'o':
                output_file = optarg;  // optarg 包含选项的参数
                break;
            case 'n':
                count = atoi(optarg);
                break;
            case 'h':
                printf("用法: %s [-v] [-o 输出文件] [-n 计数] 文件名\n", argv[0]);
                return 0;
            case '?':
                // getopt 会自动打印错误信息
                return 1;
        }
    }

    // 处理非选项参数
    for (int i = optind; i < argc; i++) {
        printf("处理文件: %s\n", argv[i]);
    }

    return 0;
}

7.2 环境变量结合

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

int main(int argc, char *argv[]) {
    // 从环境变量获取默认值
    char *default_editor = getenv("EDITOR");
    if (default_editor == NULL) {
        default_editor = "vi";  // 默认编辑器
    }

    char *editor = default_editor;

    // 命令行参数可以覆盖环境变量
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-e") == 0 && i + 1 < argc) {
            editor = argv[i + 1];
            i++;
        }
    }

    printf("使用编辑器: %s\n", editor);

    return 0;
}

总结

核心概念:

  • argc 和 argv 的含义
  • 参数解析和验证
  • 字符串到数字转换
  • 选项和标志处理
  • 错误处理和用户友好性

实用技能:

  • 构建命令行工具
  • 实现帮助系统
  • 处理多种输入格式
  • 使用标准库函数
  • 遵循UNIX约定

命令行参数是C程序与外界交互的重要接口。掌握了这些技能,你就能编写出真正实用的命令行工具和应用程序。

Course Overview

Command line arguments allow C programs to receive external input, making programs more flexible and practical. Mastering command line argument handling is a fundamental skill for writing professional C programs:

  • Understand the meaning and usage of argc and argv
  • Learn to parse and validate command line input
  • Master common argument patterns and conventions
  • Implement robust error handling
  • Build configurable command line tools

1. What Are Command Line Arguments?

Command line arguments are data passed to a program from the command line when it starts. They allow users to change the program's behavior without modifying the source code.

$ ./my_program file.txt -n 10 --verbose
↑ This command contains multiple arguments

Argument Breakdown:

  • ./my_program: Program name (argv[0])
  • file.txt: First argument (argv[1])
  • -n: Option flag (argv[2])
  • 10: Option value (argv[3])
  • --verbose: Long option (argv[4])

Complete form of the main function:

int main(int argc, char *argv[]) {
    // argc: argument count
    // argv: argument vector (array)

    printf("Program received %d arguments\n", argc);

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

    return 0;
}

2. Deep Dive into argc and argv

2.1 argc (Argument Count)

argc is an integer representing the total number of arguments passed to the program, including the program name itself.

// Example: ./program hello world
// argc = 3 (program name + 2 arguments)

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

    if (argc < 2) {
        printf("Usage: %s  [arg2] ...\n", argv[0]);
        return 1;  // Error exit
    }

    return 0;
}

2.2 argv (Argument Vector)

argv is an array of strings, where each element is a pointer to a C string.

Command: ./calculator 15 + 25

argv[0]
"./calculator"
argv[1]
"15"
argv[2]
"+"
argv[3]
"25"

argc = 4

Important Note:

All command line arguments are strings! Even if you enter numbers, you need to use atoi(), atof(), etc. to convert them to numeric types.

3. Parsing and Processing Arguments

3.1 Basic Argument Iteration

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

int main(int argc, char *argv[]) {
    printf("Program name: %s\n", argv[0]);
    printf("Argument count: %d\n", argc - 1);  // Subtract program name

    // Iterate through all arguments (skip program name)
    for (int i = 1; i < argc; i++) {
        printf("Argument %d: %s\n", i, argv[i]);
    }

    return 0;
}

3.2 String to Number Conversion

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

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("Usage: %s <number1> <number2>\n", argv[0]);
        return 1;
    }

    // Convert strings to integers
    int num1 = atoi(argv[1]);
    int num2 = atoi(argv[2]);

    printf("%d + %d = %d\n", num1, num2, num1 + num2);

    return 0;
}

3.3 Argument Validation

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

// Check if a string is a valid number
int is_valid_number(const char *str) {
    if (str == NULL || *str == '\0') {
        return 0;  // Empty string
    }

    // Allow negative sign
    if (*str == '-') {
        str++;
    }

    // Check each character is a digit
    while (*str) {
        if (!isdigit(*str)) {
            return 0;
        }
        str++;
    }

    return 1;
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        printf("Usage: %s <number>\n", argv[0]);
        return 1;
    }

    if (!is_valid_number(argv[1])) {
        printf("Error: '%s' is not a valid number\n", argv[1]);
        return 1;
    }

    int number = atoi(argv[1]);
    printf("You entered: %d\n", number);
    printf("Its square is: %d\n", number * number);

    return 0;
}

4. Common Argument Patterns

4.1 Option Flag Handling

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int verbose = 0;    // Verbose output flag
    int help = 0;       // Help flag
    char *filename = NULL;

    // Parse options
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
            verbose = 1;
        } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
            help = 1;
        } else if (argv[i][0] != '-') {
            // Arguments not starting with '-' are treated as filenames
            filename = argv[i];
        } else {
            printf("Unknown option: %s\n", argv[i]);
            return 1;
        }
    }

    if (help) {
        printf("Usage: %s [options] <filename>\n", argv[0]);
        printf("Options:\n");
        printf("  -v, --verbose  Verbose output\n");
        printf("  -h, --help     Show help\n");
        return 0;
    }

    if (filename == NULL) {
        printf("Error: Please specify a filename\n");
        return 1;
    }

    if (verbose) {
        printf("Processing file: %s\n", filename);
    }

    // File processing code...
    printf("File '%s' processed successfully\n", filename);

    return 0;
}

4.2 Options with Values

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

int main(int argc, char *argv[]) {
    int count = 1;      // Default count
    char *output = NULL; // Output file

    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-n") == 0) {
            // Next argument should be a number
            if (i + 1 < argc) {
                count = atoi(argv[i + 1]);
                i++;  // Skip processed argument
            } else {
                printf("Error: -n option requires a numeric value\n");
                return 1;
            }
        } else if (strcmp(argv[i], "-o") == 0) {
            // Next argument should be an output filename
            if (i + 1 < argc) {
                output = argv[i + 1];
                i++;  // Skip processed argument
            } else {
                printf("Error: -o option requires a filename\n");
                return 1;
            }
        }
    }

    printf("Repeat count: %d\n", count);
    if (output) {
        printf("Output file: %s\n", output);
    } else {
        printf("Output to stdout\n");
    }

    return 0;
}

5. Practical Examples

5.1 Simple Calculator

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

int main(int argc, char *argv[]) {
    if (argc != 4) {
        printf("Usage: %s <number1> <operator> <number2>\n", argv[0]);
        printf("Operators: +, -, *, /\n");
        return 1;
    }

    double num1 = atof(argv[1]);
    char *operator = argv[2];
    double num2 = atof(argv[3]);
    double result;

    if (strcmp(operator, "+") == 0) {
        result = num1 + num2;
    } else if (strcmp(operator, "-") == 0) {
        result = num1 - num2;
    } else if (strcmp(operator, "*") == 0) {
        result = num1 * num2;
    } else if (strcmp(operator, "/") == 0) {
        if (num2 == 0) {
            printf("Error: Division by zero\n");
            return 1;
        }
        result = num1 / num2;
    } else {
        printf("Error: Unsupported operator '%s'\n", operator);
        return 1;
    }

    printf("%.2f %s %.2f = %.2f\n", num1, operator, num2, result);

    return 0;
}

// Usage example:
// $ ./calculator 15.5 + 8.3
// 15.50 + 8.30 = 23.80

5.2 File Processing Tool

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

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("Usage: %s [options] <file1> [file2] ...\n", argv[0]);
        printf("Options:\n");
        printf("  -c  Count characters\n");
        printf("  -l  Count lines\n");
        printf("  -w  Count words\n");
        return 1;
    }

    int count_chars = 0, count_lines = 0, count_words = 0;
    int file_start = 1;  // Index where filenames begin

    // Parse options
    for (int i = 1; i < argc && argv[i][0] == '-'; i++) {
        if (strcmp(argv[i], "-c") == 0) {
            count_chars = 1;
        } else if (strcmp(argv[i], "-l") == 0) {
            count_lines = 1;
        } else if (strcmp(argv[i], "-w") == 0) {
            count_words = 1;
        } else {
            printf("Unknown option: %s\n", argv[i]);
            return 1;
        }
        file_start++;
    }

    // If no options specified, count everything by default
    if (!count_chars && !count_lines && !count_words) {
        count_chars = count_lines = count_words = 1;
    }

    // Process each file
    for (int i = file_start; i < argc; i++) {
        FILE *file = fopen(argv[i], "r");
        if (file == NULL) {
            printf("Error: Cannot open file '%s'\n", argv[i]);
            continue;
        }

        int chars = 0, lines = 0, words = 0;
        int in_word = 0;
        int c;

        while ((c = fgetc(file)) != EOF) {
            chars++;

            if (c == '\n') {
                lines++;
            }

            if (c == ' ' || c == '\t' || c == '\n') {
                in_word = 0;
            } else if (!in_word) {
                words++;
                in_word = 1;
            }
        }

        fclose(file);

        printf("%s: ", argv[i]);
        if (count_lines) printf("%d lines ", lines);
        if (count_words) printf("%d words ", words);
        if (count_chars) printf("%d characters", chars);
        printf("\n");
    }

    return 0;
}

6. Best Practices and Common Mistakes

Best Practices:

  • Always check the value of argc to ensure sufficient arguments
  • Provide clear usage information and error messages
  • Validate the validity of input arguments
  • Support common option conventions (-h for help, -v for verbose)
  • Handle edge cases (such as division by zero, file not found, etc.)

Common Mistakes:

  • Forgetting to check argc, leading to access of non-existent argv elements
  • Using atoi() directly without validating the input is a number
  • Not handling file open failures
  • Not checking for sufficient arguments when parsing options
  • Error messages not clear enough for users to know how to fix the issue

Error Handling Template:

int main(int argc, char *argv[]) {
    // 1. Check argument count
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <argument>\n", argv[0]);
        return 1;
    }

    // 2. Validate argument
    if (!is_valid_input(argv[1])) {
        fprintf(stderr, "Error: Invalid input '%s'\n", argv[1]);
        return 1;
    }

    // 3. Perform actual processing, catch errors
    if (process_input(argv[1]) != 0) {
        fprintf(stderr, "Error: Processing failed\n");
        return 1;
    }

    return 0;  // Success
}

7. Advanced Topics

7.1 Parsing Options with getopt()

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>  // for getopt

int main(int argc, char *argv[]) {
    int opt;
    int verbose = 0;
    char *output_file = NULL;
    int count = 1;

    // Parse options: v no argument, o: requires argument, n: requires argument
    while ((opt = getopt(argc, argv, "vo:n:h")) != -1) {
        switch (opt) {
            case 'v':
                verbose = 1;
                break;
            case 'o':
                output_file = optarg;  // optarg contains the option's argument
                break;
            case 'n':
                count = atoi(optarg);
                break;
            case 'h':
                printf("Usage: %s [-v] [-o output_file] [-n count] filename\n", argv[0]);
                return 0;
            case '?':
                // getopt automatically prints error messages
                return 1;
        }
    }

    // Process non-option arguments
    for (int i = optind; i < argc; i++) {
        printf("Processing file: %s\n", argv[i]);
    }

    return 0;
}

7.2 Combining with Environment Variables

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

int main(int argc, char *argv[]) {
    // Get default value from environment variable
    char *default_editor = getenv("EDITOR");
    if (default_editor == NULL) {
        default_editor = "vi";  // Default editor
    }

    char *editor = default_editor;

    // Command line arguments can override environment variables
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-e") == 0 && i + 1 < argc) {
            editor = argv[i + 1];
            i++;
        }
    }

    printf("Using editor: %s\n", editor);

    return 0;
}

Summary

Core Concepts:

  • The meaning of argc and argv
  • Argument parsing and validation
  • String to number conversion
  • Option and flag handling
  • Error handling and user-friendliness

Practical Skills:

  • Building command line tools
  • Implementing help systems
  • Handling multiple input formats
  • Using standard library functions
  • Following UNIX conventions

Command line arguments are a vital interface between C programs and the outside world. With these skills mastered, you can write truly useful command line tools and applications.