[gelöst] ifstream::fail() liefert false trotz vorherigem .setstate(ios_base::failbit)
-
Hallo miteinander.
Ich durchlaufe eine Datei in einer Schleife bis zu ihrem Ende und überprüfe innerhalb dieser Schleife auch, ob das Failbit gesetzt ist:
while(1) { if(ifsDeltaDatei.eof()) { ifsDeltaDatei.close(); break; } //hier Unterschiedsaufnahme deltaParsen(ifsDeltaDatei, delta); if(ifsDeltaDatei.fail()) { !ifsDeltaDatei.failbit; //nach Vector kopieren } }
Innerhalb der Funktion deltaParsen setze ich unter einer bestimmt Bedingung das Failbit:
... else if(token == "}") { // Objekttiefe nimmt ab if(!--iLevel) is.setstate(ios_base::failbit); return is; } ...
In der aufrufenden Funktion prüfe ich dann, ob das Failbit gesetzt ist (Zeile 10 im obersten Codeausschnitt):
if(ifsDeltaDatei.fail()) { !ifsDeltaDatei.failbit; //nach Vector kopieren }
Ich habe diese Situation (Failbit über eine Referenz in einer separaten Funktion setzen) dann auch mal in einem "Miniprogramm" getestet, um einen evtl. Seiteneffekt ausschließen zu können. In diesem Testprogramm funktionierte das. Auch, wenn ich diese Prüfung in die aufgerufenen Funktion verlagere, geht es.
Es liegt auch nicht daran, dass ich den Filestream als std::istream& an die aufgerufene Funktion übergebe.
Danke fürs Reinschauen
Gruß
Kai
-
Hi,
du bist erstens im falschen Forum und zweitens solltes Du kompletten code posten, mit dem der Fehler reproduzierbar ist.
!ifsDeltaDatei.failbit;
Welchen Sinn hat dieses Statement?
VG
-
mgaeckler schrieb:
Hi,
du bist erstens im falschen Forum
Ich weiß. Was ich nicht weiß ist, wie ich es woanders hinschieben kann.
mgaeckler schrieb:
und zweitens solltes Du kompletten code posten, mit dem der Fehler reproduzierbar ist.
Kann ich gerne machen.
mgaeckler schrieb:
!ifsDeltaDatei.failbit;
Welchen Sinn hat dieses Statement?
Damit möchte ich das Failbit wieder umkehren. Alternative wäre wohl ifsDeltaDatei.clear().
-
_Bongo schrieb:
mgaeckler schrieb:
Hi,
du bist erstens im falschen Forum
Ich weiß. Was ich nicht weiß ist, wie ich es woanders hinschieben kann.
Das muß ein Admin machen und Du überlegst es Dir in Zukunft vorher.
_Bongo schrieb:
mgaeckler schrieb:
!ifsDeltaDatei.failbit;
Welchen Sinn hat dieses Statement?
Damit möchte ich das Failbit wieder umkehren. Alternative wäre wohl ifsDeltaDatei.clear().
Dumm nur, daß failbit eine Konstante ist. Bekommst Du vom Compiler keine Warnung?
VG Martin
-
mgaeckler schrieb:
Das muß ein Admin machen und Du überlegst es Dir in Zukunft vorher.
Der Grund, warum ich das zunächst hier hinein geschrieben habe ist der, dass ich zurzeit mit der WinAPI arbeite. Mir ist dann etwas später eingefallen, dass das hier doch eher ein Fall für den C++-Standard ist. Ich habe vor mehreren Stunden eine Mail an das Team, mit der Bitte um Verschiebung ins richtige Forum, geschrieben.
mgaeckler schrieb:
Dumm nur, daß failbit eine Konstante ist. Bekommst Du vom Compiler keine Warnung?
Nein, der Compiler meckert keineswegs. Eigentlich müsste das so lauten:
ifstream::setstate(!ios_base::failbit);
Aber wie bereits gesagt, normalerweise setzt man diese Flags mit ifstream::clear() zurück.
Ich werde mal den Code posten.
Gruß
Kai
-
_Bongo schrieb:
Nein, der Compiler meckert keineswegs.
Warnungen ausgeschaltet? Ich hätte jetzt sowas wie "Code has no effect" erwartet.
_Bongo schrieb:
Eigentlich müsste das so lauten:
ifstream::setstate(!ios_base::failbit);
Wer hat Dir das beigebracht? Wenn Du nur ein Bit löschen willst, geht das so:
stream.clear( rdstate() & ~failbit );
setstate fügt nur neue Flags hinzu. !failbit ist 0, daher wird auch nichts hinzugefügt.
VG
-
delta.h
#include <Windows.h> #ifndef STR_FSTR #define STR_FSTR #include <string> #include <fstream> #endif using namespace std; struct strctDelta { string strChangeTyp; string strZiel; }; class CDelta { private: string strObjName, strObjTyp, strObjID; int iDeltaZaehler; vector<strctDelta> vecDelta; public: CDelta() : iDeltaZaehler(0) { } friend istream& deltaParsen(istream&, CDelta&); };
Hauptprogramm
//#include "export.h" #include "delta.h" #include <CommCtrl.h> #include <vector> #define ID_BN_ABGLEICH 0 #define ID_GB_KONFIGLISTE 1 #define ID_LV_KONFIGLISTE 2 #define ID_LV_DELTALISTE 3 #define ID_BN_TEST 10 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //int konfigEinlesen(vector<CExport>&); //int listviewSpaltenAufbau(HWND&, int); //int listviewFuellen(HWND&, int, vector<CExport>&); istream& deltaParsen(istream&, CDelta&); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iShow) { MSG msg; WNDCLASS wndClass; HWND hwnd; wchar_t wcAppName[] = L"Abgleichtool"; wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = wcAppName; if(!RegisterClass(&wndClass)) { MessageBox(NULL, L"Fehler bei Klassenregistrierung", L"Fehler", MB_ICONERROR); return 0; } hwnd = CreateWindow(wcAppName, wcAppName, WS_OVERLAPPEDWINDOW, 10, 10, 1420, 780, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iShow); UpdateWindow(hwnd); while(true) { if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else { //Leerlauf } } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; //HDC hdc; LVITEM lvItem; ifstream ifsDeltaDatei; CDelta delta; //static vector<CExport> vecKonfigListe; //static vector<CDelta> vecDeltaInfo; static HWND hwndLVKonfigListe, hwndBTVergleich, hwndBTTest, hwndGBKonfigListe; static int iWinBreite, iWinHoehe, iVerglQuelle, iVerglZiel; //tmporäre Variablen static wchar_t dummy[100]; static int iDummy1, iDummy2; static string strDummy; switch(message) { case WM_CREATE: iVerglQuelle = iVerglZiel = -1; // temp. Knopf für Ausführung des Vergleichs: Anfang hwndBTVergleich = CreateWindow( L"Button", L"Abgleich", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON, 10, 10, 140, 30, hwnd, (HMENU) ID_BN_ABGLEICH, ((LPCREATESTRUCT) lParam)->hInstance, NULL); // temp. Knopf für Ausführung des Vergleichs: Ende // temp. Knopf zum Testen des Parsens: Anfang hwndBTTest = CreateWindow( L"Button", L"Parsen", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON, 150, 10, 140, 30, hwnd, (HMENU) ID_BN_TEST, ((LPCREATESTRUCT) lParam)->hInstance, NULL); // temp. Knopf zum Testen des Parsens: Ende // Rahmen für Konfigliste aufbauen: Anfang hwndGBKonfigListe = CreateWindow(L"Button", NULL, BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 10, 100, 1380, 250, hwnd, (HMENU) ID_GB_KONFIGLISTE, ((LPCREATESTRUCT) lParam)->hInstance, NULL); // Rahmen für Konfigliste aufbauen: Ende // Konfigliste aufbauen: Anfang hwndLVKonfigListe = CreateWindow( L"SysListView32", NULL, WS_CHILD | WS_VISIBLE | LVS_REPORT, 20, 120, 1360, 220, hwnd, (HMENU) ID_LV_KONFIGLISTE, ((LPCREATESTRUCT) lParam)->hInstance, NULL); // Konfigliste aufbauen: Ende /*if(konfigEinlesen(vecKonfigListe) != 0) { MessageBox(hwnd, L"Datei fehlt", L"Fehler", MB_ICONERROR); return 1; } listviewSpaltenAufbau(hwndLVKonfigListe, ID_LV_KONFIGLISTE); listviewFuellen(hwndLVKonfigListe, ID_LV_KONFIGLISTE, vecKonfigListe); */ return 0; case WM_PAINT: BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); return 0; case WM_SIZE: iWinBreite = LOWORD(lParam); iWinHoehe = HIWORD(lParam); return 0; case WM_NOTIFY: switch(((LPNMHDR) lParam)->code) { case NM_DBLCLK: MessageBox(hwnd, L"ListView-Doppelklick-Ereignis", L"TEST", MB_OK); break; case NM_CLICK: memset(&lvItem, 0, sizeof(LVITEM)); lvItem.mask = LVIF_TEXT; lvItem.iItem = iVerglQuelle; lvItem.iSubItem = 2; if(iVerglQuelle != iVerglZiel) { lvItem.pszText = L""; SendMessage(hwndLVKonfigListe, LVM_SETITEM, 0, (LPARAM) &lvItem); } iVerglQuelle = ((LPNMITEMACTIVATE) lParam)->iItem; lvItem.iItem = iVerglQuelle; lvItem.pszText = L"Quelle"; SendMessage(hwndLVKonfigListe, LVM_SETITEM, 0, (LPARAM) &lvItem); if(iVerglQuelle == iVerglZiel) iVerglZiel = -1; break; case NM_RCLICK: memset(&lvItem, 0, sizeof(LVITEM)); lvItem.mask = LVIF_TEXT; lvItem.iItem = iVerglZiel; lvItem.iSubItem = 2; if(iVerglZiel != iVerglQuelle) { lvItem.pszText = L""; SendMessage(hwndLVKonfigListe, LVM_SETITEM, 0, (LPARAM) &lvItem); } iVerglZiel = ((LPNMITEMACTIVATE) lParam)->iItem; lvItem.iItem = iVerglZiel; lvItem.pszText = L"Ziel"; SendMessage(hwndLVKonfigListe, LVM_SETITEM, 0, (LPARAM) &lvItem); if(iVerglZiel == iVerglQuelle) iVerglQuelle = -1; break; } return 0; case WM_COMMAND: switch(LOWORD(wParam)) { case ID_BN_ABGLEICH: if(iVerglQuelle == -1 || iVerglZiel == -1) // Auswahl fehlt { MessageBox(hwnd, L"eine Auswahl fehlt", L"Fehler", MB_ICONERROR); break; } // Export aller Objekte aus der Quell-Version //vecKonfigListe[iVerglQuelle].objektAktion("ExportObjects", eObjekt::TABLE, "5146000__5146999", \ "ID=5146000..5146999;Type=Table", eFormat::TXT); // Export aller Objekte aus der Ziel-Version //vecKonfigListe[iVerglZiel].objektAktion("ExportObjects", eObjekt::TABLE, "5146000__5146999", \ "ID=5146000..5146999;Type=Table", eFormat::TXT); // Abgleich zwischen den Objekte ausführen //vecKonfigListe[iVerglQuelle].NAVVergleich(vecKonfigListe[iVerglZiel]); // Parsen der DELTA-Datei /*ifsDeltaDatei.open("DELTA.txt", ios_base::in); if(!ifsDeltaDatei.is_open()) { MessageBox(hwnd, L"Vergleich ergab keine Unterschiede", L"Fehler", MB_ICONERROR); break; } while(1) { if(ifsDeltaDatei.eof()) break; getline(ifsDeltaDatei, strDummy); //hier Unterschiedsaufnahme }*/ break; case ID_BN_TEST: ifsDeltaDatei.open("DELTA.txt", ios_base::in); if(!ifsDeltaDatei.is_open()) { MessageBox(hwnd, L"Vergleich ergab keine Unterschiede", L"Fehler", MB_ICONERROR); break; } while(1) { if(ifsDeltaDatei.eof()) { ifsDeltaDatei.close(); break; } //hier Unterschiedsaufnahme deltaParsen(ifsDeltaDatei, delta); // vorher: ifsDeltaDatei >> deltaParsen / jetzt weitere Parameter delta if(ifsDeltaDatei.fail()) { !ifsDeltaDatei.failbit; //nach Vector kopieren } } break; } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } /*int konfigEinlesen(vector<CExport>& prefVecKonfigListe) { ifstream ifKonfDatei("exportKonfig.txt"); if(ifKonfDatei.is_open()) { CExport expKonfig; while(!ifKonfDatei.eof()) { ifKonfDatei >> expKonfig; if(!ifKonfDatei.fail()) prefVecKonfigListe.insert(prefVecKonfigListe.end(), expKonfig); } ifKonfDatei.close(); } else return 1; return 0; } */ /*int listviewSpaltenAufbau(HWND& prefListView, int pintListe) { HFONT hFont; LVCOLUMN lvColumn; hFont = CreateFont(16, 13, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, 0, 33, L"Arial"); SendMessage(prefListView, WM_SETFONT, (WPARAM) hFont, (LPARAM) TRUE); DeleteObject(hFont); memset(&lvColumn, 0, sizeof(LVCOLUMN)); lvColumn.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_FMT | LVCF_SUBITEM; SendMessage(prefListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, (LPARAM) LVS_EX_FULLROWSELECT); SendMessage(prefListView, LVM_SETVIEW, (WPARAM) LV_VIEW_DETAILS, 0); switch(pintListe) { case ID_LV_KONFIGLISTE: // Spalte 1 lvColumn.cx = 150; lvColumn.iSubItem = 0; lvColumn.pszText = L"Konfig-ID"; lvColumn.fmt = LVCFMT_LEFT; SendMessage(prefListView, LVM_INSERTCOLUMN, 0, (LPARAM) &lvColumn); // Spalte 2 lvColumn.cx = 400; lvColumn.iSubItem = 1; lvColumn.pszText = L"Beschreibung"; lvColumn.fmt = LVCFMT_LEFT; SendMessage(prefListView, LVM_INSERTCOLUMN, 1, (LPARAM) &lvColumn); // Spalte 3 lvColumn.cx = 100; lvColumn.iSubItem = 2; lvColumn.pszText = L"Status"; lvColumn.fmt = LVCFMT_CENTER; SendMessage(prefListView, LVM_INSERTCOLUMN, 2, (LPARAM) &lvColumn); break; case ID_LV_DELTALISTE: break; } return 0; } */ /*int listviewFuellen(HWND& prefListView, int pintListe, vector<CExport>& prefVecKonfigListe) { LVITEM lvItem; vector<CExport>::iterator iter; int i; wchar_t wcBuffer[100]; memset(&lvItem, 0, sizeof(LVITEM)); lvItem.mask = LVIF_TEXT; lvItem.cchTextMax = 50; switch(pintListe) { case ID_LV_KONFIGLISTE: SendMessage(prefListView, LVM_DELETEALLITEMS, 0, 0); // Listen-Einträge löschen // Schleife: Anfang (Konfigdatei einlesen) for(i = 0, iter = prefVecKonfigListe.begin(); iter != prefVecKonfigListe.end(); iter++, i++) { // Spalte 1 lvItem.iItem = i; lvItem.iSubItem = 0; wcscpy_s(wcBuffer, iter->holeKonfigNameW().c_str()); lvItem.pszText = wcBuffer; SendMessage(prefListView, LVM_INSERTITEM, 0, (LPARAM) &lvItem); // Spalte 2 lvItem.iSubItem = 1; wcscpy_s(wcBuffer, iter->holeDatenbankW().c_str()); lvItem.pszText = wcBuffer; SendMessage(prefListView, LVM_SETITEM, 0, (LPARAM) &lvItem); // Spalte 3 lvItem.iSubItem = 2; lvItem.pszText = L""; SendMessage(prefListView, LVM_SETITEM, 0, (LPARAM) &lvItem); } // Schleife: Ende break; case ID_LV_DELTALISTE: break; } return 0; } */ // ******************* DELTA-Datei parsen (Anfang) ******************* template <char ATag> istream& shiftToChar(istream& is) { char cTag; if(is >> cTag && cTag != ATag) is.putback(cTag); return is; } template<char ATag, char ETag> struct strctToken { private: string& token; public: strctToken(string& strrefToken) : token(strrefToken) { } friend istream& operator>>(istream& is, strctToken& tok) { return getline(is >> shiftToChar<ATag>, tok.token, ETag); } }; istream& deltaParsen(istream& is, CDelta& delta) { string token, strTmpBuffer; static string strStatus; static strctDelta strctDeltaBuffer; static bool bChng, bCode, bSucheZiel; static int iLevel; is >> token; if(token == "OBJECT") { bChng = bCode = bSucheZiel = false; is >> strStatus >> strctToken<'"','"'>(delta.strObjName) >> strctToken<'(',' '>(delta.strObjTyp); if( strStatus == "Table" || strStatus == "Report" || strStatus == "Codeunit" || strStatus == "XMLport" || strStatus == "Page") { // Objekt nur in Ziel vorhanden } else getline(is, delta.strObjID, ')'); } else if(token == "CHANGES") { bChng = true; return is; } else if(token == "CODE") { bChng = false; bCode = true; return is; } else if(token == "{") { // Objekttiefe nimmt zu iLevel++; return is; } else if(token == "}") { // Objekttiefe nimmt ab //if(!--iLevel) // is.setstate(ios_base::failbit); iLevel--; return is; } if(bChng) { if( token == "CodeModification" || token == "Deletion" || token == "Insertion" || token == "Modification" || token == "PropertyDeletion" || token == "PropertyInsertion" || token == "PropertyModification" || token == "PropertyModification;" || token == "Move") { if(token.substr(token.length() - 1, 1) == ";") token.pop_back(); strctDeltaBuffer.strChangeTyp = token; delta.iDeltaZaehler++; bSucheZiel = true; return is; } if(bSucheZiel) { if(strctDeltaBuffer.strChangeTyp == "CodeModification") // bei Codeänderungen steht "Target" nicht hinter dem ersten Semikolon { //Ziel erfassen if(token.substr(0, strlen("Target=")) == "Target=") { strctDeltaBuffer.strZiel = token.substr(strlen("Target="), token.length()); delta.vecDelta.push_back(strctDeltaBuffer); bSucheZiel = false; } } else { // keine CodeModification //Ziel erfassen if(token.substr(0, strlen(";Target=")) == ";Target=") { strctDeltaBuffer.strZiel = token.substr(strlen(";Target="), token.length()); getline(is, strTmpBuffer, '\n'); strctDeltaBuffer.strZiel += strTmpBuffer; delta.vecDelta.push_back(strctDeltaBuffer); bSucheZiel = false; } else { if(token.substr(0, strlen("Property=")) == "Property=") { strctDeltaBuffer.strZiel = token.substr(strlen("Property="), token.length()); getline(is, strTmpBuffer, '\n'); strctDeltaBuffer.strZiel += strTmpBuffer; delta.vecDelta.push_back(strctDeltaBuffer); bSucheZiel = false; } } return is; } } } return is; } // ******************* DELTA-Datei parsen (Ende) *******************
Ich habe jetzt einige Anweisungen auskommentiert, weil sie erstens nichts mit dem Problem zutun haben und das zweitens ein bisschen zuviel wäre.
-
Wenn Du das Setzen des failbits auskommentiert, darfst Du Dich nicht wundern, wenn es nicht gesetzt wird.
-
mgaeckler schrieb:
Wer hat Dir das beigebracht? Wenn Du nur ein Bit löschen willst, geht das so:
stream.clear( rdstate() & ~failbit );
setstate fügt nur neue Flags hinzu. !failbit ist 0, daher wird auch nichts hinzugefügt.
VG
Ich habe mir das unter http://en.cppreference.com/w/cpp/io/basic_ios/setstate angeschaut. Bin zwar nicht der große Englisch-Hoschi, aber ich glaube setstate heißt soviel wie Status setzen und nicht Flag hinzufügen.
-
Ich zitiere Deine Quelle
Sets the stream error flags state in addition to currently set flags. Essentially calls clear(rdstate() | state). May throw an exception.
ParametersHervorhebung von mir.
VG
-
mgaeckler schrieb:
Wenn Du das Setzen des failbits auskommentiert, darfst Du Dich nicht wundern, wenn es nicht gesetzt wird.
Das Setzen habe ich während meiner Versuche es ans Laufen zu bringen mal auskommentiert. Nimm den Kommentar wieder raus - es funktioniert nicht. Das Ergebnis der Abfrage die in der aufrufenden Funktion dem Funktionsaufruf folgt lautet: Failbit nicht gesetzt
-
mgaeckler schrieb:
Ich zitiere Deine Quelle
Sets the stream error flags state in addition to currently set flags. Essentially calls clear(rdstate() | state). May throw an exception.
ParametersHervorhebung von mir.
VG
Das habe ich auch so verstanden. Aber was ist mit dem Beispiel-Code? Da wird das auch so gemacht. Ausserdem habe ich es ja auch schon in einem kurzen Testprogramm ausprobiert. Da übergebe ich ein ifstream-Objekt an eine Funktion, setze dort dieses Flag, der Prozessor springt zurück hinter den Aufruf und das Bit ist gesetzt.
Nur im eigentlichen Programm ist etwas anders und ich weiß nicht was.
-
_Bongo schrieb:
mgaeckler schrieb:
Ich zitiere Deine Quelle
Sets the stream error flags state in addition to currently set flags. Essentially calls clear(rdstate() | state). May throw an exception.
ParametersHervorhebung von mir.
VG
Das habe ich auch so verstanden. Aber was ist mit dem Beispiel-Code? Da wird das auch so gemacht. Ausserdem habe ich es ja auch schon in einem kurzen Testprogramm ausprobiert. Da übergebe ich ein ifstream-Objekt an eine Funktion, setze dort dieses Flag, der Prozessor springt zurück hinter den Aufruf und das Bit ist gesetzt.
Nur im eigentlichen Programm ist etwas anders und ich weiß nicht was.
Ich zitiere nochmal:
#include <iostream> #include <sstream> int main() { std::ostringstream stream; if (!stream.fail()) { std::cout << "stream is not fail\n"; } stream.setstate(std::ios_base::failbit); if (stream.fail()) { std::cout << "now stream is fail\n"; } if (!stream.good()) { std::cout << "and stream is not good\n"; } }
Wo siehst Du hier das logische NOT (!) beim Aufruf von setstate ?
-
Darüber mache ich mir Gedanken, wenn der EIP des Prozessors mal in den Zweig mit der Abfrage
if(ifsDeltaDatei.fail())
verzweigt.
Mein Problem ist, dass das was ich da vorhabe in einem Testprogramm funktioniert und in meinem "richtigen" Programm nicht - der essentielle Code ist derselbe.
In Zeile 12 deines Posts wird doch das Bit gesetzt. Und danach springt der Prozessor auch in die Verzweigung die ich oben notiert habe. Verlagere ich die Abfrage ausserhalb der setzenden Funktion, verzweigt er nicht mehr.
-
Was ich sehe, sieht in Ordnung aus. Lann es sein, daß Deine Funktion deltaParsen einfach zu früh beendet?
else if(token == "}") { // Objekttiefe nimmt ab if(!--iLevel) is.setstate(ios_base::failbit); iLevel--; return is; }
Diese Teil bricht ab sobald das erste } gefunden wurde. Egal, was in iLevel drinnen steht. Ist das wirklich Absicht? Außerdem decrementierst Du iLevel zweimal.
EDIT: Wo wird eigentlich iLevel initialisiert?
VG
-
Das zweite Dekrement steht da nur, weil ich das eine mal auskommentiert habe. Ich bin mit dem Debugger dadurch. Die Zeile in der das Bit gesetzt wird, wird definitiv durchlaufen. Nach dem Return in diesem Zweig, wird in der aufrufenden Funktion die nächste Zeile über die Funktion deltaParsen verarbeitet. Aber vorher wird halt auf das gesetzte Bit geprüft.
iLevel ist eine static-Variable.
-
_Bongo schrieb:
Das zweite Dekrement steht da nur, weil ich das eine mal auskommentiert habe. Ich bin mit dem Debugger dadurch. Die Zeile in der das Bit gesetzt wird, wird definitiv durchlaufen. Nach dem Return in diesem Zweig, wird in der aufrufenden Funktion die nächste Zeile über die Funktion deltaParsen verarbeitet. Aber vorher wird halt auf das gesetzte Bit geprüft.
iLevel ist eine static-Variable.
Wie soll man in Deinen Code 'nen Fehler finden, wenn Du nicht den Code postest, der funktionieren soll?
-
Du hast bereits das auskommentiert was ich fälschlicher Weise auskommentiert gelassen habe. Alles andere was auskommentiert ist, hat nix mit dem Fehler hier zutun.
-
_Bongo schrieb:
Du hast bereits das auskommentiert was ich fälschlicher Weise auskommentiert gelassen habe. Alles andere was auskommentiert ist, hat nix mit dem Fehler hier zutun.
Also: Wenn Deine nicht initialisierte Variable iLevel zufällig 1 enthält während ein } gefunden wurde, setzt Du das failbit decrementiert möglicherweiser nochmal iLevel und kehrt ansonsen SOFORT zurück. Der Aufrufer überprüft dann auch SOFORT das failbit.
Richtig?
-
Statische Variablen werden nicht zufällig mit irgendwas initialisiert. Statische Variablen werden immer mit 0 initialisiert.
-
_Bongo schrieb:
Statische Variablen werden nicht zufällig mit irgendwas initialisiert. Statische Variablen werden immer mit 0 initialisiert.
OK, hast recht, find ich trotzdem nicht schön.