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 ersetztEcht 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 ersetztEcht 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; }
-
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