Problem bei Funktion für Stringverarbeitung



  • Wutz schrieb:

    Set/GetWindowText ist eindeutig WinAPI, und die arbeiten ausschließlich mit char/TCHAR.

    Ja, aber das geht trotzdem mit C++-Strings. Da braucht man nicht RAII zu vernachlässigen. 🙂

    Ich werfe mal eine neue Version in den Ring:

    template <class myType>
    BOOL AddWindowText( HWND hWnd,
                        myType const& text,
                        std::size_t nMaxChars,
                        bool breakLine = true )
    {
        std::string Buffer( nMaxChars + 1 );
    
        GetWindowText(hWnd, &Buffer[0], Buffer.length());
    
        std::ostringstream stream( Buffer );
        stream << text;
    
        if( breakLine )
            stream << "\r\n";
    
        std::string rval = stream.str();
        char const* begin = rval.c_str():
    
        if( rval.length() > nMaxChars )
    		begin += rval.length() - nMaxChars - 1;
    
        return SetWindowText(hWnd, begin);
    }
    


  • Ein anderes kleines Problem ist die to_string Funktion. Wieso muss ich ein int zu long double casten beim übergeben und wieso hat to_string bei mir nur 3 varianten die alle kein int nehmen, wie es hier zu sehen ist: http://www.cplusplus.com/reference/string/to_string/?kw=to_string

    Außerdem würde ich gern den << Operator für HWND überladen, aber es geht nicht.

    HWND operator<<(HWND hWnd, const char* text)
    {
    	AddWindowText(hWnd, text);
    	return hWnd;
    }
    

    Da kommt nur die Meldung dass ein Operator der kein Member ist einen Klassen- oder Enumerationstyp erfordert. Geht der Operator also nur als Klassenmember?



  • hat keine ne idee?



  • Wutz schrieb:

    Set/GetWindowText ist eindeutig WinAPI, und die arbeiten ausschließlich mit char/TCHAR.

    Och, ein std::vector<char/TCHAR> tut es auch, vector<...>.data() gibt es schon in VS 2010.

    Das Problem: Ist das Window dann owner des Textes?

    Wieso muss ich ein int zu long double casten beim übergeben und wieso hat to_string bei mir nur 3 varianten die alle kein int nehmen,

    1.) Es gibt auch eine Ueberladung fuer (in)signed Long Long.
    2.) Du benutzt wahrscheinlich VS 2010.

    Außerdem würde ich gern den << Operator für HWND überladen, aber es geht nicht.

    1.) Tolle Fehlerbeschreibung
    2.) HWND ist wahrscheinlich ein void*, diese ueberladung gibt es wahrscheinlich schon.



  • 1. to_string() hat Überladungen für fast alle arithmetischen Typen, sieht man auch in deinem Link, es gibt auch eine für int.
    2. Operaturüberladungsfunktionen müssen mindestens einen benutzerdefinierten Typen (Klasse, ....) als Argument nehmen (oder zurückgeben?), du kannst keine Version für zwei Pointer schreiben (HWND ist ein Typedef für einen Pointer auf eine struct HWND__ oder mit ähnlichem Namen, weiß ich nicht auswendig).
    So eine Operatorüberladung ist auch schwachsinnig und unintuitiv (?).
    Falls du es doch machen willst, musst du entweder HWND in eine Klasse kapseln (was du schon allein wegen RAII machen solltest!) oder einen std::string als zweites Argument nehmen.



  • Francis123 schrieb:

    Ein anderes kleines Problem ist die to_string Funktion. Wieso muss ich ein int zu long double casten beim übergeben und wieso hat to_string bei mir nur 3 varianten die alle kein int nehmen, wie es hier zu sehen ist: http://www.cplusplus.com/reference/string/to_string/?kw=to_string

    Das leigt daran, dass vor VS2012 mit to_string nur eben die Standard Floatingpoint Zahlen eingebaut waren. to_string ist eigentlich C++11 und war damals im begrenzten Umfang eine kleine Erweiterung von VS2010 (und ich weis nicht welchen Versionen vorher), mit VS2012 wird to_string dann voll unterstützt.



  • Ist es möglich beim Aufrufen einer Funktion die ein Struct erwartet das Struct direkt zu erzeugen ohne vorher eine Variable zu erstellen und diese dann zu übergeben?



  • Meinst du sowas?

    struct foo{};
    ...
    func(foo(a, b, c, d, e, f, g));
    

    ?



  • Ja das meine ich, aber bei mir geht das so nicht weil da nur ein Kopierkonstruktor und ein leerer Konstruktor zur Auswahl stehen.



  • Dann schreibste halt einen benutzerdefinierten Konstruktor!
    Oder du nutzt Aggregat-Initialisierung:

    func({a, b, c, d});
    


  • Ich will bei einem vector mit diesem struct die structs mit push_back einfügen.
    So wie du das geschrieben hast geht es leider nicht. Da steht dann nur es wurde ein Ausdruck erwartet. Geht wohl nur mit einer eigenen Funktion die den vector pointer und die restlichen Daten nimmt.



  • Wutz schrieb:

    Reg dich ab.
    Set/GetWindowText ist eindeutig WinAPI, und die arbeiten ausschließlich mit char/TCHAR.

    Das ist kein Grund, mit new[] / delete[] zu arbeiten. Kannst auch genauso gut

    vector<char> puffer(999);
    eine_C_Funktion(&puffer[0],999);
    

    schreiben. Dann kann es dir gar nicht passieren, delete[] zu "vergessen". Auch wenn du delete[] dort stehen hast, kann ja zwischendurch irgendwo eine Ausnahme fliegen und dann hättest du ein Speicherleck, weil die Ausführung gar nicht erst zum delete[] kommt.

    Ab C++11 ist das auch bei std::string erlaubt, weil garantiert ist, dass die Elemente hintereinander im Speicher stehen. Allerdings muss man sich, wenn man das so in String schreiben lässt, selbst um die Nullterminierung kümmern. Die will man typischerweise nicht mit drin haben und auch den Rest dahinter nicht. Also:

    string s (999);
    eine_C_Funktion(s.data(),999); // ab C++11
    s.erase(find(s.begin(),s.end(),'\0'),s.end());
    

    (ungetestet)

    Merken: new[] und delete[] brauchen wir so gut wie nie mehr.



  • Merken: new[] und delete[] brauchen wir so gut wie nie mehr.

    so gut? 🙂
    Ich meine, wir brauchen seit C++11/14* nicht mal new zu schreiben, vorausgesetzt wir arbeiten brav mit Smart-Pointern.

    Auch wenn du delete[] dort stehen hast, kann ja zwischendurch irgendwo eine Ausnahme fliegen und dann hättest du ein Speicherleck, weil die Ausführung gar nicht erst zum delete[] kommt.

    Wieso erklärst du ihm das? Das weiß er (so hoffe ich) selbst.

    HWND ist wahrscheinlich ein void*, diese ueberladung gibt es wahrscheinlich schon.

    Beides richtig. HWND ist ein HANDLE , was wiederum ein PVOID ist. Und der Ausgabeoperator für void* ist schon überladen (in ostream selbst).

    Die will man typischerweise nicht mit drin haben und auch den Rest dahinter nicht.

    Bei vielen solchen Funktionen ist von vornherein klar, dass '\0' das letzte Zeichen im String ist - daher reicht da meistens auch ein pop_back().
    Und wieso benutzt du nicht die find() -Funktion aus std::string ?

    • make_unique


  • Sone schrieb:

    HWND ist wahrscheinlich ein void*, diese ueberladung gibt es wahrscheinlich schon.

    Beides richtig. HWND ist ein HANDLE , was wiederum ein PVOID ist. Und der Ausgabeoperator für void* ist schon überladen (in ostream selbst).

    Er redet nicht vom Ausgabeoperator, Sone. 🙄 😉



  • Nathan schrieb:

    Sone schrieb:

    HWND ist wahrscheinlich ein void*, diese ueberladung gibt es wahrscheinlich schon.

    Beides richtig. HWND ist ein HANDLE , was wiederum ein PVOID ist. Und der Ausgabeoperator für void* ist schon überladen (in ostream selbst).

    Er redet nicht vom Ausgabeoperator, Sone. 🙄 😉

    Ich weiß ja nicht, wie du das siehst, aber wenn ich lese

    Knivil schrieb:

    Außerdem würde ich gern den << Operator für HWND überladen, aber es geht nicht.

    [...]
    2.) HWND ist wahrscheinlich ein void*, diese ueberladung gibt es wahrscheinlich schon.

    Dann folgere ich daraus, dass er sich auf das Zitat bezieht...
    Edit: Ah, er will gar nicht den operator<< für ostream überladen... :kopf->tisch: 🙂



  • Sone schrieb:

    Die will man typischerweise nicht mit drin haben und auch den Rest dahinter nicht.

    Bei vielen solchen Funktionen ist von vornherein klar, dass '\0' das letzte Zeichen im String ist - daher reicht da meistens auch ein pop_back().

    Wenn du vorher genug Platz schaffst, der dann aber nicht voll ausgenutzt wird und dir so eine C-Funktion auch nicht verrät, wie lang der String wirklich war, musst du '\0' erst mal suchen. Und genau das wollte ich erwähnt haben.

    Sone schrieb:

    Und wieso benutzt du nicht die find() -Funktion aus std::string ?

    Ich bin faul. Da hätte ich erst nachgucken müssen, wie die Überladungen und Signaturen aussehen, ob da ein Iterator oder ein Index zurück kommt und sowas...



  • ob da ein Iterator oder ein Index zurück kommt

    Ist relativ egal, weil du den Index dann auch auf begin() addieren kannst. Und die Zehn Sekunden Google-Recherche sind nicht die Welt. 🙂

    Wenn du vorher genug Platz schaffst, der dann aber nicht voll ausgenutzt wird und dir so eine C-Funktion auch nicht verrät, wie lang der String wirklich war, musst du '\0' erst mal suchen.

    Ganz vergessen - natürlich ist so ein String nicht immer auch genau so lang... 💡 🙄

    Zum Glück geben viele solche Funktionen die Länge zurück, da reicht ein resize .


Anmelden zum Antworten