Zeilenweise Auslesen aus Datei

schwegennagel

Cadet 4th Year
Registriert
Feb. 2005
Beiträge
79
Hallo,
ich möchte aus einer Datei den Text zeilenweise auslesen. nach einer Zeile soll also erst einmal gestoppt werden, dass Prgramnm soll etwas machen, dann soll die nächste Zeile gelesen werden. Das ganze am Besten nur in C++.
Mein Vorschlag:
while(!infile.eof())
{
infile.getline(zeile,250,'/n');
cout<<zeile<<"test"<<endl;

}
Nun sollte ja nach jedem Zeilenumbruch ein test erscheinen, tut es aber nicht. Wieso??
 
Könnte daran liegen, daß du /n statt \n verwendest. Wenn du es weglässt sollte er automatsich bis \n lesen so wie ich die MSDN verstehe.
 
'/n' müsste doch direkt zu einem Fehler beim Compilieren führen... insofern weiß ich nicht, ob er wirklich '/n' geschrieben hat....
 
Mal anders gefragt, was tut es denn dann? Soviel musst du uns schon verraten, sonst kommen die Antworten aus der Glaskugel. ;)

So wie es da steht (ich gehe davon aus, dass '\n' bei getline steht)- wenn nicht gerade eine Zeile mal länger als 250 Zeichen ist - wird das test an's Ende jeder Zeile geschrieben.
 
Hallo,
habe einfach den Schrägstich falsch gesetzt. Habe ich dann leider erst nach einiger Zeit bemerkt. Hat sich also erledigt. Ich habe noch eine Frage zu folgendem:

CPunkt operator+=(CPunkt &p1, const CPunkt &p2)

{ p1=p1+p2;
return p1;
}

p1 und p2 sind Objekte derselben Klasse. Die Addition durch + wurde durch eine andere Operatorüberladung definiert. Die zwei Objekte sollen also mit += verarbeitet werden. Mein Prof. meinte das & vor p1 sei unbedingt nötig. Aber wieso denn, es gibt doch return?
 
Zuletzt bearbeitet:
p1 soll doch schließlich verändert werden. Da hilft dir der Return-Wert nicht.

Also p1 += p2;

Und zum Schrägstrich - eigenartig, das hätte eigentlich nicht kompilieren dürfen (2 Zeichen in einem char-Literal). Welchen Compiler benutzt du?
 
Guten Morgen,
ich benutze die Visual C++ Umgebung. Wieso reicht das return denn nicht?? Return gibt doch das Ergebnis der Addition zurück. Wozu diese Referenz? Wernn ich jetzt p1+=p2 aufrufe, werden p1 und p2 als Argumente übergeben und der return Wert wird p1 zugewiesen. Dann wird p1 doch verändert??
 
Nein. Der Return-Wert hat damit nix zu tun. Du könntest auch void nehmen.
Der Return-Wert ist nur für Verkettung:

p3 = p1 += p2;

p3 -> Return-Wert
p1 -> Erstes Argument an Operator +=
p2 -> Zweites Argument an Operator +=

p1 muss verändert werden, daher eine Referenz, keine const-Referenz. So funktioniert operator += nunmal.
 
Ich hätte noch eine Frage. Bei diesem Code meckert der Compiler:
CPunkt CPunkt::operator-(void) const

{ this->x=-(this->x);
this->y=-(this->y);
}

Hier kann doch keine read-only Methode verwendet werden, oder?
 
Doch, MUSS sogar. Die X-operatoren - im Gegensatz zu den X= Operatoren (das X durch die jeweiligen Zeichen +,-,*,/,... ersetzen) - verändern das Objekt nicht, sondern geben ein neues zurück.

Die kanonische Implementierung von operator+ (etc) sieht so aus:
Code:
const A A::operator+( const A& other) const
{
  A result( *this);
  result += other;
  return result;
}
Also operator+ wird mit operator+= implementiert. Prinzip verstanden? :)

Achso, welche Version vom Visual C++ benutzt du?
 
