anfängerprobleme mit sprintf



  • jetzt hab ich die lösung von swordfish genommen 😛

    habt ihr bitte auch ne lösung für mein 2tes problem mit der for schleife (erster post)?!



  • kens0o schrieb:

    [...] irgendwie mogelt der mir eine 8 darein:

    das machst Du schon selbst,

    kens0o schrieb:

    stream << std::ios::hex << akku;
    

    in dem du hier einfach so ein Format flag in den stream schiebst.

    Wenn schon Format flags setzen, dann richtig:

    std::ostringstream stream;
    	stream.setf( std::ios::hex, std::ios::basefield );
    	stream << 42;
    


  • Oder std::hex nehmen. 😉



  • ... und da wir uns jetzt g'rad' so schön einig sind, packen wir's noch in eine Funktion und vergessen den Quatsch wieder.

    #include <iostream>
    #include <sstream>
    #include <iomanip>
    #include <string>
    
    std::string to_hex_string( const unsigned value, const unsigned width = 4, const std::ostream::char_type fill = '0' ) {
    	static std::ostringstream ss;
    	ss.str( "" );
    	ss << std::hex << std::setfill( fill ) << std::setw( width ) << value;
    	return ss.str( );
    }
    
    int main( )
    {
    	std::string foo = to_hex_string( 42 );
    
    	std::cout << "foo: " << foo << std::endl;
    }
    


  • Ich biete dagegen!

    #include <iostream>
    #include <sstream>
    #include <iomanip>
    
    std::string to_hex_string(const unsigned value)
    {
        std::ostringstream stream;
        stream << std::hex << value;
        return stream.str();
    }
    
    int main()
    {
       std::cout << to_hex_string(80) << '\n';
    }
    


  • ... und was hast Du getan?
    1. flexibilität eingespart
    2. bloßes "Zurücksetzen" des Streams durch komplettes Neubauen des Streams ersetzt

    Echt toll. 👍 🙄
    Aber ich hau' jetzt hier ab, wird mir en bisserl 'z blöd.



  • Ah, warte! ich hab das static nicht gesehen.



  • Swordfish schrieb:

    ... und was hast Du getan?
    1. flexibilität eingespart
    2. bloßes "Zurücksetzen" des Streams durch komplettes Neubauen des Streams ersetzt

    Echt toll. 👍 🙄
    Aber ich hau' jetzt hier ab, wird mir en bisserl 'z blöd.

    Sorry, aber Hackers Lösung ist deutlich besser. Nur der formale Parameter hätte nicht const-Qualifiziert sein müssen.



  • Hacker schrieb:

    Ah, warte! ich hab das static nicht gesehen.

    Machs wieder hin. Das war gut, so ganz ohne static.



  • Tachyon schrieb:

    Hacker schrieb:

    Ah, warte! ich hab das static nicht gesehen.

    Machs wieder hin. Das war gut, so ganz ohne static.

    Gut. Ich dachte nur, Zeile 8 bei Swordsfish's Code wäre unnötig.



  • Oder einfach C-API. Da spart man sich den ganzen Streamoverhead (mind. 1 zusätzliche Allokation).

    std::string to_hex_string(unsigned value)
    {
        char buffer[std::numeric_limits<unsigned>::digits];
        return std::string(std::itoa(value, buffer, 16));
    }
    


  • Ethon schrieb:

    Oder einfach C-API. Da spart man sich den ganzen Streamoverhead (mind. 1 zusätzliche Allokation).

    std::string to_hex_string(unsigned value)
    {
        char buffer[std::numeric_limits<unsigned>::digits];
        return std::string(std::itoa(value, buffer, 16));
    }
    

    Nur, dass itoa kein Standard-C ist.



  • Tachyon schrieb:

    Sorry, aber Hackers Lösung ist deutlich besser.

    Mhm. Erklärst Du mir auch, warum?



  • Swordfish schrieb:

    Tachyon schrieb:

    Sorry, aber Hackers Lösung ist deutlich besser.

    Mhm. Erklärst Du mir auch, warum?

    Weil Deine Version sich sinnfreierweise so ziemlich alle Probleme einfängt, die static-Variablen so mit sich bringen. Was versprichst Du Dir davon? Ein Performancegewinn?



  • Tachyon schrieb:

    Ethon schrieb:

    Oder einfach C-API. Da spart man sich den ganzen Streamoverhead (mind. 1 zusätzliche Allokation).

    std::string to_hex_string(unsigned value)
    {
        char buffer[std::numeric_limits<unsigned>::digits];
        return std::string(std::itoa(value, buffer, 16));
    }
    

    Nur, dass itoa kein Standard-C ist.

    Imho fast egal, da ich noch nie einen Compiler gesehen habe, der es nicht kann. Na dann einfach die Idee des OPs gefixt:

    std::string to_hex_string(unsigned value)
    {
        char buffer[sizeof(value) * 2 + 1];
        sprintf(buffer,"%x", value); 
        return std::string(buffer);
    }
    

    Immer noch schneller als per stringstream.



  • Tachyon schrieb:

    Weil Deine Version sich sinnfreierweise so ziemlich alle Probleme einfängt, die static-Variablen so mit sich bringen.

    Im konkreten Fall? Sorry, ich wills wirklich wissen.

    Tachyon schrieb:

    Was versprichst Du Dir davon? Ein Performancegewinn?

    Ja, wenn ich auch nicht gemessen habe.



  • Swordfish schrieb:

    Tachyon schrieb:

    Weil Deine Version sich sinnfreierweise so ziemlich alle Probleme einfängt, die static-Variablen so mit sich bringen.

    Im konkreten Fall? Sorry, ich wills wirklich wissen.

    Was wenn bspw. Fehlerbits gesetzt werden?



  • Es ist auf jeden Fall nicht Threadsafe. Mit C++11 und thread_local könnte es Sinn machen, aber Variable reusing neigt oft dazu die Performance zu drücken, da der Compiler schlechter optimieren kann.



  • Swordfish schrieb:

    Tachyon schrieb:

    Weil Deine Version sich sinnfreierweise so ziemlich alle Probleme einfängt, die static-Variablen so mit sich bringen.

    Im konkreten Fall? Sorry, ich wills wirklich wissen.

    Ok, Threadsafe ist es (noch) nicht. Sonst?

    Swordfish schrieb:

    Tachyon schrieb:

    Was versprichst Du Dir davon? Ein Performancegewinn?

    Ja, wenn ich auch nicht gemessen habe.

    Gemessen: // edit Fehlerbits noch löschen...

    Swordfish: 591.937
    Hacker:    1005.78
    Ethon:     171.649
    

    Gut, daß uns sprintf schlägt, ist klar...

    #include <iostream>
    #include <sstream>
    #include <iomanip>
    #include <string>
    #include <cstdlib>
    
    #include <Windows.h>
    #define WIN32_LEAN_AND_MEAN
    
    std::string to_hex_string_swordfish( unsigned value ) {
    	static std::ostringstream ss;
    	ss.clear( );
    	ss.str( "" );
    	ss << std::hex << value;
    	return ss.str( );
    }
    
    std::string to_hex_string_hacker( unsigned value)
    {
        std::ostringstream stream;
        stream << std::hex << value;
        return stream.str();
    } 
    
    std::string to_hex_string_ethon(unsigned value)
    {
        char buffer[sizeof(value) * 2 + 1];
        sprintf(buffer,"%x", value);
        return std::string(buffer);
    }
    
    int main( )
    {
    	HANDLE me = GetCurrentProcess( );
    	if( !SetPriorityClass( me, REALTIME_PRIORITY_CLASS ) ) {
    		std::cerr << "SetPriorityClass failed!\n";
    		return EXIT_FAILURE;
    	}
    
    	std::srand( static_cast< unsigned >( std::time( 0 ) ) );
    
        LARGE_INTEGER start, end;
    
    	if( !QueryPerformanceFrequency( &start) ) {
            std::cerr << "QueryPerformanceFrequency failed!\n";
    		return EXIT_FAILURE;
    	}
    
        double frequency = start.QuadPart / 1000.0;
    	double elapsed;
    
    	std::string result;
    
    	// Swordfish
    	QueryPerformanceCounter( &start );
    
    	for( size_t i = 0; i < 1000000; ++i ) {
    
    		result = to_hex_string_swordfish( rand( ) );
    	}
    
        QueryPerformanceCounter( &end );
    	elapsed = ( end.QuadPart - start.QuadPart ) / frequency;
    
    	std::cout << "Swordfish: " << elapsed << std::endl;
    
    	// Hacker
    	QueryPerformanceCounter( &start );
    
    	for( size_t i = 0; i < 1000000; ++i ) {
    
    		result = to_hex_string_hacker( rand( ) );
    	}
    
        QueryPerformanceCounter( &end );
    	elapsed = ( end.QuadPart - start.QuadPart ) / frequency;
    
    	std::cout << "Hacker:    " << elapsed << std::endl;
    
    	// Ethon
    	QueryPerformanceCounter( &start );
    
    	for( size_t i = 0; i < 1000000; ++i ) {
    
    		result = to_hex_string_ethon( rand( ) );
    	}
    
        QueryPerformanceCounter( &end );
    	elapsed = ( end.QuadPart - start.QuadPart ) / frequency;
    
    	std::cout << "Ethon:     " << elapsed << std::endl;
    }
    

    🙄


  • Mod

    Hat zwar nichts mit dem Thema zu tun... aber

    #define WIN32_LEAN_AND_MEAN
    

    nachdem du <windows.h> bereits eingebunden hast, scheint mir sinnlos zu sein.


Anmelden zum Antworten