[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.
    Parameters

    Hervorhebung 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.
    Parameters

    Hervorhebung 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.
    Parameters

    Hervorhebung 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.


Anmelden zum Antworten