2016-08-06 29 views
0

Ich bin ziemlich neu in C++ 11 und ich es nicht wirklich bekommen, wie die Befehlszeilenargumente in den argv-Zeiger analysiert werden ...C++ 11 Kommandozeilenparameter Trennung

Ich habe diesen Code :

int main(int argc, char* argv[]) 
{ 
    std::string curr_arg = ""; 

    std::string str_base = ""; 
    std::string str_subs_file = ""; 
    std::string str_subs = ""; 

    for(int i = 1; i < argc; i++) 
    { 
     curr_arg = argv[i]; 

     if(curr_arg == "-b" || curr_arg == "--base") 
     { 
      str_base = argv[++i]; 
     } 
     else if(curr_arg == "-f" || curr_arg == "--file") 
     { 
      str_subs_file = argv[++i]; 
     } 
     else if(curr_arg == "-s" || curr_arg == "--subs") 
     { 
      str_subs = argv[++i]; 
     } 
     else 
     { 
      std::cout << "Argument '" << argv[i] << "' is not recognised." << std::endl; 
      return -1; 
     } 
    } 
} 

Wenn ich mein Programm mit ./subs -b Basis -sa = 1,2,3 nennen; b = 4,5,6; c = 6,7,8 würde ich erwarten, dass ich "a = 1,2,3; b = 4,5,6; c = 6,7,8" als Argument, wenn ich in den if(curr_arg == "-s" || curr_arg == "--subs" Block statt gebe ich nur "a = 1,2,3" und nichts mehr . Ich weiß, es funktioniert, wenn ich Zitate um das ganze Argument verwende, aber ich verstehe nicht, warum es so passiert .. Gibt es jemanden, der es mir erklären kann?

+3

';' ist ein Befehlseparator in den meisten Shells. Das hat nichts mit C oder C++ zu tun. – Mat

+0

als beiseite: Wollen Sie wirklich Ihren eigenen CLI-Parser schreiben? Warum nicht ein existierendes verwenden ('boost :: program_options', ...)? –

+0

Oh okay, danke für die schnelle Antwort! Ich dachte nur, weil es nichts wirklich schwierig ist, es wäre ein Overkill –

Antwort

3

Sie haben kein Problem mit C++, sondern mit Ihrer Befehlsshell. Das liegt höchstwahrscheinlich daran, dass Ihre Shell das Semikolon als Befehlsseparator verwendet.

Ihre Shell interpretiert Ihr Befehl als ./subs -b base -s a=1,2,3, dann ist es das Semikolon erkennt und interpretiert den nächsten Befehl, der b=4,5,6 in Ihrem Fall und das gleiche mit c=6,7,8 ist.

Es ist so ziemlich das gleiche wie die Eingabe (die auf den meisten Unix-Shells funktionieren sollte):

echo abc; sleep 5; echo def 5 seconds later 

Diese Drucke „abc“, schläft danach für 5 Sekunden und druckt „def 5 Sekunden später“.

Lösung: zu bekommen, was Sie wollen, können Sie das Teil a=1,2,3;b=4,5,6;c=6,7,8 mit Anführungszeichen wie kapseln könnte:

./subs -b base -s "a=1,2,3;b=4,5,6;c=6,7,8" 

oder man könnte das Semikolon wie entkommen:

./subs -b base -s a=1,2,3\;b=4,5,6\;c=6,7,8 

Beide Versionen sollte mit den meisten (wenn nicht allen) Unix-Shells und auch in den Windows cmd arbeiten, denke ich.

+0

Oh, ich habe überhaupt nicht darüber nachgedacht ... Danke für Ihre Antwort! Dann mache ich es entweder wie du es erwähnst oder ein anderes Trennzeichen verwenden musst ... –