2016-07-05 8 views
3

実行可能ファイルの後のコマンドラインから引数を取るより大きなプログラムを作成しています。いくつかの引数は、オプションの等号の後に渡されることが期待されます。例えば、ログへの出力は、デフォルトではカンマで区切られたベクトルであるが、ユーザがコンマの代わりにピリオドまたは何か他のものに区切りを変更したい場合、彼らはと引数を与えるかもしれない:C++のargvから文字列のエスケープシーケンスを適切に処理します

./main --separator="." 

これは正常に動作しますが、ユーザが希望する場合、区切り文字は特殊文字も(例:タブ):それは動作しません

./main --separator="\t" 
./main --separator='\t' 
./main --separator=\t 

、彼らは次のいずれかの方法でエスケープシーケンスを渡すために期待するかもしれません私はそれを(タブとして\ tを解釈するため)したい代わりに、文字列をそのまま書いています(引用符をつけず、引用符をつけずに 't'を出力します)。私は二重スラッシュを使用してみましたが、私はこれを間違って接近しているかもしれないと思っていますし、適切に質問する方法もわかりません(検索しました)。私はここにダミーの例では、問題を再現しました

#include <string> 
#include <iostream> 
#include <cstdio> 

// Pull the string value after the equals sign 
std::string get_option(std::string input); 
// Verify that the input is a valid option 
bool is_valid_option(std::string input); 

int main (int argc, char** argv) 
{ 

    if (argc != 2) 
    { 
     std::cerr << "Takes exactly two arguments. You gave " << argc << "." << std::endl; 

     exit(-1); 
    } 

    // Convert from char* to string 

    std::string arg (argv[1]); 

    if (!is_valid_option(arg)) 
    { 
     std::cerr << "Argument " << arg << " is not a valid option of the form --<argument>=<option>." << std::endl; 

     exit(-2); 
    } 

    std::cout << "You entered: " << arg << std::endl; 
    std::cout << "The option you wanted to use is: " << get_option(arg) << "." << std::endl; 

    return 0; 
} 

std::string get_option(std::string input) 
{ 
    int index = input.find('='); 
    std::string opt = input.substr(index + 1); // We want everything after the '=' 
    return opt; 
} 

bool is_valid_option(std::string input) 
{ 
    int equals_index = input.find('='); 

    return (equals_index != std::string::npos && equals_index < input.length() - 1); 
} 

私はこのようにコンパイルします。以下のコマンドで

g++ -std=c++11 dummy.cpp -o dummy 

、それは次の出力を生成します。引用符なしで

./dummy --option='\t' 
You entered: --option=\t 
The option you wanted to use is: \t. 

:単一引用符で

/dummy --option="\t" 
You entered: --option=\t 
The option you wanted to use is: \t. 

./dummy --option=\t 
You entered: --option=t 
The option you wanted to use is: t. 

私の質問は次のとおりです。それことを指定する方法はあります二重引用符で

部分文字列\ tをタブ文字(または他のエスケープシーケンス)として解釈する必要があります。文字列リテラル "\ t"?私は手動でそれを解析することができますが、私は何か小さいものを見逃しているかもしれないときにホイールを再発明するのを避けようとしています。

お時間をいただきありがとうございます。これは非常にシンプルなので、私を夢中にさせてくれました。私はそれを素早く簡単に修正する方法がわかりません。

答えて

3

エスケープシーケンスは、使用しているシェルからすでに解析されており、それに応じてコマンドラインパラメータ配列argvに渡されます。

引用されたバージョンのみが、"\\t"文字列が解析され、main()に渡されたことを検出できるようになります。
ほとんどのシェルは、実際のTAB文字を空白としてスキップするだけなので、コマンドライン引数には表示されません。

しかし、これは主に、シェルがコマンドラインをどのように解釈するのか、そしてプログラムの引数には何が残っているのかという問題があります。

私の質問は:それはタブ文字(またはその他のエスケープシーケンス)などの部分文字列\ tを解釈する必要があることを指定する方法ではなく、文字列リテラルは「\ t」はありますか?私は手動でそれを解析することができますが、私は何か小さいものを見逃しているかもしれないときにホイールを再発明するのを避けようとしています。

あなたが実際にはC++コード内

"\\t" 

リテラル文字列をスキャンする必要があります。

+0

ありがとうございました。私はこれが事実であることを恐れていましたが、それが事実であることを知って、私はそれを使って作業することができます。 – LeapDayWilliam

関連する問題