Vala与C的命令行参数处理

命令行应用在Unix类系统上很流行,而Vala借助OptionContext类可以方便地处理命令行参数。

下例根据valadoc官方例子改编,供参考:

Vala

/**
 * @{author} YanWen
 * @{email} i@yanwen.email
 * @{file} cli_app.vala
 * @{last_modified} 2017-11-03
 * @{description} a vala cli demo
 */

/**
 * @{class} Person
 */
public class Person : GLib.Object {

  // Command line arguments
  private static bool version = false;
  private static string fullname = null;
  private static int age = 0;

  // NOTE: the most prominent attributes
  [CCode (array_length = false, array_null_terminated = true)]
  private static string[]? hobbies = null;

  // Entry options
  private const GLib.OptionEntry[] options = {
    // -v, --version
    { "version", 'v', 0, OptionArg.NONE, ref version, "Display version number", null },
    // -n, --fullname
    { "fullname", 'n', 0, OptionArg.STRING, ref fullname, "Set your fullname", "FULLNAME" },
    // -a, --age
    { "age", 'a', 0, OptionArg.INT, ref age, "Set your age", "AGE" },
    // -a, --age
    { "hobbies", 'b', 0, OptionArg.STRING_ARRAY, ref hobbies, "Set your hobbies", "HOBBY..." },
    // list terminator
    { null }
  };

  public static void say_version() {
    stdout.puts("Person 0.0.1n");
  }

  public static void introduce_myself() {
    stdout.puts(@"My name is $fullname, I am $age years old. My hobbies are");
    foreach (string hobby in hobbies) { stdout.puts(@" $hobby"); }
    stdout.puts(".n");
  }

  public static int main(string [] argv) {
    try {
      var opt_context = new OptionContext("- Person help");
      opt_context.set_help_enabled(true);
      opt_context.add_main_entries(options, null);
      opt_context.parse(ref argv);
    } catch (OptionError e) {
      stderr.printf(@"Error: %sn", e.message);;
      stdout.printf("Run '%s -h' to see a full list of available command line optionsn", argv[0]);
      return -1;
    }

    if (version) { say_version(); return 0; }

    introduce_myself();

    return 0;
  }
}

上例输出示例:

-h, –help参数

[yanwen@localhost]$ ./Person -h
Usage:
  Person [OPTION?] - Person help

Help Options:
  -h, --help                  Show help options

Application Options:
  -v, --version               Display version number
  -n, --fullname=FULLNAME     Set your fullname
  -a, --age=AGE               Set your age
  -b, --hobbies=HOBBY...      Set your hobbies

-v –version参数

[yanwen@localhost]$ ./Person -v
Person 0.0.1

Vala 示例

[yanwen@localhost]$ ./Person -n YanWen -a 20 -b gaming -b reading
My name is YanWen, I am 20 years old. My hobbies are gaming reading.

C

Unix类系统上,可以用“unistd.h”库实现相同的功能(详见参考资料),不过下例更好地处理了单选项多参数命令行。比如传入hobbies的多参数可以直接写成“-b gaming reading”,当然,Vala也可以实现。

/**
 * @{author} YanWen
 * @{email} i@yanwen.email 
 * @{file} cli_app.c
 * @{last_modified} 2017-11-10
 * @{description} a c cli demo
 */

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

#define MAX_NUM_HOBBIES 10

// Private data

// Persons' information
struct global_args_t {
  char * fullname;
  int age;
  char * hobbies[MAX_NUM_HOBBIES];
  int num_hobbies;
} global_args;

static const char * opt_string = "vn:a:b:h?";

static const struct option long_opts[] = {
  { "version", no_argument, NULL, 'v' },
  { "fullname", required_argument, NULL, 'n' },
  { "age", required_argument, NULL, 'a' },
  { "hobbies", required_argument, NULL, 'b' },
  { "help", no_argument, NULL, 'h' },
  { NULL, no_argument, NULL, 0}
};

// Private methods
void say_version() {
  puts("Person 0.0.1");

  exit(EXIT_SUCCESS);
}

void introduce_myself() {
  printf("My name is %s, I am %d years old. My hobbies are",
    global_args.fullname, global_args.age);

  for (size_t index = 0; index < global_args.num_hobbies; index++) {
    printf(" %s", global_args.hobbies[index]);
  }
  puts("");
}

void say_help() {
  puts("Usage:n
  Person [OPTION?] - Person helpn
n
Help Options:n
  -h, --help                  Show help optionsn
n
Application Options:n
  -v, --version               Display version numbern
  -n, --fullname=FULLNAME     Set your fullnamen
  -a, --age=AGE               Set your agen
  -b, --hobbies=HOBBY...      Set your hobbies");

  exit(EXIT_FAILURE);
}

// Public static
int main(int argc, char * argv[]) {
  global_args.fullname = NULL;
  global_args.age = 0;

  int option = 0, long_index = 0;

  while ((option = getopt_long(argc, argv, opt_string, long_opts, & long_index)) != -1) {
    switch (option) {
      case 'v':
        say_version();
        break;
      case 'n':
        global_args.fullname = optarg;
        break;
      case 'a':
        global_args.age = atoi(optarg);
        break;
      case 'b': {
        global_args.num_hobbies = 0;
        char * hobby = optarg;
        do {
          global_args.hobbies[global_args.num_hobbies] = hobby;
        } while (
          NULL != (hobby = argv[optind + global_args.num_hobbies++])
          && hobby[0] != '-'
        );

        break;
      }
      case 'h':
      case '?':
        say_help();
        break;
      default:
        say_help();
    }
  }

  introduce_myself();

  return 0;
}

C 示例

[yanwen@localhost]$ ./Person -n YanWen -a 20 -b gaming reading
My name is YanWen, I am 20 years old. My hobbies are gaming reading.

参考:

作者: V

Web Dev

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s