Problem bei Funktion für Stringverarbeitung
-
Wollte eine Funktion erstellen die aus einer WinApi Editbox den Text ausliest, Text hinzufügt und wenn er eine bestimmt Länge überschreitet den Anfang absäbelt.
Das einzige was jetzt nicht richtig funktioniert sind die Zeilenumbrüche. Ich füg da ein \r\n hinzu wenn ich einen Zeilenumbruch will, aber ich kann grade nicht erkennen in welchen Fällen er nicht dargestellt wird. Ich benutz einen stringstream um jeden Datentyp zu einem String umzuwandeln.
Hier die Funktion://nMaxChars ist die maximale Länge des Textes von hWnd template <class myType> BOOL AddWindowText(HWND hWnd,myType text, const int nMaxChars, bool breakLine=1) { stringstream strBuffer; char* cstrBuffer=new char[nMaxChars+1]; //GetWindowText fügt eine 0 am Ende hinzu int charsRead=0; charsRead=GetWindowText(hWnd, cstrBuffer,nMaxChars+1); strBuffer<<cstrBuffer; strBuffer<<text; if(breakLine) strBuffer<<"\r\n"; string str=strBuffer.str(); if(str.size()>nMaxChars) str=str.substr(str.size()-nMaxChars-1, nMaxChars+1); delete [] cstrBuffer; return SetWindowText(hWnd, str.c_str()); }Also wenn der String nicht gekürzt wird dann wird auch jeder Zeilenumbruch richtig angezeigt, aber irgendwie kommt es vor dass einige einfach verschwinden wenn der Anfang vom Text entfernt werden soll, ich kann grade nichts genaueres erkennen.
Kann da jemand einen Fehler erkennen? Vermutlich eher mehrere Fehler.
-
Och nö.
template <class myType> BOOL AddWindowText( HWND hWnd, myType text, std::size_t nMaxChars, bool breakLine = true ) { std::string Buffer( nMaxChars + 1 ); std::size_t charsRead = GetWindowText(hWnd, &Buffer[0], Buffer.length()); string str = Buffer + text; if( breakLine ) // Editiert. Ein if-Statement scheint hier einfach sinnvoller. str += "\r\n"; if( str.size() > nMaxChars ) str.erase( 0, str.size() - nMaxChars ); return SetWindowText(hWnd, str.c_str()); }~(Natürlich ungetestet)~
-
Sone schrieb:
if( str.size() > nMaxChars ) str.erase( 0, str.size() - nMaxChars ); return SetWindowText(hWnd, str.c_str()); }Och nö.
return SetWindowText(hWnd, str.size()>nMaxChars ? &*str.end() - nMaxChars : str.c_str());~(Selbstverständlich natürlich ungetestet)~
-
Geht beides nicht wie es soll. Schon weil man nicht einfach zB Ints und Doubles an einen String anhängen kann.
Und ich wüsste von keinem String constructor der nur ein int nimmt.
-
Dafür gibt es dann std::to_string.
-
Von to_string wusste ich nichts, deswegen hab ich den stringstream benutzt.
Jedenfalls scheint es als hätte nur die Zeilestr.erase( 0, str.size() - nMaxChars );das Problem mit den Zeilenumbrüchen gelöst, auch wenn ich den Grund nicht erkenne.
-
Folgendes:
&*str.end() - nMaxCharserzeugt UB (str.end() ist nicht dereferenzierbar). MSVC haut einem im Debug-Modus dafür einen assert um die Ohren.
str.c_str() + str.size() - nMaxCharswär jetzt mein Ansatz. Geht sogar in C++03.
-
untester schrieb:
Och nö.
Autsch, hast Recht, das bearbeiten des Strings ist völlig überflüssig. Da habe ich wieder zu genau hingeschaut....
-
Es geht auch ohne string oder gar stringstream.
//nMaxChars ist die maximale Länge des Textes von hWnd template <class myType> BOOL AddWindowText(HWND hWnd,myType text, const int nMaxChars, bool breakLine=true) { char* buf=new char[nMaxChars+1]; //GetWindowText fügt eine 0 am Ende hinzu GetWindowText(hWnd, buf, nMaxChars+1); strncat(buf, text, strlen(buf)<nMaxChars?nMaxChars-strlen(buf):0); if( breakLine ) strncat(buf, "\r\n", strlen(buf)<nMaxChars-1?2:0); BOOL r = SetWindowText(hWnd, buf); delete [] buf; return r; }
-
Wutz, was soll der Blödsinn? Wer zum Teufel arbeitet hier mit
new/delete?Hier würde sich ein Start/End Iteratorenpaar besser machen.
Edit²: Weil unten schon steht, dass er ja irgendwie jeden Typen ausgeben lassen können will, muss man doch per Referenz o.ä. übergeben.Ich benutz einen stringstream um jeden Datentyp zu einem String umzuwandeln.
Edit: Habe ich übersehen... das ist was anderes. Das geht dann tatsächlich nicht ohne Stringstream, wenn diese Datentypen möglicherweise nur den
operator<<überladen.
-
Reg dich ab.
Set/GetWindowText ist eindeutig WinAPI, und die arbeiten ausschließlich mit char/TCHAR.
-
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.