Hallo,
also was mit "Also operator+ wird mit operator+= implementiert." gemeint habe ich so nicht verstanden.
Aber wenn ich den unten stehenden Code benutze sagt der Compiler:"error C2166: L-Wert gibt ein konstantes Objekt an". Wenn ich das const weglasse funktioniert alles. Verstehe ich nicht. Ich benutze Visual Basic 6.0.


CPunkt CPunkt::operator-(void) const

{ this->x=-(this->x);
this->y=-(this->y);
return *this;
}
 
Kann mir bitte jemand das Problem mit dem Compiler noch erklären. War meine Frage nicht verständlich?
 
Nunja
das "const" sagt eben das die Variablen der Klasse nicht verändert werden dürfen du machst es aber trotzdem.
Ganz zu schweigen der Sinn des Codes. Wozu benötigt man einen - operator der keine Argumente übernimmt? Der dazu auch noch Sachen rechnet die man auf ein simples "x = 0" bzw. "y = 0" reduzieren könnte.

EDIT: Achja, werf den Compiler in die Tonne der hat auch schon seine Dekade hinter sich und ist so verbuggt das man gar nicht weiß wo man anfangen soll den zubemängeln.
 
Zuletzt bearbeitet:
Moin,
also der -Operator ist hier der unäre. Er ist als Methode in einer Klasse implementiert. Aufgrund des this-Zeigers brauch der Operator dann ja nichts mehr übernehmen. Aber um noch einmal auf das Andere zurückzukommen- das const ist hier also fehl am Platz, da ich ja ein Objekt ändere. Richtig??
 
Hi,

bitte ein bisschen Geduld mit Antworten :) Die kommen schon, nur manchmal kommen auch ein paar andere Sachen dazwischen. :)

Zum Compiler - warum benutzt du denn das alte Mistding? Müsst ihr das? Sonst würde ich auf jeden Fall wechseln.

Sorry, hatte übersehen, dass es sich um den unären operator- handelt. Da dieser das Objekt selbst verändern muss, darf der natürlich nicht const sein, das ist richtig. Das ganze Gedusel mit dem this-> würde ich übrigens rauswerfen. Es gibt nur wenige Situationen, wo ein vollständig qualifizierter Bezeichner von nöten ist. In den Situationen, wo er mit anderen Namen in der Klasse kollidiert, sollte man sich eher über die Namensgebung gedanken machen.


Nochmal oben zu operator + und operator += :

operator+= verändert das Objekt, aus das er angewandt wird - sprich den ersten Parameter im operator+= bzw. den this-Pointer. operator+ gibt dagegen ein neues Objekt zurück, was die "Addition" der beiden Parameter des operator+ ist. Er verändert die Parameter bzw. den this-Pointer auf keinen Fall.

Beispiel anhand von int's:
Code:
int x = 3;
int y = 4;
int z = 5;
x += y; // in x steht nun 7, x wird verändert. der Return-Wert wird nicht genutzt!
z = x += y; // in x steht nun 11 (7+4), in z steht jetzt auch 11, da der Return-Wert genutzt wird
z = x + y; // in z steht nun 15, x und y werden nicht geändert

Wenn du nun einen korrekt funktionierenden operator += hast, kannst du beim operator+ vom ersten Parameter-Objekt eine Kopie erstellen und auf diese Kopie den operator+= anwenden um den zweiten Parameter auf die Kopie zu "addieren". Dann gibst du die Kopie zurück.
Noch ein Beispiel:
Code:
int x = 2;
int y = 3;
int z = 0; // z soll der Ergebnis von x + y erhalten

int kopie = x;
kopie += y;
z = kopie;

Das ist mit operator+ mit operator+= implementieren gemeint. Auf diese Art und Weise schreibst du Code nicht zweimal, außerdem verhält er sich so wie operator+ bei int's. (erste Regel zum Verhalten beim Schreiben von Operatoren: do it as the int's do - lass deine Operatoren sich so verhalten, wie sie es auch bei int's tun würden)
 
