float Zahlen aus einer txt auslesen und in array speichern
-
Es ist eig. nur ein Stoffname da, also nur eine Zeichenkett, hab das soweit umgeändert.
Joa dann musst nur eine Zeichenkette einlesen.
Was bedeutet den das vector<double> values
Das ist ein dynamisches Array. D.h. die Größe des Arrays kann zur Laufzeit beliebig sein. Du hast ein statisches Array benutzt. Wenn es zu einem Stoff mal mehr als 30 Werte gibt, hast du ein Problem. Bei dynamischen Arrays hast du kein Problem.
string::npos
Das bedeutet "nicht gefunden".
values.push_back(d)
Das bedeutet, dass du eine Kopie der Variable d im Array values ablegst.
und was genau nochmal das file.clear() ?
Ein Stream-Objekt kann verschiedene Zustände annehmen: good, bad, fail, eof. Wenn das Stream-Objekt nicht im Zustand good ist, kannst du damit keine Streamoperationen durchführen. clear() versetzt das Stream-Objekt wieder in den Zustand good. Wie gesagt, es irgendwann wird versucht, eine Zeichenkette in einem double zu speichern. Das geht nicht und die Operation schlägt fehl und das Stream-Objekt geht in den Zustand fail über.
Sowie ich das verstanden habe werden ja die Werte in d eingespeichert ?
Ja, alle Werte werden in einer Variable double d gespeichert. Damit du die Werte nach der for-Schleife aber noch hast, musst du sie natürlich in ein Array kopieren.
und ich hab da jetzt versucht sie in der Schleife einzuspeichern, aber i.wie speichert der alle Werte die in der txt.Datei vorhanden sind...
Dein
alpha[i] = d; ++i;
steht nich innerhalb der if.ich glaube, das file.clear(); müsste in der 2. for Schleife stehen oder ?
Ne. Der Fehlerzustand tritt ja bei einem Lesevorgang auf. Ein erfolgreicher Lesevorgang ist Bedingung für einen Schleifendurchlauf. Würde es in der for-Schleife stehen, würde der Fehlerzustand nicht beseitigt werden.
-
ArtiTT schrieb:
Hallo Leute,
ich habe mich heute angemeldet weil ich gedacht hab etwas Hilfe von eurer Seite zu bekommen,
Hallo ArtiTT,
Willkommen im C++-Forum.
ArtiTT schrieb:
Ich hab da noch ein paar fragen, weil ich teilweise nicht weiß was die Befehle die da drinnen sind machen.
out hat Dir ja schon gut geholfen. Du kannst die einzelnen Methoden und Klassen des C++-Standards auch hier nachlesen. (vector, push_back, string::npos)
Ansonsten ist ein gutes C++-Buch für Einsteiger zu empfehlen. Falls Du noch keins hast, so erkundige Dich vorher über die Qualität einzelner Bücher - am besten hier im Forum.ArtiTT schrieb:
Es ist eig. nur ein Stoffname da, also nur eine Zeichenkett, hab das soweit umgeändert.
Bei solchen Einlese-Problemen bitter immer eine Kopie eines Ausschnitts aus der Datei posten. Dann kann man Dir am besten helfen.
Gruß
Werner
-
Hey Out, danke nochmal, jetzt ergibt alles ein Sinn, eine Frage bleibt mir dennoch
Und zwar, du hast ja gemeint, dass:
vector<double> values
ein dynamisches Array ist, heißt das das die Werte von
double d
hier abgelegt werden ? Und wenn ja wie kann ich diese dann wieder aufrufen ?
Lg
-
Ah okay, hab es verstanden
großes Dankeschön
-
ArtiTT schrieb:
vector<double> values
ein dynamisches Array ist, heißt das das die Werte von
double d
hier abgelegt werden ?
Richtig.
ArtiTT schrieb:
Und wenn ja wie kann ich diese dann wieder aufrufen ?
Ganz normal:
cout << values[0];
-
Hey und zwar ich hab den Aufruf mit meiner richtigen txt. Datei probiert, leider klappt es da nicht, da teilweiße die Strings übereinstimmen,
d.h. ich suche z.B. die Verbindung "abcde", es gibt aber auch eine Verbindung die mit der anderen im Sring übereinstimmt, also z.B. "abc". Aber ich brauche z.B. nur die Verbindung "abcde" und nicht beide, wie kann ich da unterscheiden?@ out: ich könnte dir auch die txt. Datei mal schicken i.wie da kannst das mal selber schauen wie das aufgebaut ist, weil ich glaub so ohne zu wissen wie die ganau ausschaut es schwer vorstellbar ist
Noch eine andere Frage zu diesem Forum
wie füge ich den solche Programmcodestücke ein so wie du die immer machst ?
lg
P.S. Dankeschön schon mal
-
ArtiTT schrieb:
@ out: ich könnte dir auch die txt. Datei mal schicken i.wie da kannst das mal selber schauen wie das aufgebaut ist, weil ich glaub so ohne zu wissen wie die ganau ausschaut es schwer vorstellbar ist
Du kannst den Inhalt auch einfach mit copy&paste hier posten.
ArtiTT schrieb:
Noch eine andere Frage zu diesem Forum
wie füge ich den solche Programmcodestücke ein so wie du die immer machst ?
Also ich klicke 2x auf den "C++"-Button und füge mein innerhalb der beiden Tags ein.
-
so schaut das aus, nur mit mehr Stoffen, und eig brauche ich immer nur die 2 und die 3 Zeile vom bestimmten Stoff, je nach Bedingungen welche gegeben sind, muss ich dann halt mit der 2. Zeile oder der 3. rechnen.
SN 121286S 1N 1 G 0300.00 5000.00 1000.00 1 3.88828659E+00 6.77842705E-04-2.72530883E-07 5.13592745E-11-3.59383628E-15 2 3.04449609E+04 4.19429112E+00 3.40734577E+00 1.79788738E-03-2.01896978E-06 3 2.10785744E-09-9.52759247E-13 3.06237324E+04 6.82148123E+00 4 SO 121286S 1O 1 G 0300.00 5000.00 1000.00 1 4.02107763E+00 2.58485612E-04 8.94814178E-08-3.58014451E-11 3.22842987E-15 2 -7.11962036E+02 3.45252252E+00 3.08040142E+00 1.80310570E-03 6.70502232E-07 3 -2.06900541E-09 8.51465708E-13-3.98616303E+02 8.58102799E+00 4 SO2 121286S 1O 2 G 0300.00 5000.00 1000.00 1 5.25449848E+00 1.97854545E-03-8.20422599E-07 1.57638291E-10-1.12045120E-14 2 -3.75688555E+04-1.14605629E+00 2.91143870E+00 8.10302235E-03-6.90671004E-06 3 3.32901551E-09-8.77712128E-13-3.68788164E+04 1.11174030E+01 4 SO3 121286S 1O 3 G 0300.00 5000.00 1000.00 1 7.05066824E+00 3.24656023E-03-1.40889733E-06 2.72153494E-10-1.94236479E-14 2 -5.02066758E+04-1.10644264E+01 2.57528257E+00 1.51509158E-02-1.22987167E-05 3 4.24025703E-09-5.26681184E-13-4.89441055E+04 1.21951160E+01 4
und wenn ich jetzt z.B. SO brauche, und nach SO suche, dann greift er auch auf SO2 und auf SO3, bitte um Hilfe
-
ArtiTT schrieb:
und wenn ich jetzt z.B. SO brauche, und nach SO suche, dann greift er auch auf SO2 und auf SO3, bitte um Hilfe
Hallo ArtiII,
Da kommt noch hinzu, dass hinter der Materialbezeichnung Dinge stehen, Du Du anscheinend nicht benötigst. Ändere das Programm von out wie folgt:
#include <iostream> #include <fstream> #include <string> #include <vector> #include <limits> // std::numeric_limits< std::streamsize > int main() { std::string search; std::cout << "Search: "; std::cin >> search; std::ifstream file("C:\\Users\\...\\Desktop\\master.txt"); // <== Filename eintragen std::vector<double> values; for( std::string material; file >> material; ) // lese Wort für Wort { if( material == search ) // prüfe, ob das gelesene Wort 'material' mit 'search' über ein stimmt break; // gesuchtes Material gefunden; dann Suche abbrechen } file.ignore( std::numeric_limits< std::streamsize >::max(), '\n' ); // Rest der Zeile überlesen for(double d; file>>d;) // Werte einlesen; bis eine Fehler auftritt { values.push_back(d); // Werte in 'values' ablegen } std::cout << values.size() << " Werte gelesen" << std::endl; }
Das 'numeric_limits< std::streamsize >::max()' in Zeile 21 steht hier für 'beliebig viele' - also heißt
file.ignore( std::numeric_limits< std::streamsize >::max(), '\n' );
(über-)lese beliebig viele Zeichen bis Du ein '\n' (Zeilenende) gefunden wird.
Da sollten immer 17 Werte gelesen werden. Ich unterstelle jedoch, dass Du die zahlen am Ende der Zeilen nicht benötigst - oder? Dieses stehen auch im vector 'values'.
Gruß
Werner
-
Hallo,
ich stelle mir bezüglich dieses Threads 3 weitere Fragen:
1.
Ich besitze Messwerte, die ich mit dem Programm MATLAB aufnehmen werden. MIr ist noch nicht bekannt, wieviele das ingesamt werden. Die Messwerte werden in einer Matrix angelegt. Die Spaltenanzahl richtet sich nach einer Abtastrate und ist variabel.
Die Zeilenanzahl richtet sich nach den Messzeiten und ist vom Benutzer einstellbar.
Aufbauend auf:
#include <iostream> #include <fstream> #include <string> #include <vector> #include <limits> // std::numeric_limits< std::streamsize > int main() { std::string search; std::cout << "Search: "; std::cin >> search; std::ifstream file("C:\\Users\\...\\Desktop\\master.txt"); // <== Filename eintragen std::vector<double> values; for( std::string material; file >> material; ) // lese Wort für Wort { if( material == search ) // prüfe, ob das gelesene Wort 'material' mit 'search' über ein stimmt break; // gesuchtes Material gefunden; dann Suche abbrechen } file.ignore( std::numeric_limits< std::streamsize >::max(), '\n' ); // Rest der Zeile überlesen for(double d; file>>d;) // Werte einlesen; bis eine Fehler auftritt { values.push_back(d); // Werte in 'values' ablegen } std::cout << values.size() << " Werte gelesen" << std::endl; }
würde ich den code gerne verändern:
#include <iostream> #include <fstream> #include <string> #include <vector> #include <limits> // std::numeric_limits< std::streamsize > int main() { std::string verzeichnis; std::cout << "Dateiverzeichnis: "; std::cin >> verzeichnis; std::ifstream file(verzeichnis); // <== Filename eintragen // Hierzu haette ich noch eine Frage std::vector<double> values; for(double d; file>>d;) // Werte einlesen; bis eine Fehler auftritt { values.push_back(d); // Werte in 'values' ablegen /* Hier wuerde ich gerne einen inkrementierenden integer haben, der bei jedem eingelesenen Wert auslöst. Sobald ein Zeilenumbruch '\n' erreicht wird, soll der integer nicht mehr weiterzaehlen. Im Gegenzug soll ebenfalls die Anzahl der Zeilenumbrüche mitgezählt werden. */ } // std::cout << values.size() << " Werte gelesen" << std::endl; }
Mit der Anzahl von Spalten und Zeilen kann ich nachher eigenständig den Vektor values in ein dynamisches zweidimensionales Array umschreiben. Das ist zwar in Workaround, macht aber für mich erstmal keine Probleme.
Kann mir irgendeiner zu meinem Kommentator im Quellcode einen Implementierungstipp bitte geben?
2.
Ein Ausschnitt aus dem oben komplett gezeigten Quellcode:
std::string verzeichnis; std::cout << "Dateiverzeichnis: "; std::cin >> verzeichnis; std::ifstream file(verzeichnis); // <== Filename eintragen // Hierzu haette ich noch eine Frage std::vector<double> values;
Muss ich bei dem string verzeichnis die \ schon als '\' eingeben?
Wenn ja (was ich auch denke), gibt es bei der string-klasse eine Funktion, die einen einzelnen char aufspürt und ihn austauscht?Ich würde dann gerne als Pseudocode:
Durchsuche verzeichnis nach char \ Wenn \ gefunden, dann ersetze mit '\\' Wenn verzeichnis durchlaufen ist, return
3.
Das hat eigentlich nichts mit Zahlen zu tun. Allerdings würde ich, weil ich den Quellcode aus diesem Thread stammt, meine Frage kurz stellen.
Ich möchte ein Startskript schreiben:
Startanzahl: 1100 Endzahl: 1200 Speicherort: c:\\bla bla\\ modus: nichts
Hierzu eignet sich meiner Meinung nach die Suche aus dem obigen Quellcode.
#include <iostream> #include <fstream> #include <string> #include <vector> #include <limits> // std::numeric_limits< std::streamsize > int main() { std::vector<std::string> values; // konfigurierbare Menupuenkte im Skript values.push_back("Startanzahl:"); values.push_back("Endanzahl:"); values.push_back("Speicherort:"); values.push_back("modus:"); std::vector<std::string> option; // gewahlte Menupuenkte std::ifstream file("C:\\Users\\...\\Desktop\\master.txt"); // <== Filename eintragen for(int k = 0; k <= values.size(); k++){ for( std::string material; file >> material; ) // lese Wort für Wort { if( material == values[k] ) // prüfe, ob das gelesene Wort 'material' mit 'values[k]' über ein stimmt break; // gesuchtes Material gefunden; dann Suche abbrechen } // Hier weiss ich nicht mehr eigenständig weiter. Siehe unten im Thread } } }
Wenn ich einen Menuepunkt gefunden habe, möchte ich die gewählte Option einlesen.
Ich würde gerne nicht so penibel drauf achten, wieviele Leerzeichen zwischen dem ':' und dem ersten char sind. Also bräuchte ich einen Funktion, die erst ein Wort einliest, wenn es kein ' ' ist. Am Besten wäre auch eine Implemtierung, in der ich auch einen konfigurierbare Menupuenkte im Skript nicht mit einem ':' beenden muss, sondern auch hier Leerzeichen einfügen kann.
Beispiel:Startanzahl : 1100 Endzahl : 1200
Die gewählte Option sollte mit einem Zeilenumbruch aufhören (siehe Beispielsskript oben).
Mögliche Zahlen würde ich später via stoi o.Ä. casten.
Weiß einer, wie ich das implementiere?
Danke & cu
John
-
Hallo John,
zu 1.)
#include "is_endl.h" // s. http://www.c-plusplus.net/forum/p1940874#1940874 #include <iostream> #include <fstream> #include <string> #include <vector> #include <limits> // std::numeric_limits< std::streamsize > int main() { std::string verzeichnis; std::cout << "Dateiverzeichnis: "; std::cin >> verzeichnis; std::ifstream file(verzeichnis); // <== Filename eintragen std::vector< std::vector< double > > values; // alle Werte quasi 2-dimensional for( int idxZeile = 0; file; ++idxZeile ) { // -- eine Zeile lesen std::vector<double> werte_einer_zeile; // Hier wuerde ich gerne einen inkrementierenden integer haben, der bei jedem eingelesenen Wert auslöst. int inkrementierender_Integer = 0; for( double d; !is_endl( file ) && file >> d; ++inkrementierender_Integer ) werte_einer_zeile.push_back(d); // Werte in 'values' ablegen values.push_back( werte_einer_zeile ); // Werte aus einer Zeile merken // Im Gegenzug soll ebenfalls die Anzahl der Zeilenumbrüche mitgezählt werden. // --> s. idxZeile } }
Das Erkennen eines Zeilenendes ist nicht so einfach, weil es genau wie Space zu den white-space-charactern gehört und somit normalerweise schlicht überlesen wird. Aber da das immer wieder gefragt wird, habe ich mal ein
is_endl
gebastelt - siehe Link im Code oben.
wobei noch zu bemerken ist, dass Du jeden Vektor nach der Anzahl seiner Werte fragen kannst (vector::size()).Zu 2.)
Johnny_walk schrieb:
Muss ich bei dem string verzeichnis die \ schon als '\' eingeben?
Wenn ja (was ich auch denke), gibt es bei der string-klasse eine Funktion, die einen einzelnen char aufspürt und ihn austauscht?Ja- Du musst das mit angeben. Ja - es gibt eine Methode; besser zwei Methoden string::find() und string::replace().
Und - Nein - das kannst Du hier nicht machen, da das '\' nur in dem Literal notwendig ist und gar nicht im string ankommt. Das '\' ist ein sogenanntes Fluchtsymbol, was dem Compiler angibt, dass da jetzt was kommt, was man normalerweise nicht in den Text schreiben kann.
Z.B. wird "C:\normal\tag\\egal" 'übersetzt' mit "C:" + <LF> + "ormal" + <Tab> + "ag\egal". <LF> ist Code 10 und <Tab> ist Code 9
Wenn Deine Umgebung das '/' auch als Directorie-Trenner akzeptiert, so benutze besser dies.Zu 3.)
Johnny_walk schrieb:
Ich würde gerne nicht so penibel drauf achten, wieviele Leerzeichen zwischen dem ':' und dem ersten char sind. Also bräuchte ich einen Funktion, die erst ein Wort einliest, wenn es kein ' ' ist.
mach Dir keinen Kopf um die Leerzeichen, da können auch ein oder mehrere Zeilenumbrüche stehe - das wird korrekt gelesen. Der std::istream ist so gemacht, dass er Leerzeichen bzw. white-sapce-character (s.o.) zwar als Trenner akzeptiert, aber es im völlig egal ist, wie viele davon da stehen.
Johnny_walk schrieb:
Startanzahl: 1100 Endzahl: 1200 Speicherort: c:\\bla bla\\ modus: nichts
Also ein:
string token; if( getline( file >> ws, token, ':' ) >> wert ) { // 'token' und 'wert' sind ohne Fehler gelesen
reicht aus um dieses Format einzulesen; probiere das einfach mal aus. Das 'c:\\bla bla\' wird auch genau so gelesen - mit jeweils zwei(!) '\' - korrekt ist in der Datei: 'c:\bla bla\'
Johnny_walk schrieb:
Am Besten wäre auch eine Implemtierung, in der ich auch einen konfigurierbare Menupuenkte im Skript nicht mit einem ':' beenden muss, sondern auch hier Leerzeichen einfügen kann.
Mit obigen Code am einfachsten zu erreichen, indem Du nach dem Einlesen von 'token' alle Leerzeichen die rechts stehen, beseitigst.
:xmas2: Werner
-
Danke Werner Salomon,
ich habe gestern noch viel ausprobiert und habe mich in einige Libaries eingelesen. Das meiner Ansicht unangenehmste ist, dass ich die Länge einer TXT-Zeile nicht abschätzen konnte. Damit viel
http://www.cplusplus.com/reference/istream/istream/getline/
schein mal raus, weil ich zwar, meiner bisherigen Meinung nach, '\n' als Delimiter festlegen konnte, aber bei dem Parameter streamsize auf den Schlauch stand.
Ich bin deswegen ersmal über gegangen, die Zeilen zu erkennen. Mittels Internet habe ich folgendes geschafft:
#include <iostream> #include <fstream> #include <string> #include <vector> #include <limits> // std::numeric_limits< std::streamsize > int main() { std::string verzeichnis = // TXT-Datei std::ifstream file(verzeichnis); // <== Filename eintragen std::ifstream columscounter(verzeichnis); std::vector<double> values; bool row = true; unsigned int count_row = 0; for(double d; file>>d;) // Werte einlesen; bis eine Fehler auftritt { values.push_back(d); // Werte in 'values' ablegen } while ( std::getline(columscounter, std::string()) ) ++count_row; std::cout << values.size() << " Werte gelesen" << std::endl; std::cout << count_row << " Zeilen gelesen" << std::endl; }
Das ist zwar ineffizient, aber hat die richtigen Werte ausgegeben. Mittels der size_of() von values konnte ich damit die Zeilenanzahl ermitteln (Matrix und so).
2)
Mir ist auch shcon aufgefallen, dass es besser sei mit / zu arbeiten. In meinen jämmerlichen Versuchen das '\n' einzufangen, wollte ich die Funktion
http://www.cplusplus.com/reference/istream/istream/peek/
benutzen und hatte halt Probleme mit '\'. Das ist ja quasi wie ein Quant und lässt sich nicht fangen
3)
Dazu hatte ich mir noch keine Gedanken gemacht. Allerdings ist mir beim Debuggen aufgefallen, dass die Leerzeichen übersrpungen werden.
Ob er daher auch ein Verzeichnis mit leerzeichen im Skript einliest, keine Ahnung. Ich werde es ausprobieren.
Danke und tschüss
Johnny_walk