Komma wird zu Punkt - aber wie wieder rückgängig?
-
Hallo,
ich versuche damit
for(string::iterator itStr = strLine.begin(); itStr != strLine.end(); itStr++) if((*itStr) == ',') (*itStr = '.');
die Kommas für die Berechnung durch Punkte zu ersetzen. Nun brauche ich sie aber wieder als Kommas am Ende bevor ich das ganze ich die Ausgabdatei packe. Wie bewerkstellige ich das? Bin ratlos!
Vielen Dank für eure Hilfe im voraus.
-
Ich verstehe das Problem nicht. Du kannst ein Komma durch einen Punkt ersetzen, aber nicht umgekehrt
Wie wäre es, wenn Du einfach die Zeichen in der Schleife vertauschst?Übrigens geht es kürzer so:
std::replace(strLine.begin(), strLine.end(), ',', '.');
Der umgekehrte Weg ist gar nicht schwieriger.
-
TechM schrieb:
ich versuche ... die Kommas für die Berechnung durch Punkte zu ersetzen. Nun brauche ich sie aber wieder als Kommas am Ende bevor ich das ganze ich die Ausgabdatei packe.
Also Zahlen aus der Datei mit Kommas lesen und mit Komma statt Punkt wieder zurückschreiben.
Das geht viel einfacher. Teile dem Stream aus dem Du liest doch einfach mit, dass Du 'deutsch' mit ihm reden willst. Im Deutschen ist das ',' der Dezimaltrenner. Etwa so
#include <iostream> #include <fstream> #include <locale> int main () { using namespace std; ifstream in("Datei.txt"); in.imbue( locale( "german" ) ); // wir reden deutsch double z1, z2; in >> z1 >> z2; // z.B. 2 Zahlen lesen cout << "Gelesen: " << z1 << " " << z2 << endl; ofstream out("Datei2.txt"); out.imbue( locale( "german" ) ); // scheiben auch in deutsch out << z1 << " " << z2 << endl; return 0; }
Bem.: der String 'german' kann evt. auch anders heißen. Obiges funktioniert unter Windows.
Gruß
Werner
-
Da ist wohl jemandem langweilig -_-"
-
Hallo,
also erstmal vielen Dank für eure Hilfe!
das mit den locales wollte ich umgehen aber wie ich sehe wird es mit denen wohl um einiges einfacher sein.
Hier mal der gesamte Quelltest da ich auf ein neues Problem gestoßen bin durch eben diese Änderung.
#include <fstream> #include <iostream> #include <string> #include <sstream> #include <cmath> #include <locale> using namespace std; int main(int argc, char* argv[]) { string strFileIn, strFileOut; string strLine, strTest; double d1, d2, d3, d4, d5, d6, dOut, dQuo, c0 = 11926.309; char t1[30], t2[30]; int iLineCount = 0, iBlockCount = 0, iArt; bool ist = false; long int lx, lstep = 1, ls = 0, lq = 100000000; cout << "\t\t\t********** XXX v1.1 **********" << endl << endl; //argumente prüfen if (argc < 3) { //keine oder zuwenig Parameter angegeben -> nach den Dateinamen fragen cout << "Eingabedatei angeben: "; cin >> strFileIn; cout << endl; cout << "Ausgabedatei angeben: "; cin >> strFileOut; cout << endl; } else { //Dateinamen aus Parameter-Array übernehmen strFileIn = argv[1]; strFileOut = argv[2]; } //Wahl der Auswertungsart cout << "Fuer logarithmische Auswertung waehlen Sie bitte die '1'" << endl; cout << "Fuer lineare Auswertung waehlen Sie bitte die '2'" << endl; cout << "--> "; cin >> iArt; cout << endl; if (iArt == 2) { //a einlesen cout << "Beginn der Auswertung bei Lastwechsel ('0' eingeben fuer komplette Auswertung)" << endl; cout << "--> "; cin >> ls; cout << endl; //Ist ds ungleich '0' wird b eingelesen, ansonsten gilt der bei der Deklartion festgelegte Wert if (ls != 0) { cout << "Ende der Auswertung bei Lastwechsel:" << endl; cout << "--> "; cin >> lq; cout << endl; } //Schrittweite einlesen cout << "Bitte Schrittweite eingeben:" << endl; cout << "--> "; cin >> lstep; cout << endl; } //Dateien öffnen ifstream in(strFileIn.c_str()); in.imbue( locale( "german" ) ); // wir reden deutsch if(!in) return -2; ofstream out(strFileOut.c_str()); out.imbue( locale( "german" ) ); // scheiben auch in deutsch if(!out) return -3; //Datei lesen do { //Zeile einlesen getline(in, strLine); //alles OK? if(in) { //alles OK, kein Fehler aufgetreten und Datei noch nicht zu Ende //string in stringstream kopieren stringstream in(strLine); in >> strTest; //Wenn das 1. Wort 'Zyklische' ist, Zeilenzähler zurücksetzen und Blockzähler erhöhen if(strTest == "Zyklische") { iLineCount = 0; iBlockCount++; } if (iBlockCount == 1 && iLineCount == 1) { out << "Anzahl der Lastwechsel" << ";" << "c [N/mm]" << ";" << "c/c0" << endl; } //Zeile zählen iLineCount++; //Wenn Zeile leer ist, nichts machen if(strLine.empty()) continue; if(iLineCount == 2 && iBlockCount > 0) { //für 2. Zeile //string in stringstream kopieren stringstream in(strLine); //Zeichenketten aus stringstream auslesen in >> t1 >> t2 >> lx; } if (iArt == 1) { if (lx > 0 && lx < 1000) lstep = 100; if (lx > 1000 && lx < 10000) lstep = 1000; if (lx > 10000 && lx < 100000) lstep = 10000; if (lx > 100000 && lx < 1000000) lstep = 100000; if (lx > 1000000 && lx < 10000000) lstep = 1000000; } if (lx % lstep == 0) ist = true; else ist = false; if (lx > (ls - 1) && lx < (lq + 1) && ist == true) { if(iLineCount == 6 && iBlockCount > 0) { //für 6. Zeile //string in stringstream kopieren stringstream in(strLine); //Zahlen aus stringstream auslesen in >> d1 >> d2 >> d3; } if(iLineCount == 7 && iBlockCount > 0) { //ab 7. Zeile //string in stringstream kopieren stringstream in(strLine); //Zahlen aus stringstream auslesen in >> d4 >> d5 >> d6; //Berechnung durchführen dOut = ((d6 + fabs(d3)) / (fabs(d2) + d5)); dQuo = (dOut / c0); //Genauigkeit der Ausgabe setzen out.precision(10); //Ergebnis ausgeben out << lx << ";" << dOut << ";" << dQuo << endl; } } } //bis Dateiende oder Fehler }while(in); return 0; }
Ich versuche folgende Text-datei mit diesem programm zu bearbeiten und in eine .csv-datei zu schreiben.
Hier ein Auschnitt:
es handelt sich hier um die 6. und 7. Zeile.
6. Zeile: d1 d2 d3
7. Zeile: d4 d5 d610,550537 -0,093262166 -2803,3469
10,588135 0,11793396 -284,5567wenn ich die nun einlesen kommen totaler Quatsch raus! Hab ich irgendwo einen Fehler?
Ohne der Umstellung auf "german" lacale funktionierte es wunderbar!
Kann mir jemand helfen?
Danke im voraus!
TechM
-
Hallo TechM,
das Problem ist offensichtlich; weil die locale("german") gar nicht zum Lesen der Fließkommazahlen genutzt wird! In Zeile 73 setzt Du die locale("german") bei dem File. Aus diesem liest Du aber keine Zahlen sondern den Text in Zeile 84. Den Text steckst Du in einen stringstream (Zeile 145 und 154) und aus diesen liest Du dann die Fließkommazahlen aus. Der stringstream weiß nix von 'german' und versucht die Zahlen mit der Standard-Facette std::num_get zu lesen; und diese erwartet einen '.' als Dezimaltrenner.
Kopiere die Zeile 73 hinter die Zeilen 145 und 154. Dann sollte es gehen.
Es wäre außerdem hilfreich, direkt das einzulesen, was Du lesen willst und und die Schleife nur über die Blöcke laufen lässt. Das vereinfacht alles. Ich habe mir das etwa so vorgestellt.
#include <fstream> #include <iostream> #include <string> #include <sstream> #include <cmath> #include <locale> using namespace std; int getStep( int lx ) { int lstep = 1; if (lx > 0 && lx < 1000) lstep = 100; if (lx > 1000 && lx < 10000) // was, wenn lx == 1000 ? lstep = 1000; if (lx > 10000 && lx < 100000) lstep = 10000; if (lx > 100000 && lx < 1000000) lstep = 100000; if (lx > 1000000 && lx < 10000000) lstep = 1000000; return lstep; } int main(int argc, char* argv[]) { string strFileIn, strFileOut; double c0 = 11926.309; int iArt; long lx = 1000000, lstep = 1, ls = 0, lq = 100000000; cout << "\t\t\t********** XXX v1.1 **********" << endl << endl; //argumente prüfen if (argc < 3) { //keine oder zuwenig Parameter angegeben -> nach den Dateinamen fragen cout << "Eingabedatei angeben: "; cin >> strFileIn; cout << endl; cout << "Ausgabedatei angeben: "; cin >> strFileOut; cout << endl; } else { //Dateinamen aus Parameter-Array übernehmen strFileIn = argv[1]; strFileOut = argv[2]; } //Wahl der Auswertungsart cout << "Fuer logarithmische Auswertung waehlen Sie bitte die '1'" << endl; cout << "Fuer lineare Auswertung waehlen Sie bitte die '2'" << endl; cout << "--> "; cin >> iArt; cout << endl; if (iArt == 2) { //a einlesen cout << "Beginn der Auswertung bei Lastwechsel ('0' eingeben fuer komplette Auswertung)" << endl; cout << "--> "; cin >> ls; cout << endl; //Ist ds ungleich '0' wird b eingelesen, ansonsten gilt der bei der Deklartion festgelegte Wert if (ls != 0) { cout << "Ende der Auswertung bei Lastwechsel:" << endl; cout << "--> "; cin >> lq; cout << endl; } //Schrittweite einlesen cout << "Bitte Schrittweite eingeben:" << endl; cout << "--> "; cin >> lstep; cout << endl; } //Dateien öffnen ifstream in(strFileIn.c_str()); in.imbue( locale( "german" ) ); // wir reden deutsch if(!in) return -2; ofstream out(strFileOut.c_str()); out.imbue( locale( "german" ) ); // scheiben auch in deutsch if(!out) return -3; out << "Anzahl der Lastwechsel" << ";" << "c [N/mm]" << ";" << "c/c0" << endl; for( string text1; in >> text1; ) { in.ignore( 999, '\n' ); // 1.Zeile Rest lesen if( text1 != "Zyklische" ) continue; // -- Block lesen string dummy; in >> dummy >> dummy >> lx; in.ignore( 999, '\n' ); // 2.Zeile Rest lesen if( iArt == 1 ) lstep = getStep( lx ); if (lx >= ls && lx <= lq && (lx % lstep == 0) ) { for( int zeilen = 3; zeilen; --zeilen ) in.ignore( 999, '\n' ); // 3.-5. Zeile double dummy, d2, d3, d5, d6; in >> dummy >> d2 >> d3; in.ignore( 999, '\n' ); // 6.Zeile (ignore evt. weglassen) in >> dummy >> d5 >> d6; // 7.Zeile // -- Ergebnis ausgeben double dOut = ((d6 + fabs(d3)) / (fabs(d2) + d5)); double dQuo = (dOut / c0); //Genauigkeit der Ausgabe setzen out.precision(10); //Ergebnis ausgeben out << lx << ";" << dOut << ";" << dQuo << endl; } } return 0; }
Das ignore für die 6.Zeile hinter 'Zyklische' brauchst Du auch nur dann, wenn hinter den Zahlen noch was steht. Sonst könntest Du diese auch mit
in >> dummy >> d2 >> d3 >> dummy >> d5 >> d6;
einlesen. Der Zeilenumbruch stört nicht weiter.
Gruß
Werner
-
Hallo,
also erstmal vielen vielen Dank für die Hilfe!
Ich hatte es zwar in den Griff bekommen (wenn auch sehr tölpelhaft) aber deine Version ist um einiges besser.
Es läuft jetzt auch schneller. Hatte nämlich bei manchen Datensätzen (so um die 16MB)schon mal 30 Sekunden gedauert. Jetzt ist es in 10 Sekunden durch.
Viele Grüße
TechM