2016-11-12 1 views
-1

Ich weiß, dass jeder es leid ist, gefragt zu werden, wie man Strings analysiert, aber das ist anders. Ich versuche, eine Befehlszeilenschnittstelle für ein Zeichenprogramm in C++ zu erstellen. Ich war in der Lage, Linien vorher zu analysieren, aber mein Problem ist, dass es mehrere Befehle gibt, die unterschiedliche Mengen von Parametern haben.Analysieren einer Zeile mit C++

Hier ist mein letzter Versuch, meine Befehlszeilenfunktion (die Fahne jetzt ignorieren):

//Allow user to type in commands 
void commandLine(){ 
    bool flag = true; 
    do { 
     cout << "Enter a command (format 'command x y z') : "; 
     vector<string> v; 
     string line; 
     cin.ignore() //edit: seg fault without this 
     getline(cin, line); 
     char space = ' '; 
     int p1, p2, p3, p4, p5, p6; 
     auto i = 0; 
     auto pos = line.find(space); 
     while(pos != string::npos){ 
      v.push_back(line.substr(i, pos-i)); 
      i = ++pos; 
      pos = line.find(space, pos); 
      if (pos != string::npos) 
       v.push_back(line.substr(i, line.length())); 
     } 
     if (v[0]=="size"){ 
      p1 = stoi(v[1]); 
      p2 = stoi(v[2]); 
      //call asm 
      int ret = mysetSize(p1, p2); 
      if (ret == 0){ 
       cout << "Something went wrong with the setSize command..." << endl; 
      } else { 
       cout << "Size set to " << p1 << "x" << p2 << endl; 
      } 
     }else if (v[0] == "clear"){ 
      //call asm 
      int ret = myclear(); 
      if (ret == 0){ 
       cout << "Something went wrong with the clear command..." << endl; 
      } else { 
       cout << "Screen Cleared" << endl; 
      } 

     }else if (v[0] == "setBkgndColor"){ 
      p1 = stoi(v[1]); 
      p2 = stoi(v[2]); 
      p3 = stoi(v[3]); 
      //call asm 
      int ret = mysetBkgndColor(p1, p2, p3); 
      if (ret==0){ 
       cout << "Something went wrong with the setBkgndColor command..." << endl; 
      } else { 
       cout << "Background color set to " << p1 << ", " << p2 << ", " << p3 << endl; 
      } 

     }else if (v[0] == "setDrawColor"){ 
      p1 = stoi(v[1]); 
      p2 = stoi(v[2]); 
      p3 = stoi(v[3]); 
      //call asm 
      int ret = mysetDrawColor(p1, p2, p3); 
      if (ret == 0){ 
       cout << "Something went wrong with the setDrawColor command..." << endl; 
      } else { 
       cout << "Draw color set to " << p1 << ", " << p2 << ", " << p3 << endl; 
      } 

     }else if (v[0] == "rect"){ 
      p1 = stoi(v[1]); 
      p2 = stoi(v[2]); 
      p3 = stoi(v[3]); 
      p4 = stoi(v[4]); 
      vertex a; 
      a.x = p1; 
      a.y = p2; 
      drawRect(a, p3, p4); 

     }else if (v[0] == "circle"){ 
      p1 = stoi(v[1]); 
      p2 = stoi(v[2]); 
      p3 = stoi(v[3]); 
      vertex a; 
      a.x = p1; 
      a.y = p2; 
      drawCircle(a, p3); 
     }else if (v[0] == "triangle"){ 
      p1 = stoi(v[1]); 
      p2 = stoi(v[2]); 
      p3 = stoi(v[3]); 
      p4 = stoi(v[1]); 
      p5 = stoi(v[2]); 
      p6 = stoi(v[3]); 
      vertex a, b, c; 
      a.x = p1; 
      a.y = p2; 
      b.x = p3; 
      b.y = p4; 
      c.x = p5; 
      c.y = p6; 
      drawTriangle(a, b, c); 
     } 

    } while(flag == true); 

} 

Wenn ich in einem Befehl eingeben, es friert nur mit einer leeren Zeile, die ich ctrl + c habe aus. Irgendwelche Ideen?

ANTWORT: Evan Terans Methode funktioniert für diese von diesem Link: Split a string in C++?

+1

Verwenden Lex und Yacc –

+0

Wie über eine vorhandene Bibliothek für diese Verwendung? "Nicht erfunden hier" ist ein häufiges Problem, man muss das Rad nicht neu erfinden, als schon unzählige andere Leute vor dir waren. Es gibt z.B. [Boost Programm Optionen] (http://www.boost.org/doc/libs/release/libs/program_options/) –

Antwort

3

Das Problem ist hier:

while(pos == string::npos){ 
     v.push_back(line.substr(i, pos-i)); 
     i = ++pos; 
     pos = line.find(space, pos); 
     if (pos != string::npos) 
      v.push_back(line.substr(i, line.length())); 

Wenn Sie keinen Platz finden, der zurückgegebene Wert npos ist, und Sie Schleife noch einmal. Da aber am Ende der Linie keinen Platz da ist, geht es weiter auf unbestimmte Zeit: Endlosschleife mit Speicher, da der Dokumentation zunehmenden heißt

Wenn dieser (po) größer ist als die Stringlänge, die Funktion nie findet Spiele

Also um es zusammenzufassen:

  • , wenn Sie einen einzelnen Befehl eingeben, ohne Leerzeichen, pos == string::npos geben Sie die Schleife und Sie erhalten eine Endlosschleife wie oben
  • erklärt
  • Wenn Sie einen Befehl mit Argumenten eingeben, geben Sie die Schleife nicht ein, da pos nicht string::npos ist und Ihr Vektor leer ist => segfault.

Ich empfehle schauen Sie auf bessere Möglichkeiten, um Ihre Strings wie here

Aber in der Zwischenzeit zu spalten fixiert ich Ihre Schleife und es funktioniert jetzt (und es ist auch einfacher):

auto i = line.find_first_not_of(space); 
for(;;){ 
    auto pos = line.find(space,i); 
    // store token 
    v.push_back(line.substr(i,pos-i)); 
    // no more space: bail out   
    if (pos==string::npos) 
    { 
     break; 
    } 
    // move to next non-space 
    i = line.find_first_not_of(space,pos+1); 
    // protection against trailing spaces 
    if (i==string::npos) 
    { 
     break; 
    } 
} 
  • während Condition Loops sind oft eine schlechte Idee, weil Sie die Operation einen außerhalb der Schleife und die gleiche Operation innerhalb der Schleife durchführen müssen, was verwirrend ist
  • Ich suche nur nach Raumcharakter.
  • Wenn nicht gefunden, gibt es string::npos zurück, so dass die substr die ganze Zeichenfolge extrahiert, dann stoppt die Schleife.
  • Wenn Leerzeichen gefunden wurde, wird der Index zurückgegeben, springt zum ersten Nicht-Leerzeichen und sucht nach dem nächsten Feld.
  • Wenn startet oder/und mit Leerzeichen endet, wird nicht abstürzen entweder :)
+0

Vielen Dank für Ihre Antwort. Ich habe das versucht, aber jetzt habe ich einen Segmentierungsfehler, sobald er nach einem Befehl fragt. –

+1

Sie haben keine Garantie für 'v' Größe, aber Sie greifen auf' v [0] ',' v [1] '... versuchen Sie,' v.size() 'und' v.contents() 'zu drucken –

+0

Whoops Ich habe vergessen, die While-Schleife zu bearbeiten, aber jetzt macht es immer noch dasselbe wie zuvor –

Verwandte Themen