Zahlenwerte aus einem String "filtern"
-
@Checker&Murckser
Danke erstmal, soweit fuktioniert alles :p
@KasF
Hast recht, ich muss das ganze dann noch für Y und Z auch noch hintendran hängen !!
Eventuell auch noch für die Drehachsen A, B und C und dann noch GBin wie gesagt noch Anfänger, und weis auch noch nicht welche möglichkeiten
mir da offen stehn !!find und substr kenn ich jetzt noch nicht

Kannst du mal ne ganz einfache Zeile Posten, die ich als Vorlage benutzen kann !!Muss gleich mal in meiner C++ Referenz nachschauen !!
-
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); } }