Textdatei öffnen und auslesen
-
Was macht dieses Konstrukt:??
std::istream& Char( std::istream& in ) { char c; if( in >> c && c != C ) in.setstate( std::ios_base::failbit ); return in; }Was geschieht hier:
&& file
-
datensalat schrieb:
Was macht dieses Konstrukt:??
std::istream& Char( std::istream& in ) { char c; if( in >> c && c != C ) in.setstate( std::ios_base::failbit ); return in; }Char<> ist eine sogenannte Manipulator-Funktion - genau wie z.B. hex.
Sie liest ein Zeichen 'c' ein. Geschieht dies ohne Fehler, so wird das Zeichen mit der Konstanten 'C' verglichen und falls die Zeichen ungleich sind, so wird das Fehlerflag im Stream 'in' gesetzt.Das ganze überliest ein konkretes Zeichen und falls das Zeichen das erwartete war, geschieht sonst nichts.
datensalat schrieb:
Was geschieht hier:
&& file'&&' ist ein logisches UND. rechts und links davon sollten nach bool konvertierbare Ausdrücke stehen. Links steht
iZl < 3und rechts
file >> arr[iZl][0] >> Char<','> >> arr[iZl][1] >> Char<','> >> arr[iZl][2]Ist der linke Ausdruck WAHR, so wird der rechte ausgewertet, d.h. aus file werden die drei Zahlen gelesen und 'file' wird als Referenz zurück geliefert. 'file' kann danach in einen bool konvertiert werden und der liefert WAHR, wenn das Einlesen bisher gut gegangen ist.
-
Ich habe auch eine Frage zu dem Code:
Warum das:
template< char C > std::istream& Char( std::istream& in )statt dem:
std::istream& Char( std::istream& in, char C )?
-
neonew schrieb:
Warum das:
template< char C > std::istream& Char( std::istream& in )statt dem:
std::istream& Char( std::istream& in, char C )weil letzteres keine Manipulator-Funktion mehr ist. In diesem konkreten Fall müsste man schreiben
Char( Char( file >> arr[iZl][0], ',') >> arr[iZl][1], ',') >> arr[iZl][2]Die Alternative wäre ein Manipulator mit einem Parametern; das ist einfach mehr Code.
Notwendig wäre so was nur dann, wenn das genaue Dateiformat (in diesem Fall das Trenner-Zeichen) zur Compile-Zeit des lesenden Programms nicht feststeht - und das ist ziemlich ungewöhnlich.
-
std::istream& Char( std::istream& in ) { char c; if( in >> c && c != C ) in.setstate( std::ios_base::failbit ); return in; }sieht aber falsch aus...
wenn in z.B. leer iststd::istream& Char( std::istream& in ) { char c; in >> c; if( !in || c != C ) in.setstate( std::ios_base::failbit ); return in; }oder hab ich da nen denkfehler?
bb
-
unskilled schrieb:
hab ich da nen denkfehler?
Ja
- siehe auch http://www.c-plusplus.net/forum/viewtopic-var-p-is-1348863.html#1348863 .. immer wieder erstaunlich, wie schwierig so ein kleines harmloses logisches UND im if-Statement sein kann.
-
Hi
also, wie es funktionieren sollte ist mir jetz glaube ich soweit klar.
Das ganze soll natürlich auch eine schöne grafische oberfläche haben. Daher hab ich mir mit dem borland builder eine Form mit Button angelegt....
hab dann mal folgendes versucht://--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" #include <iostream> #include <fstream> TForm1 *Form1; // own---------------------------------------------------------------------- template< char C > std::istream& Charq( std::istream& in ) { char c; if( in >> c && c != C ) in.setstate( std::ios_base::failbit ); return in; } // own---------------------------------------------------------------------- //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { using namespace std; int arr[3][3]; ifstream file( "input.txt" ); if( !file.is_open() ) { cerr << "Fehler beim Oeffnen" << endl; } for( int iZl = 0; iZl < 3 && file >> arr[iZl][0] >> Charq <','> >> arr[iZl][1] >> Charq <','> >> arr[iZl][2]; ++iZl ) ; } //---------------------------------------------------------------------------Das Char musste ich umbenennen, da er mir immer einen Fehler gebracht hat.
Wenn ich den gezeigten Code compilieren will kommt jetzt folgender fehler:[C++ Fehler] E2299 Template-Spezialisierung kann aus '_fastcall operator >>(int,const Variant &)' nicht generiert werden
-
Werner_logoff schrieb:
unskilled schrieb:
hab ich da nen denkfehler?
Ja
- siehe auch http://www.c-plusplus.net/forum/viewtopic-var-p-is-1348863.html#1348863 .. immer wieder erstaunlich, wie schwierig so ein kleines harmloses logisches UND im if-Statement sein kann.naja - es war weniger das als das automatische failbit setzen des streams
Wenn !(in >> t), dann wird zwar das setstate() nicht mehr ausgeführt, aber das braucht's auch nicht, weil in dann sowieso schon den richtigen (="falschen"
) state hat.hat mir dann aber doch auf die sprünge geholfen^^
bb
-
datensalat schrieb:
[C++ Fehler] E2299 Template-Spezialisierung kann aus '_fastcall operator >>(int,const Variant &)' nicht generiert werden
Dein Compiler spinnt, der Typ Variant kommt doch gar nicht im Code vor!?
Ändere die for-Schleife in Zeile 34-36 nach
for( int iZl = 0; iZl < 3; ++iZl ) { file >> arr[iZl][0]; file >> Char<','>; file >> arr[iZl][1]; file >> Char<','>; file >> arr[iZl][2]; if( !file ) break; }und sage uns dann in welcher der Zeilen der Fehler auftritt.
-
In folgender Zeile kommt der Fehler:
file >> Charq<','>;
-
Das scheint ein BCB spezifisches Problem zu sein. Ich konnte das auch nachvollziehen. Ich habe folgenden Workaraound gefunden.
template< char C > std::istream& Charq( std::istream& in ) { char c; if( in >> c && c != C ) in.setstate( std::ios_base::failbit ); return in; } // own---------------------------------------------------------------------- //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { using namespace std; typedef std::istream& (*CharType)( std::istream& in ); CharType at = Charq<','>; int arr[3][3]; ifstream file( "input.txt" ); if( !file.is_open() ) { cerr << "Fehler beim Oeffnen" << endl; } for( int iZl = 0; iZl < 3 && file >> arr[iZl][0] >> at >> arr[iZl][1] >> at >> arr[iZl][2]; ++iZl ) ; }