Problem beim einbinden von iostream und fstream

UncleBob

Mitglied
Habe mal wieder Bibliotheksprobleme wies aussieht.

Ich verwende VisualStudio und programmiere nicht allzu häufig, nur ab und zu zum Vergnügen. Jedenfalls scheint etwas mit meiner Einbindung nicht zu stimmen.

Die Dateien iostream.h und fstream.h werden im Header inkludiert und auch Gefunden.

Wenn ich allerdings versuche funktionen daraus aufzurufen kriege ich schlagartig Lnk2001er, in etwa so:

Code:
1>ES_TerrLib.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall ifstream::close(void)" (?close@ifstream@@QAEXXZ)".
1>ES_TerrLib.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: __thiscall ifstream::ifstream(char const *,int,int)" (0ifstream@@QAE@PBDHH@Z)".
1>ES_TerrLib.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: static int const filebuf::openprot" (?openprot@filebuf@@2HB)".
1>ES_TerrLib.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: virtual __thiscall ios::~ios(void)" (1ios@@UAE@XZ)".
1>ES_TerrLib.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: virtual __thiscall ifstream::~ifstream(void)" (1ifstream@@UAE@XZ)".
1>.\Debug/IsoEngine.exe : fatal error LNK1120: 5 nicht aufgelöste externe Verweise.

Die kleinigkeit die dazu führt ist lediglich der Versuch eine Datei zu öffnen und wieder zu schliessen, ansonsten mach ich noch nicht einmal etwas damit:

Code:
	ifstream TL_File( mFileName, ios::in);
	TL_File.close();

Diese zwei Zeilchen sind die Ursache des ganzen übels. Ich nehme an ich muss irgendwo noch ne lib eintragen, aber ich weiss nicht welche und nicht wo. Wäre froh wenn mir das jemand sagen könnte...
 
Jop, funktioniert, vielen Dank.

Jetzt stecke ich allerdings in einem neuen Problemchen, hinter das ich nicht ganz blicke... wahrscheinlich irgend ein kleiner fehler den ich mit meiner geringen Erfahrung einfach nicht sehe.

Das Programm sieht jetzt so aus:

Code:
	char *Temp = new char;
	bool Check = false;

	ifstream TL_File( mFileName, ios::in);
	Check = TL_File.fail();
	cin.getline(Temp, 100);
	TL_File.close();

Das Problem ist das obwohl Check false zurückgibt, die Datei also existiert und in ihr auch was geschrieben steht (immerhin hab ichs da selber reingeschrieben), Temp immer lehr zurückkommt... irgendwas klappt da wohl noch nicht so ganz. Sieht jemand etwas im Code das nicht stimmt?
 
Hi.
Das Programm sieht jetzt so aus:

Code:
	char *Temp = new char;
	bool Check = false;

	ifstream TL_File( mFileName, ios::in);
	Check = TL_File.fail();
	cin.getline(Temp, 100);
	TL_File.close();

Das Problem ist das obwohl Check false zurückgibt, die Datei also existiert und in ihr auch was geschrieben steht (immerhin hab ichs da selber reingeschrieben), Temp immer lehr zurückkommt... irgendwas klappt da wohl noch nicht so ganz. Sieht jemand etwas im Code das nicht stimmt?
Ja. Du hast dynamisch Speicher für einen char reserviert und gaukelst dann der getline Methode vor, das dort 100 Zeichen gespeichert werden könnten. Da ist es verwunderlich, das das Programm nicht abstürzt. ;-]

Dann solltest du (fast) nie die .fail(), .eof() oder .bad() Methoden aufrufen. Um zu prüfen ob die Datei geöffnet werden konnte nimm die .is_open() Funktion.

Um dich nicht mit der Speicherallozierung rumzuschlagen, solltest du einen std::string verwenden um die Zeile einzulesen.
C++:
#include <string> // für die getline() Funktion

ifstream TL_File( mFileName);
string line;

if (!TL_File.is_open()) {
  cerr << "datei konnte nicht geöffnet werden.\n";
} else if (getline(TL_File, line)) {
  cout << line << endl;
}
Gruß
 
Aha, ja, das funktioniert, vielen Dank!
Ich wusste gar nicht das es ausserhalb des .Net-frameworks auch noch eine string-klasse gibt, das macht mir vieles einiges leichter. Leider scheint meine Dokumentation zu der Klasse aber auch dürftig zu sein, sind da per Zufall auch noch funktionen zum Konvertieren in andere Datentypen (BYTE, float etc) vorhanden?

Eine Frage habe ich aber noch zu vorhergehendem, weil mir die Sache nicht ganz klar ist...

