Seite 1 von 2

Pufferüberlauf, Namespaces und andere Katastrophen

Verfasst: Mi Okt 28, 2009 7:36 pm
von Bebu
Ich beiße mich immer noch fleißig (je nach Laune) durch mein Buch. Im Moment durch die Funktionen der C++ Standartbibliothek. Im Laufe dessen, habe ich folgenden Code verfasst, als Übung zu einem Kapitelende:

Code: Alles auswählen

//Präprozessor Includes
#include <iostream>
#include <string>
#include <fstream>

// Namespace Verwaltung
using namespace std; //Standartnamespace nutzen


// Globale Variablen

// Aufzählungen(enum)

// Strukturdefinitionen(struct)

// Klassendefinitionen(class)

// Funktionsdeklarationen
void leeren();
// Main Funktion
int main()
{
//Variablen und Klassen definieren
string dateiquelle;
string dateiziel;

ifstream dat_in;
ofstream dat_out;

char zeichen;

cout << "Geben Sie die Quelldatei ein: ";
cin >> dateiquelle;
leeren();
cout << "Geben Sie den Namen der Zieldatei ein: ";
cin >> dateiziel;
leeren();

//Öffnen von Quell- und Zieldatei
dat_in.open(dateiquelle.c_str(),ios_base::in);
dat_out.open(dateiziel.c_str(), ios_base::out);

//Abfragen ob Quelldatei geöffnet werden konnte
if (!dat_in)
{
    cerr << "Datei konnte NICHT geöffnet werden!!\n";
    return 1;
}

//Abfragen ob Zieldatei erzeugt werden konnte
if (!dat_out)
{
    cerr << "Datei konnte NICHT erzeugt werden!!\n";
    return 1;
}

//Zeichen für Zeichen kopieren
while (!dat_in.eof())
{
    dat_in.get(zeichen);
    dat_out << zeichen;
}

//Dateien schließen
dat_in.close();
dat_out.close();
return 0;
}

// Sonstige Funktionen(müssen unter Funtionsdeklarationen eingetragen werden)
//Funktion zum leeren des Puffers von cin
void leeren()
{
    cin.clear();
    while(cin.get() != '\n')
    ;
}
Es ist ein Programm zu Kopieren von Dateien, laut meinem Buch für Textdateien gedacht.
Erste Frage: Kann dieses Programm bedenkenlos jede Art von Dateien kopieren? Ich hab es mal versucht, bin mir aber über das Ergebnis nicht ganz sicher, der erster Eindruck war, dass es geht. Binärdateien bestehen ja eigentlich auch nur aus Zeichen.

Zweite Frage: Beim Öffnen der Dateien

Code: Alles auswählen

dat_in.open(dateiquelle.c_str(),ios_base::in);
ist mir das "ios_base" ein bisschen suspekt. Das ist doch ein Namensraum oder etwa nicht? Als ich versucht habe es in die Namensräume einzutragen hat der Compiler gemeckert, ios_base wäre kein Namensraum. Versucht habe ich es so:

Code: Alles auswählen

using namespace std, ios_base;

sowie so

Code: Alles auswählen

using namespace std;
using namespace ios_base;
Habe ich da einen Fehler gemacht, oder ist das wirklich kein Namensraum? Wenn nicht, was ist es dann?

3. Frage: Enthält die Funktion cin eine Feldgrenzenüberwachung? Wenn nicht, wie kann ich die Größe der Daten im Puffer überprüfen, bevor ich sie in eine Variable schreibe?
Hat cin eine Memberfunktion, mit der man die Größe des Puffers überprüfen kann, z. B. per sizeof?

Das war es fürs erste mal

Gruß Bebu

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Verfasst: Mi Okt 28, 2009 7:56 pm
von Dirty Oerti
Mal eine Antwort auf deine 2.Frage, also die Frage nach dem Namespace ios_base. (Ich sollte jetzt eigntl Physik lernen..^^ )
Darin steckt auch gleich die Antwort: ios_base ist (meines Wissens nach) ein ganz normaler Namespace.
Ich zeige dir nun auch, wie du ihn verwenden können müsstest:

Code: Alles auswählen

using namespace std::ios_base;
Das Problem: Variablennamen wie "in" wären dann nicht mehr möglich (es gibt ein "in" in ios_base).
Von daher ist dieser Namespace wohl ziemlich sinnvoll gewählt...

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Verfasst: Mi Okt 28, 2009 8:05 pm
von Bebu
Mit den Variablennamen hast du dann natürlich recht, es hat mich eigentlich auch nur so interessiert.
Allerdings meckert der Compiler auch, wenn ich deinen Code oben so verwende. Jemand eine Idee?

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Verfasst: Mi Okt 28, 2009 8:19 pm
von cloidnerux
ios_base ist eine Klasse, siehe hier.
ios_base enthält einige globale konstanten für die Steuerung der eingabe, die du über "::" abrufen musst, da sie im Objekt nicht erreichbar sind.
Desswegen kannst du auch nicht

Code: Alles auswählen

using namespace std::ios_base
nutzen.

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Verfasst: Mi Okt 28, 2009 8:22 pm
von Dirty Oerti
Sollte man nicht auch auf Klassen-Namespaces irgendwie zugreifen können?

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Verfasst: Mi Okt 28, 2009 8:25 pm
von cloidnerux
Wieso sollte man das können?
Damit hättest du dan zugriff auf Klassenspezifische Funktionen und Variablen, die im Aktuellen Kontext sinnlos wären.
Was für ein Sinn hätten dan noch Namespaces und Klassen, wenn man alle mit using namespace Gloabl zugänglich macht.
Und ob

