anfängerprobleme mit sprintf



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



  • Teste doch nochmal das hier:

    template<typename CharT>
        std::basic_string<CharT> to_hex_string(unsigned value)
        {
            typedef std::basic_string<CharT> string_type;
            string_type result(sizeof(value) * 2, 0);
            typename string_type::reverse_iterator iter = result.rbegin();
            while(value > 16)
            {
                unsigned cur = value % 16;
                *iter = cur < 10 ? CharT('0') + cur : CharT('A') + cur - 10;
                ++iter;
                value /= 16;
            }
    
            *iter = value < 10 ? CharT('0') + value : CharT('A') + value - 10;
            return result;
        }
    


  • camper schrieb:

    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.

    Äh, ja 😉

    Ethon schrieb:

    Teste doch nochmal das hier:

    Ethon:    33.6387
    

Anmelden zum Antworten