Wie schreibe ich eine Ellipse?



  • Hallo!

    Wie schreibt man so eine Funktion wie printf? Die undefiniert viele Parameter der unterschiedlichsten Typen frisst?

    Ich muss sonst superoft das hier schreiben:

    CString strMsg;
    	strMsg.Format(_T("COrteSet::SetPlz(CString f_strPlz(==%s)) Anfang"), f_strPlz);
    	AfxMessageBox(strMsg); // Ist eigentlich was anderes, aber als Beispiel okay.
    

    Links? Suchbegriffvorschläge? Büchertipps? Ich finde nix. 😞



  • Guck mal im C++ Forum, da gabs erst vor kurzem ne Diskussion dürber.

    Devil



  • va_start

    dann die parameter..

    http://www.eckart-winkler.de/computer/varargs.htm

    ich glaube, du meinst sowas?



  • Guck mal ins MFC-Forum da hat's inzwischen schon zwei Beispiele (IIRC) für Messageboxen mit variabler Argumentenliste.



  • Danke, das werd ich erstmal absuchen. 🙂



  • Elises Link hat mir sehr geholfen, auch wenn ich es erstmal in "MFC" übersetzen musste.

    Aber nächste Frage: Wie übergebe ich eine Ellipse?



  • Aber vorher noch diese Frage:

    Was habe ich falsch gemacht?

    Hier die Funktion:

    void CLog::Log(CString f_strFormat, UINT f_nLogNummer, ...)
    {
    	va_list args;
    	TCHAR chAktuellesZeichen;
    	CString strReturn;
    
    	// Parameterabfrage initialisieren
    	va_start(args, f_strFormat);
    
    	// Für jedes Zeichen der Formatierung einmal...
    	for (int i = 0; i < f_strFormat.GetLength(); i++)
    	{
    		// Aktuelles Zeichen holen
    		chAktuellesZeichen = f_strFormat.GetAt(i);
    
    		// Wenn das aktuelle Zeichen kein % ist...
    		if (chAktuellesZeichen != _T('%'))
    		{
    			// An die Zielzeichenkette anhängen
    			strReturn += chAktuellesZeichen;
    		}
    		else
    		{
    			i++; // Nächstes Zeichen! Nicht schön aber hier sinnvoll.
    			chAktuellesZeichen = f_strFormat.GetAt(i);
    
    			CString strTemp;
    			// Formatkennzeichner abarbeiten
    			switch (chAktuellesZeichen)
    			{
    			// Funktioniert genauso wie bei printf
    			// Einzelne Buchstaben
    			case _T('d'):
    				strTemp.Format(_T("%d"), (int)va_arg(args, int));
    				break;
    			// Strings
    			case _T('s'):
    				strTemp.Format(_T("%s"), (char*)va_arg(args, char*)); // <-------- TILT!
    				break;
    			default:
    				strTemp = _T("%") + chAktuellesZeichen;
    			}
    
    			// Das Ergebnis hinten anhängen
    			strReturn += strTemp;
    		}
    	}
    
    	// Fertig mit Formatieren, also weitergeben
    	CLog::LogLine(strReturn, f_nLogNummer);
    
    	// Parameterabfrage beenden
    	va_end(args);
    }
    

    Das funktioniert auch einige Male ganz klasse, bis es in der markierten Zeile abstürtzt.
    Eigentlich ist es ja diese Zeile in der output.c

    while (i-- && *p)
    

    Dabei hat es im Durchlauf vorher mit dem selben Aufruf noch funktioniert...

    CLog::Log(_T("COrteView::AddLine(UINT f_nID(==%d), CString f_strPlz(==%s), CString f_strOrt(==%s)) Anfang"), LOG_NR_FUNKTION_BEGINN, f_nID, f_strPlz, f_strOrt);
    

    Funktioniert mit den Werten: 1, 0, "38100", "Braunschweig"
    Funktioniert nicht mit: 1, 1, "38300", "Wolfenbüttel"
    Der Wert, der gerade beim Absturz behandelt wird ist die Postleitzahl.

    Achja, hier noch die Fehlermeldung:
    ---------------------------
    Microsoft Visual C++
    ---------------------------
    Unbehandelte Ausnahme in Audiodatic_III.exe (MSVCRTD.DLL): 0xC0000005: Access Violation.
    ---------------------------
    OK
    ---------------------------

    Ideen? 😞



  • So, nach einigem Debuggen habe ich herausgefunden, dass der den zweiten Parameter auch noch in der Liste drin hat. Ich habe den also im Prinzip doppelt.

    So, und beim schreiben des Beitrags habe ich auch meinen Fehler gefunden:
    Es muss

    va_start(args, f_nLogNummer);
    

    statt

    va_start(args, f_strFormat);
    

    sein.
    Hoffe jetzt geht es.

    [Edit] Achja, den Datentyp habe ich auch noch entdeckt: va_list [/edit]


Anmelden zum Antworten