C++解析命令行参数

说是c++,其实是c语言的接口。详细参考man 3 getopt。直接看例子,

void show_usage(const char* exe_name) {
    printf(
        "Usage:\t%s [options] file\n\n"
        "    -c, --cut <n>          Cut the mdl binary file containing first n messages.\n"
        "    --calc a[,b,c,...,n]   Calculate the offsets of a[b,c,...,n] messages in mdl binary file.\n"
        "    -h                     Print help message and exit.\n\n",
        exe_name);
}
 
int main(int argc, char* const* argv) {
    int c, n_opts;
    uint64_t n_cut_msg = 0;
    vector<uint64_t> msg_sizes;
    while (true) {
        int option_index = 0;
        int this_option_optind = optind ? optind : 1;
        static struct option longopts[] = {
            {"cut", required_argument, 0, 'c'},
            {"calc", required_argument, 0, 0},
            {"verbose", no_argument, 0, 0},
            {"help", no_argument, 0, 'h'},
            {"file", required_argument, 0, 0},
            {0, 0, 0, 0},
        };
        c = getopt_long(argc, argv, "hc:012", longopts, &option_index);
        if (c == -1)
            break;
 
        ++n_opts;
        switch (c) {
        case 0:
            printf("option %s", longopts[option_index].name);
            if (optarg)
                printf(" with arg %s", optarg);
            printf("\n");
            if (strcmp(longopts[option_index].name, "calc") == 0 &&
                !parse_calc_args(optarg, msg_sizes)) {
                return 1;
            }
            break;
 
        case 'h':
            show_usage(argv[0]);
            return 0;
 
        case 'c':
            if (!parse_cut_args(optarg, n_cut_msg)) {
                return 1;
            }
            break;
 
        case '?':
            break;
 
        default:
            printf("?? getopt returned char code 0%o ??\n", c);
        }
    }
 
    vector<string> non_opt_args;
    while (optind < argc) non_opt_args.emplace_back(argv[optind++]);
 
    // If no options and no non-option arguments, show usage
    if (non_opt_args.empty() && n_opts == 0) {
        show_usage(argv[0]);
        return 1;
    }
 
    if (n_cut_msg > 0) {
        if (non_opt_args.size() != 1) {
            printf("missing file argument!");
            return 1;
        }
        if (!SplitMdlBinary(non_opt_args[0], n_cut_msg)) {
            printf("split binary file failed!");
            return 2;
        }
    }
 
    if (!msg_sizes.empty()) {
        if (non_opt_args.size() != 1) {
            printf("missing file argument!");
            return 1;
        }
        auto offsets = CountMessageOffset(non_opt_args[0], std::move(msg_sizes));
        if (offsets.empty()) {
            printf("count message offsets failed!");
            return 2;
        }
        for (auto& off : offsets) {
            printf("%lu\n", off);
        }
    }
 
    return 0;
}