Zahlenwerte aus einem String "filtern"
-
string text = "N142X-342765Y31357Z36970G00"; size_t x_start = text.find("X"), y_start = text.find("Y"), z_start = text.find("Z"); cout << text.substr(x_start + 1, y_start - x_start - 1);Natürlich die find-Sachen auf npos prüfen.
http://www.cppreference.com/cppstring/substr.html
http://www.cppreference.com/cppstring/find.html
-
Oder du bastelst dir eine Methode, die den String flexibel zerlegt.
Stelle ich mir ungefähr so vor:bool ExtractCoords( string text, map<char,double>& coords ) { // Zerlegt hier den String in die einzelnen Teile und schreibt // zu jedem darin vorkommenden Buchstaben den zugehörigen Zahlenwert // in die map. } ... string text = "N142X-342765Y31357Z36970G00"; map<char,double> coords; if ( ! ExtractCoords( text, coords ) ) { // Fehler } else { // coords['X'] beinhaltet die x-Koordinate usw. }
-
std::string text = "N142X-342765Y31357Z36970G00"; void extract_coords(const std::string& string, double& x, double& y, double& z) { std::size_t pos_x = string.find_first_of('X'); std::size_t pos_y = string.find_first_of('Y', pos_x); std::size_t pos_z = string.find_first_of('Z', pos_y); std::size_t pos_end = string.find_first_not_of("0123456789", pos_z); if (pos_x == std::string::npos || pos_y == std::string::npos || pos_z == std::string::npos) throw std::logical_error("Invalid string!"); std::stringstream ss(string.substr(pos_x + 1, pos_y)); ss >> x; ss.clear(); ss.str(""); ss << string.substr(pos_y + 1, pos_z); ss >> y; ss.clear(); ss.str(""); ss << string.substr(pos_z + 1, pos_end); ss >> z; }ist aber nicht die kürzeste Lösung

-
Ich bin nicht besonders gut mit der STL, aber das hier geht auch:
void ExtractCoords( string text, map<char,double>& coords ) { char last_char = '\0'; for ( size_t i=0, last=-1, len=text.length(); i<len; ++i ) { if ( isalpha( text[i] ) ) { char c = text[i]; if ( last != -1 ) { text[i] = '\0'; coords[last_char] = atof( text.c_str()+last ); } last_char = c; last = i+1; } } if ( last != -1 ) coords[last_char] = atof( text.c_str()+last ); }edit: Nur aus Interesse, wie kann man das elegant mit der STL machen

-
ok, funktioniert jetzt einigermasen, jetzt versuche ich
das alles in eine Funktion zu packen um diese dann in eine
externe Headerdatei auszulagern, aber irgendwie will´s nich so
recht funktionieren.Kann ich der Funktion ein String übergeben und als
Rückgabewert eine double erhalten ??Ich bekomme als Rückgabewerd x_koord immer "999999999999999"
so als wenn der String überhaupt nicht bearbeitet wird !!#include <cstdlib> #include <string> #include <iostream> using namespace std; double x_filter(string); int main(int argc, _TCHAR* argv[]) { string programmzeile; // Variablendeklaration double x_koord; cout << "NC-Programmzeile eingeben: "; // Textzeile einlesen: getline ( cin, programmzeile); x_koord = x_filter(programmzeile); cout.precision(3); // Genauigkeit auf 3 Stellen setzen cout << showpoint << fixed << showpos // X-Koordinate ausgeben mit 3 Nachkommastellen und << "\n\nX-Koordinate: " << x_koord << "\n\n"; // positiven Vorzeichen system("PAUSE"); return 0; } double x_filter(string) { string x_edit; double x_koord; // Programmzeile in die Variable x_edit kopieren int xanfang = x_edit.rfind("x"); // Anfang der X-Koordinate suchen und X-Buchstabe entfernen if (xanfang != std::string::npos) // Wenn kein X vorhanden ist an Verzweigungsende Springen { xanfang++; x_edit = x_edit.erase(0,xanfang); // Zeilenanfang bis X-Koordinate löschen int satzlaenge = x_edit.length()-1; // Länge der restlichen Zeile bestimmen int xende = x_edit.rfind("y"); // Anfang der Y-Koordinate suchen if (xende != std::string::npos); // Wenn kein Y vorhanden ist nach Z-Koordinate suchen else xende = x_edit.rfind("z"); if (xende != std::string::npos); // Wenn auch kein Z vorhanden ist nach G Suchen else xende = x_edit.rfind("g"); if (xende != std::string::npos); // Wenn auch kein G vorhanden ist dann Zeilenende nehmen else xende = satzlaenge+1; x_edit = x_edit.erase(xende,satzlaenge); // von Ende der X-Koordinate bis Zeilenende löschen x_koord = atof (x_edit.c_str()); // X-Koordinate von String in Double umwandeln x_koord = x_koord / 1000;} // 1000stel in ganze MM umrechnen else x_koord = 999999999999999; // Wenn kein X vorhanden ist setz den wert auf 999999999999999 return x_koord; }Was hab ich da falsch gemacht ??
Es geht mir jetzt nur um den richtigen Rückgabwert, die
Zerlegung des String´s werde ich dann noch umschreiben, entsprechend
euren vorschlägen !!
-
'x' != 'X'

if(x_edit.find('x') != string::npos || x_edit.find('X') != string::npos) { ... } else ... //9999999
-
Badestrand schrieb:
edit: Nur aus Interesse, wie kann man das elegant mit der STL machen

Vielleicht so:
void ExtractCoords( string text, map<char,double>& coords ) { char last_char = 0; string::iterator pos = text.end(), last_pos = text.end(); while ( (pos = find_if(text.begin(),text.end(),isalpha)) != text.end() ) { if( pos == text.begin() ) { last_char = *pos; last_pos = pos; *pos = 0; continue; } stringstream sstr(""); copy(last_pos+1,pos,ostream_iterator<char>(sstr)); //da es blöderweise kein string::substr für iteratorn gibt double val = 0; sstr >> val; coords[last_char] = val; last_char = *pos; last_pos = pos; *pos = 0; } }Edit: gcc aus C::B will die find_if Anweisung nicht kompilieren

-
KasF schrieb:
copy(last_pos+1,pos,ostream_iterator<char>(sstr)); //da es blöderweise kein string::substr für iteratorn gibt
Meinst Du folgendes?string newstring(last_pos + 1, pos);
-
KasF schrieb:
Edit: gcc aus C::B will die find_if Anweisung nicht kompilieren

Das liegt daran dass isalpha dort wohl ein Makro ist (und imho auch sein darf). Zusätzlich könnten Dir die Überladungen aus <locale> einen Strich durch die Rechnung machen (betrifft alle Compiler).
-
LordJaxom schrieb:
KasF schrieb:
Edit: gcc aus C::B will die find_if Anweisung nicht kompilieren

Das liegt daran dass isalpha dort wohl ein Makro ist (und imho auch sein darf).
AFAIK ist 'isalpha' sowieso nur mit 'int'-Parametern definiert, d.h. die Signatur passt hier eh nicht.
-
Konrad Rudolph schrieb:
Meinst Du folgendes?string newstring(last_pos + 1, pos);

Wollte eigentlich sstr nen substring übergeben, aber habe voll vergessen, dass man einen string auch so konstruieren kann.LordJaxom schrieb:
Das liegt daran dass isalpha dort wohl ein Makro ist (und imho auch sein darf). Zusätzlich könnten Dir die Überladungen aus <locale> einen Strich durch die Rechnung machen (betrifft alle Compiler).
Achso, danke.
bool isAlpha(char c) { return isalpha(c); } ... find_if(text.begin(),text.end(),isAlpha) ... stringstream sstr( string(last_pos + 1,pos) );
-
Du musst aber, glaube ich, noch ne Kleinigkeit ändern, 'G' wird noch nicht erfasst (bei mir jedenfalls nicht). Das Problem hatte ich auch erst :p
^Und ich hab meinen Code nochmal verändert, 'text' kann ich ja verändern wie ich will :)^
-
Badestrand schrieb:
Du musst aber, glaube ich, noch ne Kleinigkeit ändern, 'G' wird noch nicht erfasst (bei mir jedenfalls nicht). Das Problem hatte ich auch erst :p
bool isAlpha(char c) { return isalpha(c); } void ExtractCoords( string text, map<char,double>& coords ) { char last_char = 0; string::iterator pos = text.end(), last_pos = text.end(); while ( (pos = find_if(text.begin(),text.end(),isAlpha)) != text.end() ) { if( pos == text.begin() ) { last_char = *pos; last_pos = pos; *pos = 0; continue; } stringstream sstr( string(last_pos + 1,pos) ); double val = 0; sstr >> val; coords[last_char] = val; last_char = *pos; last_pos = pos; *pos = 0; } stringstream sstr( string(last_pos+1,text.end()) ); double val = 0; sstr >> val; coords[last_char] = val; }
Das kann man aber bestimmt noch eleganter lösen, vielleicht zaubert ja Konrad ne rekursive Lösung ...
-
Und nochmal was gefrickelt:
bool isAlpha(char c) { return isalpha(c); } template<class T, class S> T lexical_cast(const S& val) { stringstream sstr(""); T newval; if( !( sstr << val && sstr >> newval ) ) throw bad_cast(); return newval; } void ExtractCoords( string text, map<char,double>& coords ) { typedef string::iterator sIT; struct helpFunc { void operator()(char& last_char, sIT& pos, sIT& last_pos) { last_char = *pos; last_pos = pos; *pos = 0; } }; char last_char = 0; sIT pos = text.end(), last_pos = text.end(); while ( (pos = find_if(text.begin(),text.end(),isAlpha)) != text.end() ) { if( pos == text.begin() ) { helpFunc()(last_char,pos,last_pos); continue; } coords[last_char] = lexical_cast<double>( string(last_pos + 1,pos) ); helpFunc()(last_char,pos,last_pos); } coords[last_char] = coords[last_char] = lexical_cast<double>( string(last_pos+1,text.end()) ); }
-
hehe :p:
void ExtractCoords( string text, map<char,double>& coords ) { for ( int i=text.length()-1; i>=0; --i ) { if ( isalpha( text[i] ) ) { coords[ text[i] ] = atof( text.c_str()+i+1 ); text[i] = '\0'; } } }
-
Noch ein Nachtschwärmer

Elegante Idee von Rückwärts durchzulaufen. Wenn die Sonne aufgeht, schreibe ich meins um ...
-
geSTL'te Version:
void ExtractCoords( string text, map<char,double>& coords ) { string::reverse_iterator pos = text.rend(); while ( ( pos = find_if(text.rbegin(), text.rend(), isAlpha) ) != text.rend() ) { size_t dis = distance(pos,text.rend()); coords[*pos] = lexical_cast<double>( text.substr(dis) ); text.erase(dis-1); } }