Hilfe mit substr()

partitionist

Erfahrenes Mitglied
So Leute hab ein Problem, wahrscheinlich nix neues für euch ;-)
Ich will eine eingabe erstellen die befehle entgegennimmt, beim unteren Beispiel hab ich ABCD als ein Befehl genommen, dabei werden parameter angehängt: Hallo 123
Der Wert Hallo sowie 123 ist unbekannt d.h. man kann andere sachen eingeben.



Code:
 		string str = "ABCD Hallo 123";
 		
 		 if(!str.find("ABCD"))
 		{
 			  string test = str.substr(5, str.length());
 			  cout << "test: " << test << endl;   // Ausgabe: test: Hallo 123
 		  }

Also es geht nur um die variable test, den wert 123 in eine andere variable zu speichern, ich glaub man müsste dann im string nach ein leerzeichen suchen und die adresse+1 wär dann 123 oder?
 
Hi.

partitionist hat gesagt.:
Also es geht nur um die variable test, den wert 123 in eine andere variable zu speichern, ich glaub man müsste dann im string nach ein leerzeichen suchen und die adresse+1 wär dann 123 oder?
Ja, zumindest wenn da nur ein Leerzeichen zwischen den Worten ist.

Du könntest es allerdings einfacher mit einem Stringstream machen:
Code:
#include <sstream>

std::istringstream cmdline ("ABCD Hallo 123");
std::string w1, w2, w3;

cmdline >> w1 >> w2 >> w3;
Die Variablen w1, w2 und w3 enthalten dann die ersten 3 Worte der Eingabezeile.
 
Hier kurz mein code

Code:
 Eingabe...z.B. ABCD Hallo 123
 
 else if(!Input.find("ABCD"))
	    {		    		
			if(Input.length() > 5) //da 5 ein neuer parameter anfängt
			{
				string str = Input.substr(5, Input.length());
    			cout << str << endl;  // hier wird alles ab dem parameter ausgegeben bis	  zum ende von Input also "Hallo 123"

Jetzt müsste man mit str weiterarbeiten, also nach dem leezeichen suchen und dann fängt 123 an. Kannst du mir vielleicht helfen beim suchen
 
Code:
  if (!Input.find("ABCD")) {
    string str = Input.substr (5);

    int pos = str.find_first_not_of (' ', 
				     str.find (' '));

    if (pos != string::npos)
      cout << str.substr (pos) << endl;
  }

Aber was genau spricht eigentlich gegen:
Code:
if (Input.find("ABCD") == 0) {
  istringstream cmdline (Input.substr (4));
  string str;

  if (cmdline >> str >> str) 
    cout << str << endl; // str == 123
}
 
Warum nicht eine Klasse schreiben?

Code:
class Command
{
	public:
		// Konstruktor liest die Werte aus einem String ein
		Command(std::string const& str)
		{
			// Command Name
			std::string::size_type pos = str.find(' ');
			cmd = str.substr(0, pos);
			// Parameter
			while(pos != std::string::npos) {
				std::string::size_type end = str.find(' ', pos + 1);
				params.push_back(str.substr(pos+1, end-pos-1));
				pos = end;
			}
		}

		// Gibt die Daten zum Test aus
		void dump(std::ostream& out)
		{
			out << "Command: " << cmd << std::endl;
			std::list<std::string>::iterator it = params.begin();
			for(int i=0; it != params.end(); ++i, ++it) {
				out << "Parameter #" << i << ": " << *it << std::endl;
			}
			out << "End of Command";
		}

	private:
		// Speichert den Name des Befehls
		std::string cmd;
		// Speichert die Parameter
		std::list<std::string> params;

};

Gruß
 
Info zu Anfang, ich kenne mich mit Klassen nicht so gut aus. So hab die Klasse in ein Konsolen Projekt eingefügt, bekomme gleich 10 Warnungen beim Kompilieren wie z.B.

Code:
warning C4786: '?$reverse_bidirectional_iterator@Viterator@?$list@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allo
cator@D@2@@std@@@2@@std@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@AAV43@PAV43@H' : Bezeichner wurde auf '255' Zeichen in den Browser-Informationen reduziert
	    G:\vcprojects\xmd\xmd.cpp(1415) : Siehe Verweis auf Instantiierung der kompilierten Klassenvorlage 'std::list<class std::basic_string >,class std::allocator
g<char,struct std::char_traits > > >'

Jetzt weiß ich nicht wie die Klasse verwendet wird, kannste mir ein Beispiel zeigen, also mit meiner Methode kann ich jetzt die Parameter auslesen.
 
Es ist wohl besser für dich das erstmal nicht zu verwenden wenn du dich mit Klassen noch nicht auskennst. Wenn es wirklich nur die Warning C4786 ist dann macht das rein gar nichts am besten ausschalten. Die Warunung wird von der STL erzeugt.

Falls du dich doch für die Klasse intressierst: Über den Konstruktor wird das erste Wort als Member cmd gespeichert und die Parameter in der Liste params. So alleine bringt dir die Klasse noch nichts, das kommt drauf was du nun damit machen möchtest, dementsprechende lässt sich es erweitern.

Ansonsten kannst dir ja mal den Konstruktor anschauen in dem ist implementiert wie ich die Parameter und den Befehl trenn denn afaik wurde die Methode (die ich als sauber erachte) hier noch nicht erwähnt.

Gruß
 
FireFlow hat gesagt.:
Ansonsten kannst dir ja mal den Konstruktor anschauen in dem ist implementiert wie ich die Parameter und den Befehl trenn denn afaik wurde die Methode (die ich als sauber erachte) hier noch nicht erwähnt.
Wenn in der Code Warnungen vom Compiler produziert würd ich das nicht unbedingt sauber nennen ;)

Außerdem funktioniert dein Code nur wenn der Befehl auch wirklich an erster Stelle des Strings beginnt (sonst ist cmd leer) und wenn Leerzeichen nicht mehrfach hintereinander im String auftreten. Ich weiß natürlich nicht ob das je der Fall sein wird aber meistens werden Kommandos von Menschen eingegeben und da ist es besser etwas tolerant gegenüber der Eingabe zu sein.

Desweiteren könnte (theoretisch) für sehr große Strings ( Länge > 1<<31 ) der letzte Rest des Strings nicht vollständig als Parameter der Liste hinzugefügt werden - falls string::npos - length < length ist. Aber das ist wie gesagt eher theoretisch - heutzutage.

Ich favorisiere weiterhin die Stringstream Variante - vor allem weil man von Positionen im String doch eigentlich überhaupt nichts wissen will. Anfangs-Position, End-Position, Minus 1, Plus 1 und noch eins gemerkt und eins im Sinn -- das ist doch viel zu umständlich und fehleranfällig - einerseits macht man evtl. Fehler beim Schreiben des Codes oder man schießt sich dann nachher beim Schreiben der Kommandos in den Fuß weil die Methode zum Parsen einfach nicht robust genug ist.

Gruß
 
FireFlow hat gesagt.:
Habs oben erklärt. Bitte Lesen! :rolleyes:
Ja. Der Satz war nicht ernst gemeint (auch zu erkennen an dem Smiley). :)

Ich weiß das das bloß eine Warnung über Namen vom Compiler über zu lange Debug-Symbole die der Compiler allerdings selber generiert hat ist.

Gruß
 
Zurück