Zuletzt bearbeitet:
Hallo,
ich denke ich habe es jetzt verstanden. Ich benutze den Compiler, weil der auch in der Hochschule auf den Rechnern installiert ist.
iAllerdings habe ich noch eine Frage zum exception-Handling in C++. Mit throw wird ja eine Kennung an catch ausgeworfen. Nun habe ich leider ohne Begründung gelesen, dass der Auswurf eines Objektes z.B. throw test() besser sei als einfach nur der Auswurf eines Meldungstxtes z.B throw "Fehler". Wieso??
 
Hallo,

eventuell solltest du einfach bei neuen Fragen neue Themen eröffnen. :) Mit zeilenweisem Auslesen von Dateien hat das ja nichts mehr zu tun. :)

Warum ein throw objekt; besser ist?

Dafür gibt es mehrere Gründe.

Zum einen kannst du verschiedene Typen werfen und wieder catchen und anhand dieser Typen auf die Fehlerart schließen. Wenn du nur einen Typ, z.B. const char* (throw "Test") wirfst, hast du zwar einen Text, müsstest diesen allerdings wieder parsen um zu wissen, was der Fehler eigentlich bedeutet. Sowas macht man einfach nicht, weil der reine Text, der ankommt, eine ziemlich unzuverlässige Information ist in dem Sinne, dass jeder dort irgendwas reinschreiben kann. Außerdem ist das völlig un.nötiger Aufwand.
Stattdessen kannst du z.B. throw MathematischerFehler() oder throw LogischerFehler() machen und später im catch auf diese Fehler wieder korrekt reagieren.
Außerdem wird im catch Vererbung unterstützt. Z.B. angenommen du hast folgende Klassenhierarchie:

class Basisfehler ...
class GanzSchlimmerFehler : public BasisFehler ...
class DieHoelleGefriert : public GanzSchlimmerFehler
// noch mehr ableitungen von GanzSchlimmerFehler
class NichtSoSchlimmerFehler : public BasisFehler ...
class Benutzereingabefehler : public NichtSoSchlimmerFehler ...
// und so weiter...

später kannst du ein catch auf BasisFehler machen, um jeden Typ von Fehler zu behandeln. Oder ein catch auf NichtSoSchlimmerFehler, um gezielt auf solche Fehler zu reagieren. Welche abgeleiteten Klassen es gibt, kann dir erstmal egal sein an dieser Stelle. Im Prinzip kannst du so gezielt auf bestimmte Fehlersituationen reagieren und andere Fehler allgemeiner behandeln oder auch garnicht behandeln und von einem übergeordneten catch erst auffangen lassen.
Ein catch(...) oder ein catch( const char*), wenn du nur const char* wirfst, fängt dir dagegen immer alle Fehler sofort weg. Dabei geht es mit einem catch( const KonkreterTyp&) viel viel einfacher, genauer, und vor allem im Code auch deutlicher erkennbar. Und du machst dir und dem Compiler weniger Arbeit, denn genau dafür (verschiedene Typen) ist das Exception-Handling da.

Ist das in etwa klar so?
 
Zuletzt bearbeitet:
Dazu ist anzumerken, dass es in C++ bereits eine Exception-Hierarchie gibt.

Z.B. inkludierst du <stdexcept> und kannst dann throw std::runtime_error( "Text") machen. (bzw. anstatt Text ein std::string). Die Basisklasse aller vordefinierten Exceptions ist std::exception (auf die kann und sollte man eigentlich immer catchen). Darunter gibt es eine ganze Menge andere, z.B: std::bad_alloc, wenn der Speicher zuende ist. Alle Exceptions haben die Methode what(), die die Meldung enthält.

Mit ein wenig Googeln solltest du dazu noch einiges an Infos finden.

Btw: Die goldene Regel bei Exceptions: throw by value, catch by const reference. D.h. du wirfst immer konkrete Objekte, niemals irgendwelche Pointer auf Objekte, die mit new erzeugt wurden o.ä. . Beim Catch immer eine const-Referenz auf den Exception-Typ nehmen.
 
Zurück
Oben