Fixing Command Line Option Parsing

保存时间:2026/4/4 18:00:32

Prompt

Response

You are absolutely right! The issue is that the -s and -r options, along with others, are not being recognized because the getopt_long function is being called twice with different option strings. The first call only processes -d and -D.

To fix this, you need to process all the options in a single loop. Here's the corrected main function:

C++
int main(int argc, char *argv[]) {
  try {
    if (argc == 1) {
      displayHelpMessage();
      return 0;
    }
    int option_index = 0;
    std::string device_path = "/dev/video0"; // Default device
    std::string snapshot_output;
    std::string record_sgf_output;
    bool probe_only = false;
    bool bDebug = false; // Initialize debug flag here

    struct option long_options[] = {
        {"process-image", required_argument, nullptr, 'p'},
        {"generate-sgf", required_argument, nullptr, 'g'},
        {"verify", required_argument, nullptr, 'v'},
        {"compare", required_argument, nullptr, 'c'},
        {"parse", required_argument, nullptr, 0},
        {"help", no_argument, nullptr, 'h'},
        {"debug", no_argument, nullptr, 'd'},
        {"probe-devices", no_argument, nullptr, 1},
        {"snapshot", required_argument, nullptr, 's'},
        {"device", required_argument, nullptr, 'D'},
        {"record-sgf", required_argument, nullptr, 'r'},
        {nullptr, 0, nullptr, 0}};

    int c;
    // Process all options in a single loop
    while ((c = getopt_long(argc, argv, "dp:g:v:c:h:s:r:D:", long_options,
                            &option_index)) != -1) {
      switch (c) {
      case 'd':
        bDebug = true;
        cout << "Debug mode enabled." << endl;
        break;
      case 'D':
        device_path = optarg;
        break;
      case 'p':
        processImageWorkflow(optarg);
        break;
      case 'g':
        if (optind < argc) {
          generateSGFWorkflow(optarg, argv[optind++]);
        } else {
          THROWGEMERROR(
              "-g option requires an input image path and an output SGF path.");
        }
        break;
      case 'v':
        if (optind < argc) {
          verifySGFWorkflow(optarg, argv[optind++]);
        } else {
          THROWGEMERROR("-v option requires an image path and an SGF path.");
        }
        break;
      case 'c':
        if (optind < argc) {
          compareSGFWorkflow(optarg, argv[optind++]);
        } else {
          THROWGEMERROR("-c option requires two SGF paths.");
        }
        break;
      case 'h':
        displayHelpMessage();
        return 0;
      case 0: // Long-only option
        if (strcmp(long_options[option_index].name, "parse") == 0) {
          parseSGFWorkflow(optarg);
        }
        break;
      case 1: // Long-only option
        if (strcmp(long_options[option_index].name, "probe-devices") == 0) {
          probe_only = true;
          probeVideoDevicesWorkflow();
        }
        break;
      case 's':
        snapshot_output = optarg;
        break;
      case 'r':
        record_sgf_output = optarg;
        break;
      case '?':
      default:
        displayHelpMessage();
        return 1;
      }
    }

    // Handle any remaining non-option arguments here if needed
    if (probe_only) {
      return 0; // Exit if only probing devices
    }

    if (!snapshot_output.empty()) {
      captureSnapshotWorkflow(device_path, snapshot_output);
    }

    if (!record_sgf_output.empty()) {
      recordSGFWorkflow(device_path, record_sgf_output);
    }
  } catch (const GEMError &e) {
    cerr << "Error: " << e.what() << endl;
    return 1;
  } catch (const std::exception &e) {
    cerr << "An unexpected error occurred: " << e.what() << endl;
    return 1;
  } catch (...) {
    cerr << "An unknown error occurred." << endl;
    return 1;
  }
  return 0;
}

Key Changes:

  1. Single getopt_long Loop: The code now has a single while loop that calls getopt_long to process all command-line options.

  2. Combined Short Options String: The third argument to getopt_long now includes all the short options: "dp:g:v:c:h:s:r:D:". The colons indicate that the preceding option requires an argument.

  3. bDebug Initialization: The bDebug flag is initialized to false at the beginning of the main function.

  4. Removed Second optind Reset: The line optind = 1; has been removed as it's no longer needed with a single parsing loop.

With these changes, the -s option (and other options) will be correctly parsed, and the captureSnapshotWorkflow should be executed as expected when you run ./gem.exe -s share/snapshot.jpg.