RGB-Dez nach RGB-Web umwandeln: Wie ersetze ich sprintf mit std::String?



  • Hallole mal wieder.
    Ich stehe gerade auf dem Schlauch.

    Ich möchte einen RGB-Dezimalwert in RGB Web-Wert umwandeln.
    Also ich bekomme von einer Software den Wert 8421631 als dezimal RGB Wert und möchte den dann als Webfarbe #ff8080 umwandeln.

    Ich gehe bisher so vor:

    DWORD farbe_dez;
    char farbe_webhex[16];
    
    farbe_dez=8421631;//Wird hier dann innerhalb einer Funktion natürlich ersetzt.
    
    sprintf(farbe_webhex,"#%x",farbe_dez);
    

    Heraus kommt hier: #8080ff.
    So weit so gut.

    Dabei habe ich aber noch ein Problemchen:

    1. Die Farben sind verdreht, fürs Web sollte ff8080 herauskommen.
    2. Ich arbeite mit STL Strings,also der Übergabewert(farbe_dez) wird nachher ein std::string sein.

    Wie kann ich die Farben verdrehen und vor allem:
    Wie kann ich diese Umwandlung möglichst einfach mit std::string erzeugen?

    Ich hoffe ich habe mein PRoblem(chen) deutlich darstellen können und freue mich auf Antwort, Mondmann



  • was sprichst gegen primitives:

    ((farbe_dez&0xff)<<16)|(farbe_dez&0xff00)|((farbe_dez&0xff0000)>>16)
    

    ?



  • Mondmann schrieb:

    Wie kann ich die Farben verdrehen...

    z.b. mit 'htonl()'.
    htonl() macht z.b. auf x86-kisten eine vertauschung, auf big-endian maschinen macht es nichts. der code von rapso verdreht dagegen immer.

    Mondmann schrieb:

    Wie kann ich diese Umwandlung möglichst einfach mit std::string erzeugen?

    irgendwie mit 'stringstream' und '<< std::hex', aber ich glaube sprintf ist einfacher.
    🙂



  • Grüzi !

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    #define RGB_MAX 0xFFFFFF
    
    string convert( unsigned int farbe_dez )
    {
    	char rgb[9] = "";
    
    	if ( farbe_dez > RGB_MAX )  return "";
    
    	scanf( rgb, "%x", farbe_dez );
    
    	sprintf( rgb, "%x", farbe_dez );
    	sprintf( rgb + 6, "%c%c", rgb[0], rgb[1] );
    	memcpy( rgb, rgb + 4, 2 );
    	sprintf( rgb + 4, "%c%c", rgb[6], rgb[7] );
    
    	return rgb;
    }
    
    int main() 
    {
    	cout << convert( 0x123456 );
    	return 1;
    }
    

    MfG,
    p.



  • Vielen Dank mal ich werd mir Eure Vorschläge mal ansehen.
    Ich habs jetzt mal so gelöst:
    Ist zwar umständlich,aber es funktioniert:

    void FKT_deztowebhex(std::string & inandout)
    {
    char cumwandeln[12];
    char zw_1[3],zw_2[3],zw_3[3];
    DWORD iumwandeln;
    char farbe_webhex[16];
    memset(farbe_webhex,0,16);
    
    memset(zw_1,0,3);
    memset(zw_2,0,3);
    memset(zw_3,0,3);
    
    strncpy(cumwandeln,inandout.c_str(),10);
    cumwandeln[11]='\0';
    
    inandout="";
    inandout.clear();
    
    iumwandeln=atoi(cumwandeln);
    sprintf(farbe_webhex,"%x",iumwandeln);
    
    zw_1[0]=farbe_webhex[4];
    zw_1[1]=farbe_webhex[5];
    
    zw_2[0]=farbe_webhex[2];
    zw_2[1]=farbe_webhex[3];
    
    zw_3[0]=farbe_webhex[0];
    zw_3[1]=farbe_webhex[1];
    
    inandout="#";
    inandout+=zw_1;
    inandout+=zw_2;
    inandout+=zw_3;
    }
    

    Aufruf:

    std::string zw_farbe;(...dynamisch zugewiesen...)
    
    [b]FKT_deztowebhex(zw_farbe);[/b]//Umwandeln in Webhex FArbe
    

    Dann kann ich mit zw_farbe bequem weiterarbeiten...

    Was haltet Ihr davon?

    Grüße Mondmann



  • void convert( std::ostream& out, int color )
    {
    	unsigned char* b = reinterpret_cast< unsigned char* >( &color );
    
    	out << std::hex << std::setw( 2 ) << std::setfill( '0' ) 
    		<< static_cast< int >( b[ 0 ] )
    		<< static_cast< int >( b[ 1 ] )
    		<< static_cast< int >( b[ 2 ] );
    }
    

    Je nach Byteanordnung! 😉



  • unabhängig von der byte order, aber auch doof:

    void FKT_deztowebhex (string &inandout)
    {
        unsigned long v = atoi (inandout.c_str());
        ostringstream stream;
        stream  << '#' << hex 
                << setfill('0') << setw(2) << (v&0xff) 
                << setfill('0') << setw(2) << ((v>>8)&0xff) 
                << setfill('0') << setw(2) << ((v>>16)&0xff);
        inandout = stream.str();    
    }
    

    🙂



  • pale dog schrieb:

    irgendwie mit 'stringstream' und '<< std::hex', aber ich glaube sprintf ist einfacher.
    🙂

    Da glaubst Du falsch.



  • Konrad Rudolph schrieb:

    pale dog schrieb:

    irgendwie mit 'stringstream' und '<< std::hex', aber ich glaube sprintf ist einfacher.
    🙂

    Da glaubst Du falsch.

    kennst du was einfacheres als:

    sprintf (array, "#%02x%02x%02x", wert&0xff, (wert>>8)&0xff, (wert>>16)&0xff);
    

    😕



  • Ja, den Code, den du selber da oben geschrieben hast (ist zwar etwas länger als dein sprintf()-Aufruf, aber sicherer).



  • CStoll schrieb:

    Ja, den Code, den du selber da oben geschrieben hast (ist zwar etwas länger als dein sprintf()-Aufruf, aber sicherer).

    na, ganz toll, 11 mal << und 6 mal setfill/setw 👎
    das 'sprintf' spuckt immer 8 bytes aus, also unbedenklich in bezug auf buffer overflows...
    🙂



  • pale dog schrieb:

    CStoll schrieb:

    Ja, den Code, den du selber da oben geschrieben hast (ist zwar etwas länger als dein sprintf()-Aufruf, aber sicherer).

    na, ganz toll, 11 mal << und 6 mal setfill/setw 👎

    Wenn du noch daran denkst, daß du setfill nicht für jeden Wert wiederholen mußt, wird das noch kürzer 😉

    das 'sprintf' spuckt immer 8 bytes aus, also unbedenklich in bezug auf buffer overflows...
    🙂

    Das weißt du, aber weiß es auch der Compiler? (und noch wichtiger: kann er feststellen, ob er wirklich genug Platz für diese 8 Byte zur Verfügung hat?)



  • CStoll schrieb:

    Wenn du noch daran denkst, daß du setfill nicht für jeden Wert wiederholen mußt, wird das noch kürzer 😉

    das geht? ok, drei mal << gespart 😉

    CStoll schrieb:

    das 'sprintf' spuckt immer 8 bytes aus, also unbedenklich in bezug auf buffer overflows...
    🙂

    Das weißt du, aber weiß es auch der Compiler? (und noch wichtiger: kann er feststellen, ob er wirklich genug Platz für diese 8 Byte zur Verfügung hat?)

    wieso? machste einfach char array[8]; direkt darüber, dann ist doch alles gut...



  • pale dog schrieb:

    CStoll schrieb:

    Ja, den Code, den du selber da oben geschrieben hast (ist zwar etwas länger als dein sprintf()-Aufruf, aber sicherer).

    na, ganz toll, 11 mal << und 6 mal setfill/setw 👎
    das 'sprintf' spuckt immer 8 bytes aus, also unbedenklich in bezug auf buffer overflows...
    🙂

    Warte mal. Verstehe ich das richtig? Du bist für 'sprintf', weil Dir die andere Variante zuviel zu Tippen ist und hast neulich in dem C++/Java-Thread einen Java-Code verteidigt, bei dem man seitenlang redundantes Zeugs schreibt, was einem der Compiler abnehmen könnte???



  • Konrad Rudolph schrieb:

    Warte mal. Verstehe ich das richtig? Du bist für 'sprintf', weil Dir die andere Variante zuviel zu Tippen ist und hast neulich in dem C++/Java-Thread einen Java-Code verteidigt, bei dem man seitenlang redundantes Zeugs schreibt, was einem der Compiler abnehmen könnte???

    wir sind hier ja nicht bei Java 😉
    wenn es mehrere möglichkeiten gibt, ein und dasselbe zu machen, dann bin ich immer für die kürzere oder einfachere oder vielleicht auch schnellere version...
    🙂



  • Der C Code ist bei C++ keine Alternative! :p



  • David_pb schrieb:

    Der C Code ist bei C++ keine Alternative! :p

    sprintf ist in C++ erlaubt 👍



  • pale dog schrieb:

    David_pb schrieb:

    Der C Code ist bei C++ keine Alternative! :p

    sprintf ist in C++ erlaubt 👍

    Theoretisch ja! Hab ja auch nichts Gegenteiliges behauptet.



  • pale dog schrieb:

    wieso? machste einfach char array[8]; direkt darüber, dann ist doch alles gut...

    Wie man sieht, benötigt ein C-Programmierer sehr viel Selbstdisziplin (und wenn du diesen sprintf()-Aufruf in eine Funktion packst, der sein Ziel als Parameter übergeben bekommt, muß irgendwer anderes sicherstellen, daß der Speicherplatz ausreicht - und kein Compiler der Welt wird dich daran hindern, sowas zu schreiben:

    char* rgbtext;
    convert(color,rgbtext);//viel Spaß bei der Suche nach dem Fehler
    

    Ja, die stringstream-Variante ist etwas länger zu schreiben, aber dafür sorgt sie selber dafür, daß du genau den Speicherplatz bekommst, den du benötigst. Und im Zweifelsfall ist mir die Sicherheit, daß mein Code auch in Extremsituationen funktioniert (oder erst gar keine Extremsituationen zulässt) lieber als eine eingesparte Codezeile.



  • Und wo ist nu die optimale Lösung in vollendeter Form von Quellcode ?



  • CStoll schrieb:

    Ja, die stringstream-Variante ist etwas länger zu schreiben, aber dafür sorgt sie selber dafür, daß du genau den Speicherplatz bekommst, den du benötigst. Und im Zweifelsfall ist mir die Sicherheit, daß mein Code auch in Extremsituationen funktioniert (oder erst gar keine Extremsituationen zulässt) lieber als eine eingesparte Codezeile.

    Sind wir aber ehrlich: Die stringstream-Variante bläht das Programm richtig derbe auf und ist erheblich langsamer.


Anmelden zum Antworten