String teilen und in Array speichern
-
Probiere den Compilerschalter -std=c++11 (oder 14 oder 17). Wenn der gcc zu alt ist und das nicht kennt, installiere was neueres.
-
Hallo jbaben,
deine Vorgehensweise mit dem Tokenizer ist überflüssig. Lese gleich die Daten in die richtigen Felder ein:
string str("7 Juergen Rhenosterkop Nelspruit 1000"); istringstream iss(str); int nr; string name, addr, addr2; iss << nr << name << addr << addr2;
Und wenn du mehrere Zeilen hast, dann erzeuge dir eine Struktur von den Daten und davon einen Array (bzw. genauer std::vector):
struct Person { int nr; string name, addr, addr2; }; std::vector<Person> persons; Person person; while (iss << person.nr << person.name << person.addr << person.addr2) { persons.push_back(person); }
-
Hallo,
mit Visual Studio 2015 konnte ich das stoi example erstellen.
"Th69" vielen Dank für Deinen Hinweis.
Das hat schon mal funktioniert (C++ CLR-konsolenanwendung):// String_split_03.cpp: Hauptprojektdatei. // Beispiel von: // https://www.c-plusplus.net/forum/posting #include "stdafx.h" #include <iostream> // std::cout #include <stdio.h> #include <stdlib.h> #include <sstream> using namespace System; using namespace System::IO; using namespace System::Text; using namespace std; int main(void) { string str("7 Juergen Rhenosterkop Nelspruit 1000"); istringstream iss(str); int nr, limit; string name, addr1, addr2; iss >> nr >> name >> addr1 >> addr2 >> limit; cout << "Kunden-Nr. : " << nr << '\n'; cout << "Kunden-Name : " << name << '\n'; cout << "Kunden-Addr1 : " << addr1 << '\n'; cout << "Kunden-Addr2 : " << addr2 << '\n'; cout << "Kunden-Limit : " << limit << '\n'; return 0; }
So nun muss ich das noch erweitern: Datei zeilenweise lesen und in Array speichern.
MfG
Juergen B.
-
Kein C++/CLI - nimm C++, d.h. eine Win32-Konsolenanwendung!
-
Hallo,
so hier meine Lösung (Win32-Konsolenanwendung):
// String_split_05.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung. // // Beispiel von: // https://www.c-plusplus.net/forum/viewtopic.php?p=2533723#2533723 #include "stdafx.h" #include <iostream> // std::cout #include <stdio.h> #include <stdlib.h> #include <string> #include <sstream> #include <fstream> #include <vector> using namespace std; struct Person { int nr, limit; string name, addr1, addr2; }; int main() { string fileName = "kunde"; string s, str1; int i = 0; int ende; const char *cstr = str1.c_str(); std::vector<Person> persons; struct Person person[80]; ifstream fd_kunde; fd_kunde.open(fileName, ios::in); // ios::in = lesen, ios::out = schreiben if (!fd_kunde.good()) { cerr << "Fehler beim oeffnen von " << fileName << endl; } else { // Read and display lines from the file until the end of // the file is reached. i = 0; while (!fd_kunde.eof()) { getline(fd_kunde, s); cout << "S = " << s << '\n' << endl; // convert a char* to std::string std::string str1 = s; const char *cstr = str1.c_str(); string str(cstr); istringstream iss(s); iss >> person[i].nr >> person[i].name >> person[i].addr1 >> person[i].addr2 >> person[i].limit; cout << "Kunden-Nr. : " << person[i].nr << endl;; cout << "Kunden-Name : " << person[i].name << endl;; cout << "Kunden-Addr1 : " << person[i].addr1 << endl; cout << "Kunden-Addr2 : " << person[i].addr2 << endl;; cout << "Kunden-Limit : " << person[i].limit << endl;; i++; } } fd_kunde.close(); cout << "Ende"; cin >> ende; return 0; }
Datei "kunde":
7 Juergen Rhenosterkop Nelspruit 1000 8 Margit Rhenosterkop Nelspruit 500
Aber eine Frage habe ich noch zu der Code-Zeile 32 : mit der Zahl 80 habe ich ja die Datensätze begrenzt, kann man das auch unbegrenzt angeben ?
MfG
Juergen B.
-
jbaben schrieb:
Aber eine Frage habe ich noch zu der Code-Zeile 32 : mit der Zahl 80 habe ich ja die Datensätze begrenzt, kann man das auch unbegrenzt angeben ?
Ja, nutze den Vektor aus Zeile 31 anstatt eines Arrays. Den Vektor kannst du zum Beispiel in jedem Schleifendurchlauf um einen Eintrag erweitern.
-
Deswegen habe ich dir ja in meinem vorletzten Beitrag std::vector<Person> empfohlen (den du zwar als Zeile übernommen hast, aber nicht verwendest ;-).
Der std::vector entspricht einem dynamischem Array, welches sich intern entsprechend vergrößert, wenn neue Daten angehängt werden.
Und mit .size() kannst du dann die aktuelle Größe abfragen.
-
Hallo,
danke noch mal für Eure Hinweise.
Hier der korrigierte Code:// String_split_05.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung. // // Beispiel von: // https://www.c-plusplus.net/forum/viewtopic.php?p=2533723#2533723 #include "stdafx.h" #include <iostream> // std::cout #include <stdio.h> #include <stdlib.h> #include <string> #include <sstream> #include <fstream> #include <vector> using namespace std; struct Person { int nr, limit; string name, addr1, addr2; }; int main() { string fileName = "kunde"; string s, str1; int i = 0; int ende; const char *cstr = str1.c_str(); std::vector<Person> persons; struct Person person; // file:///G:/Baben/Dokumentation/C/Dateien/Dateioperationen%20in%20C++.htm //fstream fd_kunde; ifstream fd_kunde; fd_kunde.open(fileName, ios::in); // ios::in = lesen, ios::out = schreiben if (!fd_kunde.good()) { cerr << "Fehler beim oeffnen von " << fileName << endl; } else { // Read and display lines from the file until the end of // the file is reached. i = 0; while (!fd_kunde.eof()) { getline(fd_kunde, s); cout << "S = " << s << '\n' << endl; // convert a char* to std::string std::string str1 = s; const char *cstr = str1.c_str(); string str(cstr); istringstream iss(s); iss >> person.nr >> person.name >> person.addr1 >> person.addr2 >> person.limit; persons.push_back(person); cout << "Kunden-Nr. : " << person.nr << endl;; cout << "Kunden-Name : " << person.name << endl;; cout << "Kunden-Addr1 : " << person.addr1 << endl; cout << "Kunden-Addr2 : " << person.addr2 << endl;; cout << "Kunden-Limit : " << person.limit << endl;; i++; } } fd_kunde.close(); cout << "Ende"; cin >> ende; return 0; }
Auch hier habe ich noch eine Frage: wie kann ich bei dieser Version auf die einzelnen Variablen zugreifen (z.b. Kunden-Nr.[1] usw. ?
MfG
Juergen B.
-
Entweder wie beim Array mit persons[0] für den ersten Eintrag zum Beispiel oder mit persons.at(0) auch für den ersten Eintrag.
Zweiteres überprüft ob der Eintrag existiert und schmeißt eine Exception wenn nicht. Die erste Version versucht einfach zuzugreifen.
-
Hallo,
Danke der Hinweis:
cout << "Kunden.Nr. : " << persons[0].nr << endl;
hat funktioniert.
MfG
Juergen B,
-
Obligatorischer Hinweis: Auch wenn im Volksmund vieles "Nummer" oder "Zahl" genannt wird: Vieles davon sind in Wirklichkeit Ziffernfolgen (also im Computer dann meistens Zeichenfolgen).
Faustregeln zur Unterscheidung:
- Will man damit rechnen? Dann ist es eine Zahl.
- Macht die Angabe des Durchschnitts zweier Werte einen Sinn? Dann ist es eine Zahl.
- Können führende Nullen vorkommen? Dann ist es keine Zahl.
- Würde der Wert auch dann noch Sinn machen, wenn man ihn hexadezimal angibt? Dann ist es eine Zahl.
- Können Buchstaben drin vorkommen? Offensichtlich keine Zahl.
- Was nach obigen Regeln nicht eindeutig als Zahl heraus kam, ist keine Zahl.
Beispiele für "Nummern", die keine Zahlen sind:
Postleitzahl, Telefonnummer, ISBN, Kontonummer, Ausweisnummer.Man wende obige Regeln mal auf diese Beispiele an.
Hart auf der Grenze:
Hausnummern.
Sie sind eigentlich schon sehr zahlenartig, aber dann gibt es so doofe Sonderregeln wie Hausnummer 12a. Das hätte man lieber 12.5 nennen sollen
-
jbaben schrieb:
while (!fd_kunde.eof()) { getline(fd_kunde, s); cout << "S = " << s << '\n' << endl; // convert a char* to std::string std::string str1 = s; const char *cstr = str1.c_str(); string str(cstr); istringstream iss(s); iss >> person.nr >> person.name >> person.addr1 >> person.addr2 >> person.limit;
Das sieht mir aus 2 Gründen merkwürdig aus.
1.: Den String s liest du ein, kopierst ihn in str1. Dann speicherst du einen char* auf str1. Daraus kopierst du erneut einen String namens str (den du nicht nutzt). Dann kopierst du s nochmal in einen iss. So viele Kopien für nichts?2.: eine Loop mit der Bedingung
while (!fd_kunde.eof())
ist nicht sinnvoll. Angenommen, du bist bei am Ende der Datei angekommen, hast aber noch nicht versuch, darüber weg zu lesen, eof ist also noch false. Dann kommt getline und schlägt fehl, weil Datei leer. Du müsstest also NACH dem getline testen. Daher mach doch gleich alles in dem While:while (fd_kunde >> person.nr >> person.name >> person.addr1 >> person.addr2 >> person.limit) { ... } if (!fd_kunde.eof()) std::cout << "habe das Ende nicht erreicht :-((\n";