LoginSignup
2
2

More than 5 years have passed since last update.

C++でcommand line引数をparseしたい人生だった

Posted at

Gnuに勝てるわけないだろ!馬鹿野郎お前俺は書くぞお前!


というわけでC++でコマンドライン引数をparseしたいわけで、
gccにはgnu getoptという素敵な物があるわけですが、
Gnu汚染やだよねとかいうアレコレもあるので、書いてみました。

#pragma once
#include <string>
#include <iostream>
#include <vector>
#include <map>

class Option{
    std::map<const std::string, const bool> shortNoArg;
    std::map<const std::string, const std::string> shortWithArg;
    void Parse(const std::size_t argc, const std::string* const options){
        for(std::size_t i = 0 ; i < argc ; ++ i){
            if(options[i][0] == '-'){
                //This is opt
                //If this is the last, this is bool.
                if(i == argc - 1){
                    for(std::size_t c = 1 ; c < options[i].length() ; ++ c){
                        shortNoArg.insert(std::map<std::string, bool>::value_type(options[i].substr(c, 1), true));
                    }
                }else{
                    //Look up next and if it starts '-', this is bool.
                    if(options[i+1][0] == '-'){
                        for(std::size_t c = 1 ; c < options[i].length() ; ++ c){
                            shortNoArg.insert(std::map<std::string, bool>::value_type(options[i].substr(c, 1), true));
                        }
                    }else{//otherwise
                        shortWithArg.insert(std::map<std::string, std::string>::value_type(options[i].substr(1, 1), options[i+1]));
                    }
                }
            }else{
                //This is arg
            }
        }
    }
    public:
    Option(std::size_t argc, char** argv){
        std::string* options = new std::string[argc];
        for(std::size_t i = 0 ; i < argc ; ++ i){
            options[i] = argv[i];
        }
        Parse(argc, options);
        delete [] options;
    }
    ~Option(){
    }
    void Show(void){
        std::cout << "Boolean Options" << std::endl;
        for(std::map<const std::string, const bool>::iterator it = shortNoArg.begin() ; it != shortNoArg.end() ; ++ it){
            std::cout << it->first << ", " << it->second << std::endl;
        }
        std::cout << "Options w/ Argument" << std::endl;
        for(std::map<const std::string, const std::string>::iterator it = shortWithArg.begin() ; it != shortWithArg.end() ; ++ it){
            std::cout << it->first << ", " << it->second << std::endl;
        }
    }
    bool GetShortNoArgument(const std::string key){
        return shortNoArg[key];
    }
    std::string GetShortWithArgument(const std::string key){
        return shortWithArg[key];
    }
};

で、これをopt.hみたいな名前にしといて、
つかい方としてはこんな感じ。

#include "opt.h"
int main(int argc, char** argv){
    Option opts(argc, argv);
    opts.Show();
    std::cout << opts.GetShortNoArgument("a") << std::endl;
    std::cout << opts.GetShortWithArgument("b") << std::endl;
    return 0;
}

で、コンパイルして./a.out -a -b testとか打つと、
aはbooleanでtrueに、bにtestが帰ってくる。
おすぃまい。
--versionみたいなlongな形式にはそのうち対応する…かも。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2