1

ディレクトリをスキャンしてファイル情報を取得するプログラムに取り組んでいます。ユーザーが特定のファイル グループをスキャンしたり、特定の方法でスキャンしたり、特定の方法で出力したりするために使用できるオプションのスイッチがあります。

たとえば、ユーザーが次のように入力filesum -rRcすると、再帰スキャンが実行され、ファイルが昇順で出力され、C++ 関連のファイル拡張子 (.cpp|.h|.hppなど) のみがスキャンされます。

可能な限りクリーンな方法でこれを行うにはどうすればよいですか? 私は getopt を調べましたが、その実装をまったく理解していません。また、ドキュメントで適切な例を見つけることは困難です。

スイッチが入力されたコマンドライン引数を文字列に変換してそれを解析することを考えていましたが、引数にスイッチが1つだけかどうか、またはそれに続く何かがあるかどうかを確認するために複数のifステートメントは必要ありませんなどのことができ-rcますか?または、入力されたスイッチに基づいて異なるフラグを使用した while ループも考えていましたが、よりクリーンで簡単な方法があれば、提案をいただければ幸いです。ありがとう。

可能であれば、サードパーティのライブラリを使用しないことをお勧めします。

4

3 に答える 3

0

gnu cat がコマンドラインオプションをどのように処理するかを確認しました。私は C で例を書きました。次のようなフラグを渡すことができます: cli -ab file または cli -b -ac file または cli -bc file -a

#include <stdio.h>

int main (int argc, char *argv) {
    int c;
    while ((c = getopt(argc, argv, "abc")) != -1) {
        switch (c) {
            case 'a':
                printf("selected: a\n");
                break;
            case 'b':
                printf("selected: b\n");
                break;
            case 'c':
                printf("selected: c\n");
                break;
            default:
                printf("Usage: cli -a/-b/-c\n");
                break;
        }
    }
}
于 2013-08-03T01:27:44.920 に答える
0

これを行う最もクリーンな方法は、Boostprogram_optionsを使用することです。

于 2013-08-03T01:12:46.277 に答える
0

おかしいな、今やってたんだ。ここでは一般的な考え方だけを説明します。完全なコードは現在 500 行を超えており、書式設定などにより多くのユーティリティを使用しています。

例として、私はプログラムを作成していますhelp(これはかなりダミーです)。単純な構造体には、プログラムが必要とするすべてのオプションと、デフォルト値が含まれています。

struct help_opt
{
    string owner;
    string path;
    bool rec;
    int depth;
    help_opt() : owner(""), path("/"), rec(false), depth(0) { }
};

別の構造体は、コマンド ライン引数をモデル化します。

struct help_args : public help_opt, public arguments <help_args>
{
    template <typename S>
    void define(S& s)
    {
        set(s, owner,   "owner",    'w',  "force <name> as owner",         "name");
        set(s, path,    "output",   'o',  "save all output to <path>",     "path");
        set(s, rec,     "recurse",  'r',  "recurse into sub-topics");
        set(s, depth,   "depth",    'd',  "set <number> as maximum depth", "number");
    }

    string title() const { return "my help"; }
    string usage() const { return "help [<options>] [<topic>]"; }

    string info() const
    {
        return
            "Display help on <topic>, "
            "or list available topics if no <topic> is given.";
    }

    help_args(int argc, char* argv[]) : arguments(argc, argv) { }
};

classargumentsは必要なすべてのインフラストラクチャです。すべての引数とメタデータ (名前、略語など) はdefine()、それぞれメソッドの呼び出しによって で定義されset()ます。

引数sは、ユーザー入力の収集、ヘルプ テキストの作成、ユーザーが指定した値の表示など、複数の操作をサポートするために使用されます。次に、各メンバーへの参照を渡します。ユーザー入力に応じて適切な値が与えられるか、デフォルト値のままになります。次に、引数名、略語、完全なヘルプ テキスト、およびオプションでパラメーター名が続きます。ブール引数は、パラメーターなしでフラグとして個別に扱われます。

追加のメソッドtitle()などinfo()は、プログラムに固有の情報メッセージを指定します。

実際の処理は のコンストラクタによって行われargumentsます。これが を呼び出しdefine()help_args次に が を呼び出しset()ますarguments。オプションごとに、コマンド ライン入力がスキャンされ、必要に応じて変数が更新されます。同時に、メタデータが収集され、gnu プログラムのよう--help--usage、、、などのオプションの出力が自動的に生成されます。--version

help_argsテンプレートパラメータとして渡されるという事実は、それがテンプレートであるため仮想ではないにもかかわらず、基本クラスから呼び出されるargumentsことを許可 することです。define()単一の操作のみが必要な場合は、プレーンな仮想メソッドに戻すことができます。

私はこれがかなりきれいであることを願っています。利用可能なツールやライブラリがたくさんあることは知っていますが、私はこの方法が本当に好きです。準備ができたら実装を共有できます。ほぼ完了です。

于 2013-08-03T02:40:02.657 に答える