sprintf, % und und eine Menge Ratlosigkeit



  • Hallo zusammen,
    nachdem ich jetzt ungefähr ein Dutzend Beiträge zum Maskieren von % durchgelesen habe und feststelle, dass es nicht so direkt sondern nur fast mein Problem betrifft, muss ich jetzt doch einmal an euch herantreten um meine Frage loszuwerden.

    Seit ein paar Monaten nun schon arbeite ich mich an C heran, soweit mit wachsendem Erfolg. Gestern jedoch bin ich an etwas hängengeblieben, für das ich keine Lösung parat habe.

    Und zwar will ich mittels sprintf in ein char-array eine Reihe von Bytes schreiben um damit eine binäre Telemetrie zu ermöglichen. Dies klappt auch soweit wunderbar, bis auf dieses kleine, fiese % (ASCII-Char 37). Wenn meine Variable diesen Wert hat, dann tut sprintf sie scheinbar einfach übergehen anstellen den Wert in mein char-Array zu setzen.

    Also, Beispiel:

    int strangething = 0x25; 
    char buffer [50]; 
    sprintf(buffer,"Das hier klappt nicht:%c...",strangething); 
    
    strangething = 0x41;
    
    sprintf(buffer,"Das hier klappt:%c...",strangething);
    

    So würde im ersten Fall da stehen:

    "Das hier klappt nicht:..."

    und im zweiten:

    "Das hier klappt:A..."

    Ich nehme an, sprintf versucht, das % zu interpretieren. Aber ich bin mir so gar nicht sicher, wie ich das verhindern kann. Vielleicht weiss jemand von euch rat? Wäre auf jeden Fall sehr dankbar, da mich das schon ein paar Stunden Schlaf gekostet hat 😕



  • sprintf(s,"%%");
    


  • sprintf ist da nicht anders als printf.
    Kannst du auch nachlesen: http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/



  • Neolyth schrieb:

    Ich nehme an, sprintf versucht, das % zu interpretieren.

    Tut es aber nicht, da es nicht im Formatstring steht. Ich tippe auf Betriebsblindheit bei dir. Vielleicht gibts du buffer mit printf(buffer) aus?



  • Ja, Betriebsblindheit mag sein 🙂

    _matze schrieb:

    sprintf(s,"%%");
    

    So ähnlich hatte ich das schon versucht, mit

    sprintf(buffer,"%%c",strangething);
    

    Da spuckt mir der Compiler aber lapidar aus, dass die Anzahl Argumente so nicht stimmt. Dazu muss ich evtl. erwähnen, dass es nicht unbedingt ein Standard-C Compiler ist, sondern einer von Microchip 😕

    Wenn ich das im Büro mit meinem cpp-compiler versuche, dann funktioniert das natürlich wunderbar. Aber das dsPic-Teil, mit dem ich mich rumärgere, geht halt nur mit dem Microchip-C. Und debugging ist auch so eine Sache.



  • Neolyth schrieb:

    Ja, Betriebsblindheit mag sein 🙂

    _matze schrieb:

    sprintf(s,"%%");
    

    So ähnlich hatte ich das schon versucht, mit

    sprintf(buffer,"%%c",strangething);
    

    Da spuckt mir der Compiler aber lapidar aus, dass die Anzahl Argumente so nicht stimmt.

    Du musst Dich auch entscheiden:
    So wie hier steht in Deinem Ergebnisstring am Ende: %c
    Du gibst aber noch ein Argument (strangething) mit - wo soll das denn hin? Wenn das noch in den String soll, brauchst Du ja mindestens ein interpretierbares % im Formatstring.



  • Neolyth schrieb:

    Ja, Betriebsblindheit mag sein 🙂

    Ich meinte das nicht als Witz. Wie kontrollierst du denn den Inhalt von buffer , was lässt dich glauben, dass da das Prozent fehlt?



  • Neolyth schrieb:

    So ähnlich hatte ich das schon versucht

    Genau, so ähnlich. 😉 Wenn du ein '%' im String haben willst, ist meine Variante die Lösung nach Doku. Die Variante mit %c funktioniert aber eigentlich auch.



  • Um jetzt nochmal auf die eigentliche Frage einzugehen (:D)

    int strangething = '%';
    char buffer [50];
    sprintf(buffer,"Das hier klappt 100%%ig sicher: %c",strangething);
    


  • _matze schrieb:

    Wenn du ein '%' im String haben willst, ist meine Variante die Lösung nach Doku.

    Nicht ganz. Deine Variante ist die Lösung, wenn der Formatstring ein %-Zeichen enthält, das ausgegeben werden soll, statt als Formatierungszeichen interpretiert zu werden.



  • Bashar schrieb:

    Nicht ganz. Deine Variante ist die Lösung, wenn der Formatstring ein %-Zeichen enthält, das ausgegeben werden soll, statt als Formatierungszeichen interpretiert zu werden.

    Ja, war das nicht die Aufgabe? Ach so, falls es soll dynamisch sein, ist die %c-Variante eben die richtige.



  • _matze schrieb:

    Bashar schrieb:

    Nicht ganz. Deine Variante ist die Lösung, wenn der Formatstring ein %-Zeichen enthält, das ausgegeben werden soll, statt als Formatierungszeichen interpretiert zu werden.

    Ja, war das nicht die Aufgabe?

    Nein, das Prozent steckt in strangething, nicht im Formatstring. Hast du das erste Posting überlesen?



  • Bei mir klappt ohne Probleme:

    Neolyth schrieb:

    int strangething = 0x25; 
    char buffer [50]; 
    sprintf(buffer,"Das hier klappt nicht:%c...",strangething); 
    printf("%s", buffer);
    


  • Soo, ich merk schon 🙂

    Aaaalso, feststellen, dass es irgendwo hakt tu ich bei der Ausgabe. Kurz und knapp, ich schicke dieses char-array an eine Funktion serial_output:

    void serial_output( char* format, ... )
    {
    	va_list arglist ;
    
    	va_start(arglist, format) ;
    
    	int start_index = end_index ;
    	int remaining = SERIAL_BUFFER_SIZE - start_index ;
    
    	if (remaining > 1)
    	{
    		int wrote = vsnprintf( (char*)(&serial_buffer[start_index]), (size_t)remaining, format, arglist) ;
    		end_index = start_index + wrote;
    	}
    
    	va_end(arglist);
    
    	return ;
    }
    

    Dann hab ich noch ein Interrupt, das von Zeit zu Zeit aufgerufen wird:

    void __attribute__((__interrupt__,__no_auto_psv__)) _U2TXInterrupt(void)
    {
    	indicate_loading_inter ;
    	interrupt_save_set_corcon ;
    
    	_U2TXIF = 0 ; // clear the interrupt 
    
    	int txchar = serial_callback_get_byte_to_send() ;
    
    	if ( txchar != -1 )
    	{
    		U2TXREG = (unsigned char)txchar ;
    	}
    
    	interrupt_restore_corcon ;
    	return ;
    }
    

    Und die dazugehörige serial_callback

    int serial_callback_get_byte_to_send(void)
    {
    	unsigned char txchar = serial_buffer[ sb_index++ ] ;
    
    	if ( txchar )
    		return txchar ;
    	}
    	else
    	{
    		sb_index = 0 ;
    		end_index = 0 ;
    	}
    
    	return -1;
    }
    

    Das geht dann über ein UART raus, auf der anderen Seite in mein Laptop rein. Da kuck ich dann mit hterm (oder ähnlichem) was ankommt, und dieses '%' ist nie dabei. Es ist auch kein Platzhalter da oder ähnliches, es scheint einfach so als ob sprintf dieses byte übergeht und beim nächsten weitermacht...

    Ich sollte vielleicht anmerken dass das alles natürlich nicht auf meinem Mist gewachsen ist, das ist zum Teil copy-paste aus der Microchip-Doku und andere Hilfestellungen.



  • Neolyth schrieb:

    Aaaalso, feststellen, dass es irgendwo hakt tu ich bei der Ausgabe. Kurz und knapp, ich schicke dieses char-array an eine Funktion serial_output:

    Ich seh jetzt nicht ganz eindeutig die Verbindung zu dem Problem. Versteh ich das richtig, du machst in etwa folgendes?

    int strange = '%';
    char buffer[50];
    sprintf(buffer, 'Achtung ein Prozent: %c', strange);
    serial_output(buffer);
    


  • Belli schrieb:

    Bei mir klappt ohne Probleme:

    Neolyth schrieb:

    int strangething = 0x25; 
    char buffer [50]; 
    sprintf(buffer,"Das hier klappt nicht:%c...",strangething); 
    printf("%s", buffer);
    

    Ja, wie gesagt, im Büro mit meinem schönen Standard-Compiler klappt das auch. Das macht es nicht gerade einfacher 😞



  • Compiler hin oder her.
    Neolyth, entscheiden ist doch machst du es so

    serial_out(buffer);
    

    oder so

    serial_out("%s", buffer);
    

    beantworte doch bitte einfach die Frage.
    Oder überleg dir selbst was der unterschied ist.



  • Ja, ehr, ich mache es so:

    serial_output(buffer);
    

    Was dann ja die schon erwähnte Funktion aufruft...



  • Neolyth schrieb:

    Ja, ehr, ich mache es so:

    serial_output(buffer);
    

    Was dann ja die schon erwähnte Funktion aufruft...

    Also ist das Prozentzeichen im Formatstring von vsnprintf und wird als Formatspecifier interpretiert. Wenn ich mich mal eben selbst zitieren dürfte:

    Ich tippe auf Betriebsblindheit bei dir. Vielleicht gibts du buffer mit printf(buffer) aus?

    Mach es entweder mit serial_output("%s", buffer) oder gleich serial_output("Ein tolles Prozentzeichen: %c", strangething) .



  • Und serial_output erwartet als ersten Parameter einen? Richtig: Format-String.
    Und ein Prozent im Format-String bedeutet was? Richtig: Es wird interpretiert.

    Also, wenn Du jetzt mit sprintf einen String zusammengesetzt hast, der im Ergebnis ein Prozentzeichen enthält, was passiert dann, wenn Du wiederum sprintf (hier serial_output) mit jenem Ergebnis als Formatstring aufrufst?


Log in to reply