Ich kann in einem char* ja problemlos ganze Sätze speichern, z.b. char* St = "Dieser Char beinhaltet 100 Zeichen...........usw"

warum muss ich dann zusätzlichen Speicher alokieren wenn der Input aus einem File stammt?
 
Leider scheint meine Dokumentation zu der Klasse aber auch dürftig zu sein, sind da per Zufall auch noch funktionen zum Konvertieren in andere Datentypen (BYTE, float etc) vorhanden?
Dazu verwendet man in C++ (String-) Streams:
C++:
#include <sstream>

float f;
std::istringstream frmt("45.44");

if (frmt >>f) {
  cout << "float: " << f << endl;
}
Eine Frage habe ich aber noch zu vorhergehendem, weil mir die Sache nicht ganz klar ist...

Ich kann in einem char* ja problemlos ganze Sätze speichern, z.b. char* St = "Dieser Char beinhaltet 100 Zeichen...........usw"
Offenbar hast du dich noch nicht mit Zeigern und Arrays beschäftigt. Die Variable St ist ein Zeiger. Dieser speichert eine Adresse von einem Speicherbereich. D.h. du kannst dort keine "ganzen Sätze" speichern, du kannst grundsätzlich nur eine Adresse speichern. In deinem Beispiel wird dort die Adresse des Stringliterals "Dieser Char beinhaltet 100 Zeichen...........usw" gespeichert. Das heißt der Zeiger zeigt dorthin. Der Speicher wurde in diesem Fall automatisch vom Compiler reserviert und du brauchst dich nicht darum zu kümmern.

Dein Beispiel ist allerdings auch etwas falsch, denn Stringliterale können nicht geändert werden. Ganz korrekt müßte es so aussehen:
C++:
const char* St = "Dieser Char beinhaltet 100 Zeichen...........usw";
oder so:
C++:
char St[] = "Dieser Char beinhaltet 100 Zeichen...........usw";
warum muss ich dann zusätzlichen Speicher alokieren wenn der Input aus einem File stammt?
Erstmal: das Verb heißt allozieren. :)

Das hat mit der Datei wenig zu tun. Du mußt einfach dafür sorgen, wenn du 100 Zeichen irgendwo hinspeichern willst, das dort auch 100 Zeichen zur Verfügung stehen. In dem Fall z.B. so:
C++:
char* str = new char[100]; // Platz für 100 Zeichen, also Stringlänge max. 99
Gruß
 
Offenbar hast du dich noch nicht mit Zeigern und Arrays beschäftigt.

Nun mit Arrays habe ich eigentlich keine Probleme, aber mit den Zeigern tu ich mich schon noch etwas schwer, da ich von VB her komme (und das ist auch schon ein weilchen her...). Deine Antwort hat aber meine Überlegungen in die Richtung bestätigt, ich denke ich begreife das Konzept langsam.

Vielen Dank auch für die Hilfe mit den string-streams, das hilft mir schon mal ganz schöhn weiter! :)
 
Sorry, nochmal ein kleines Problem. Dein Code für die String-streams funktioniert wundervoll mit ziemlich allen Datentypen, nur wenn ich mit BYTEs arbeite scheint das irgendwie ein bisschen anders zu sein.

Ich habe deinen Code recht genau übernommen und die entsprechenden Änderungen gemacht, sieht jetzt so aus:

Code:
	std::istringstream Sstream(Temp);
	if( Sstream >> Rows){
		cout << "BYTE: " << Rows << endl;
	}

Nur hat Rows dann einen anderen Wert als es eigentlich haben sollte. Wenn Temp den Wert "5" hat enthält Rows anschliessend den Wert 53. Woran liegt das?
 
Sorry, nochmal ein kleines Problem. Dein Code für die String-streams funktioniert wundervoll mit ziemlich allen Datentypen, nur wenn ich mit BYTEs arbeite scheint das irgendwie ein bisschen anders zu sein.

Ich habe deinen Code recht genau übernommen und die entsprechenden Änderungen gemacht, sieht jetzt so aus:

Code:
	std::istringstream Sstream(Temp);
	if( Sstream >> Rows){
		cout << "BYTE: " << Rows << endl;
	}

Nur hat Rows dann einen anderen Wert als es eigentlich haben sollte. Wenn Temp den Wert "5" hat enthält Rows anschliessend den Wert 53. Woran liegt das?
Nun, 53 ist der ASCII Code des Zeichens '5'.

BYTE ist einfach nur ein typedef (Alias) des Typs "unsigned char". Dieser Typ wird beim Einlesen genauso behandelt wie "char". Und wenn du aus dem String "5" ein einzelnes Zeichen einliest, bekommst du eben ein '5'.

Gruß
 
Zurück