Code: Alles auswählen

dat_in.open(dateiquelle.c_str(),ios_base::in);
oder

Code: Alles auswählen

dat_in.open(dateiquelle.c_str(),in);
macht ja nicht wirklich einen Unterschied.

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Verfasst: Mi Okt 28, 2009 8:37 pm
von Bebu
OK, es ist also kein Namespace im eigentlichen Sinn, der Rest ist mir wohl im Moment noch zu hoch. Die verlinkte Seite, sieht aber so aus, als ob sie ganz praktisch wäre. Da hat mein Buchautor aber ein bisschen wenig Zeit für Erklärungen verloren. Irgendwie war der Einführende Teil sehr gut erklärt, aber seit der Standardlibary tauchen immer wieder Sachen auf, die er nicht so ganz erklärt. Schon wieder ein paar Abzüge...

Es ging mir ja nicht darum alles Namespaces einzubinden, es hat mich nur Interessiert ob es funktioniert.

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Verfasst: Mi Okt 28, 2009 8:46 pm
von Dirty Oerti
cloidnerux hat geschrieben:Wieso sollte man das können?
Damit hättest du dan zugriff auf Klassenspezifische Funktionen und Variablen, die im Aktuellen Kontext sinnlos wären.
Was für ein Sinn hätten dan noch Namespaces und Klassen, wenn man alle mit using namespace Gloabl zugänglich macht.
Und ob

Code: Alles auswählen

dat_in.open(dateiquelle.c_str(),ios_base::in);
oder

Code: Alles auswählen

dat_in.open(dateiquelle.c_str(),in);
macht ja nicht wirklich einen Unterschied.
Das ist schon klar^^ Ich meinte nur mich erinnern zu können, dass es eine Möglichkeit gibt, in Klassenamespaces einzugreifen.

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Verfasst: Sa Okt 31, 2009 2:22 pm
von Bebu
Hat hier zufällig noch jemand eine Antwort auf die anderen beiden Fragen? Vor allem die Antwort auf dritte Frage fände ich wahnsinnig interessant und hilfreich. :|

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Verfasst: Sa Okt 31, 2009 2:51 pm
von Xin
Bebu hat geschrieben: Es ist ein Programm zu Kopieren von Dateien, laut meinem Buch für Textdateien gedacht.
Erste Frage: Kann dieses Programm bedenkenlos jede Art von Dateien kopieren? Ich hab es mal versucht, bin mir aber über das Ergebnis nicht ganz sicher, der erster Eindruck war, dass es geht. Binärdateien bestehen ja eigentlich auch nur aus Zeichen.
Ich bin mir da momentan nicht sicher, da ich die Streams eigentlich selten benutze, da mir die C-Funktionen hier einfacher erscheinen (und die Streams ihre Funktionalität in der Regel über die C-Funktionen abwickeln).

Grundsätzlich kann durch einen Stream kommen, was immer will. Linux macht da soweit ich weiß auch keine nennenswerten Unterscheide.
Schonmal eine ausführbare Datei kopiert? ^^
Wenn sie danach nicht mehr funktioniert, beantwortet das Deine Frage vermutlich schneller. ^^
Bebu hat geschrieben:Zweite Frage: Beim Öffnen der Dateien

Code: Alles auswählen

dat_in.open(dateiquelle.c_str(),ios_base::in);
ist mir das "ios_base" ein bisschen suspekt. Das ist doch ein Namensraum oder etwa nicht? Als ich versucht habe es in die Namensräume einzutragen hat der Compiler gemeckert, ios_base wäre kein Namensraum. Versucht habe ich es so:

Code: Alles auswählen

using namespace std, ios_base;

sowie so

Code: Alles auswählen

using namespace std;
using namespace ios_base;
Habe ich da einen Fehler gemacht, oder ist das wirklich kein Namensraum? Wenn nicht, was ist es dann?
Eine Klasse.
Eine Klasse bildet ebenfalls einen Namensraum, den Du aber nicht per using namespace einbinden kannst. Du greifst mit ios_base::in auf den statischen Member der Klasse ios_base zu.
Bebu hat geschrieben:3. Frage: Enthält die Funktion cin eine Feldgrenzenüberwachung? Wenn nicht, wie kann ich die Größe der Daten im Puffer überprüfen, bevor ich sie in eine Variable schreibe?
Hat cin eine Memberfunktion, mit der man die Größe des Puffers überprüfen kann, z. B. per sizeof?
Sizeof sagt Dir wie groß ein Datentyp ist. Über Objekte sagt sizeof nichts aus.
Feldgrenzenüberwachung ist in C++ kein Thema. Das Motto heißt, dass Du doch bitte korrekt programmieren solltest.

Dateien sind speziellere Klasen. Du müsstest Dir wo istream ansehen, dort solltest Du die seekq-Methode finden. Damit kannst Du an das Ende des Streams springen und Dir sagen lassen, wo Du grade bist. Eben soviele Bytes hinter dem Start, wie das File lang ist...

Das Beispiel findest Du hier: http://www.cplusplus.com/reference/iost ... eam/seekg/