Zahlen aus CSV einlesen, und als int verfügbar haben

martinjl

Grünschnabel
Hallo zusammen,

vorneweg, ich bin wohl auch als c++ - Neuling zu betrachten und habe noch nicht wirklich das richtige Gespühr für die Sprache bzw gute Syntax-Dokumentationen gefunden (wie zB das php-chm File). Also bitte net hauen wenn ich nichts passendes im Board gefunden habe, bzw es nicht erfolgreich anwenden konnte.

Nun zum Problem: ich habe ein cpp, das mir aus einer csv-Datei Datenpärchen ausliest.

Aufbau des CSV:
1;2
2;3
3;4
...

Es sind also immer Zwillinge, die zusammengehören.

Nun habe ich folgendes Ding verbrochen:

Code:
#include <fstream>
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
	char zeile[10];
	char *key,*value;

	ifstream input("daten.csv",ios::in);

	if (input.good())
	{
		while (!input.eof())
		{
			input.getline(zeile,10);
			key = strtok(zeile, ";");
			value = strtok(NULL, ";");

			if(pos != NULL)
			cout << "Key: " << key << " " << "Value: " << value << endl;
		}
	}
	else
	{
		cout << "Dateifehler oder Datei nicht gefunden!" << endl;
	}

	return 0;
}

Im Beispiel werden Key-Value-Pairs pro Zeile ausgegeben. Allerdings ist die Weiterverarbeitung nicht möglich, da ich 1. keine Ahnung habe, wie ich prüfen kann ob ein eingelesener Wert eine Zahl ist (außer dem Delimiter ";" sind nur Zahlen einzulesen), und 2. nicht weiß, wie ich aus "key" und "value" int-Variablen bekomme :( ... Es wird immer bemängelt, dass der Typ char* ist, wenn ich die vermeidlichen zahlen versuche wo einzulesen.

Kann mir vielleicht jemand den Trick verraten, wie ich da wirkliche Zahlen draus machen kann

Vielen Dankeschön :)
Martin
 
Hi. Willkommen bei tutorials.de!
martinjl hat gesagt.:
Nun habe ich folgendes Ding verbrochen:
So hart würde ich das zwar nicht sagen, aber es ist verbesserungsfähig und noch ist nichts verloren... ;)

martinjl hat gesagt.:
Code:
	ifstream input("daten.csv",ios::in);

	if (input.good())
Hier solltest du eher prüfen ob die Datei geöffnet werden konnte:
C++:
if (input.is_open())
Die Methode good() et. al. brauchst du fast nie.
martinjl hat gesagt.:
Code:
while (!input.eof())
In anderen Sprachen wie Visual Basic Ok; in C++ und C ein Kapitalfehler. Erstens ist nicht festgelegt wann eof() wahr wird (schon wenn die nächste Lesenaktion fehlschlagen wird oder erst wenn das Lesen wegen EOF fehlgeschlagen ist), d.h. es kann passieren das man die letzte Zeile überliest. Außerdem wird nie EOF erreicht falls der Stream in einen Fehlerzustand geht. Dann kann nämlich nichts mehr eingelesen werden und somit wird eof() nie wahr.

martinjl hat gesagt.:
Code:
input.getline(zeile,10);
Hier versuchst du etwas einzulesen, prüfst aber gar nicht ob das auch erfolgreich war. Wenn getline fehlschlägt (was es am Ende des Streams tut) arbeitest du mit dem alten Wert von zeile weiter.

Das übliche Idiom um in C++ zeilenweise von einem Stream einzulesen sieht so aus:
C++:
string zeile;
while (getline(input, zeile)) { }
Damit schlägt man gleich 2 Fliegen mit einer Klappe. Erstens muß man nicht extra in der Schleife prüfen ob das Einlesen klappt und dann wird die Schleife auch generell beendet wenn der Stream in einem Fehlerzustand ist - und auch wenn EOF auftritt.

Um einen String in Integer Werte zu wandeln würde ich in C++ einen stringstream benutzen:
C++:
#include <sstream>
...
istringstream istr (zeile); // zeile = "34;45"

int a, b;
char c;

if (istr >> a && istr >> c && c == ';' && istr >> b) {
      /* a = 34  b = 45 */
}
Gruß
 
Zuletzt bearbeitet:
Hallo deepthroat,

vielen Dank für Deine ausrührliche Antwort.
ich versuche gerade in den einzelnen Parts nachzuvollziehen wie der Code arbeitet. Das gelingt mir zum Glück auch ganz gut, nur fehlt mir leider noch für C++ der Blick für den Zusammenhang an der Geschichte ...

- input.is_open sehe ich ein, ja :)

verbunden hab ichs nun mal so, wahrscheinlich grottenfalsch, aber wiegesagt, ich mach das leider noch net lang und hab nicht wirklich doku zu der Sprache :(.

C++:
#include <fstream>
#include <iostream>
#include <iomanip>
#include <sstream>

using namespace std;

int main()
{
	char zeile[10];
	int a, b;
	char c;

	ifstream input("daten.csv",ios::in);

	if (input.is_open())
	{
		while (getline(input, zeile)) 
		{
			istringstream istr (zeile); // zeile = "34;45"
			if (istr >> a && istr >> c && c == ';' && istr >> b) 
			{
				cout << "a: " << a << " - b: " << b << endl;
			} 
		}

	}
	else
	{
		cout << "Dateifehler oder Datei nicht gefunden!" << endl;
	}

	return 0;
}

Da bekomm ich nun aber beim compilieren nen Fehler
Code:
Borland C++ 5.5 for Win32 Copyright (c) 1993, 2000 Borland
read.cpp:
Error E2285 read.cpp 18: Could not find a match for 'getline<charT,traits,Allocator>(ifstream,char *)' in function main()
*** 1 errors in Compile ***

irgendwie steh ich grad voll auf dem Schlauch :(
 
Zuletzt bearbeitet von einem Moderator:
Hi.

Du solltest die Variable zeile als std::string definieren. Das hat verschiedene Vorteile, aber der größte ist das du dir keine Sorgen machen mußt ob die Eingabe auch in den C-String eingelesen werden kann weil ja nur eine begrenzte Anzahl von Zeichen reserviert wurde. Der std::string ändert die Größe automatisch. Außerdem mußt du dir keine Gedanken über die Terminierung machen, kannst std::string's mit dem != == Operatoren vergleichen, usw.

C++:
#include <string>
...
string zeile;
Gruß
 
Zuletzt bearbeitet:
dankeschön :)

es ist doch immer wieder interessant was man alles außerhalb der regulären vorlesungen über bestimmte sachverhalten und möglichkeiten erfährt, die einem eine sprache bietet.

die geschichte mit dem string hat uns niemals jemand gesagt ... mein wissensstand betrug nur dass ein string ein chararray ist, das ich so definieren muss. große klasse, erschwert einem das leben ungemein.

also nochmals vielen dank !! nun klappt alles so wies soll :)
 
martinjl hat gesagt.:
also nochmals vielen dank !! nun klappt alles so wies soll :)
Bitte, gern geschehen. Aber dann setz doch evtl. gleich noch das Thema auf erledigt und bitte halte dich in Zukunft an die übliche Groß-/Kleinschreibung (siehe Netiquette Nr. 15).

Gruß
 
Zurück