Was taugt std::string wirklich?
-
Power Off schrieb:
kartoffelsack schrieb:
- Unicode kann nicht unterstützt werden (hier schon angesprochen) (wobei ich - ohne mich jemals näher damit beschäftigt zu haben das nicht versteh. Wieso kann man das nicht wenigstens über ne Spezialisierung machen???)
std::string basiert auf dem STL-Container std::basic_string.
std::string ist die Klasse für "char" Strings.
std::wstring ist die Klasse für "wchar_t" Strings.D.h. für Unicode nimmt man die std::wstring Klasse.
Und hat immer noch verloren. wchar_t hat keine feste Größe und keine feste Kodierung. wstring erkennt trotzdem nicht mehr-char-zeichen, wenn du den Indexoperator benutzt. wstring weiß gar nichts, es ist nur ein Buffer mit der Funktionalität, einen anderen Buffer daran zu ketten. Die Speicherverwaltung nimmt der std::string ab, sonst nichts.
Da im aktuellen C++ Standard die STL genormt ist, müssen alle Implementationen der STL identisch sein (zumindest von der Schnittstelle her).
Ja richtig, nur die Schnittstelle.
Die Verwendung von Unicode erfordert sowieso das Studium des Unicode 4.0 Standards. Sonst kann es leicht passieren, daß man etwas übersieht.
Was denn zum Beispiel? Da gibt's nichts zu übersehen, Unicode 4.0 ist eine Tabelle mit Zahlen und Zeichen. Was für den Programmierer wichtiger ist, sind die Transformationsformate.
Von den Container-basierten und ziemlich kurz gehaltenen String-Klassen der STL sollte man sich nicht zu viel erwarten, da sie nur eine minimale Programmierschnittstelle haben.
Minimal ist sie nicht, du hast sogar die Wahl zwischen size() und length().
Durch Verwendung von std::wstring kann man jedoch viel Zeit sparen beim Behandeln von Unicode Strings.
Nein. std::wstring ist komplett unbrauchbar und immer plattform- sowie Compiler-abhängig.
-
Hallo,
ich habe bisher immer char* für Strings benutzt.
Jetzt möche ich die string Objekte aus der STL benutzen.
So weit so gut, nur beim einlesen gibet ein Problem (siehe Quellcode).// I N C L U D E ********************** // ************************************ #include <string> #include <iostream> using namespace std; // M A I N **************************** // ************************************ int main (void) { // String erzeugen - leer string s; // String einlesen cin.get(s.c_str(), strlen(s.c_str())); // Hier gibt es das Problem mit dem ersten Parameter // String ausgeben cout << s << endl; return 0; }
das Problem: cin.get(); erwartet als ersten Parameter einen "normalen" char* aber s.c_str() gibt einen const char* zurück.
Wie kann ich jetzt die Daten in den String einlesen ?
__stdcall*
-
// I N C L U D E ********************** // ************************************ #include <string> #include <iostream> using namespace std; // M A I N **************************** // ************************************ int main (void) { // String erzeugen - leer string s; // String einlesen // cin.get(s.c_str(), strlen(s.c_str())); // Hier gibt es das Problem mit dem ersten Parameter getline(cin, s); // String ausgeben cout << s << endl; return 0; }
Nicht so kompliziert denken.
-
glaubst du wirklich, dass es Sinn macht std::string zu benutzen, wenn man es eh nur als char* benutzen will?
#include <iostream> #include <string> int main() { std::string str; std::getline(std::cin, str); std::cout << str << '\n'; }
-
string s; cin>>s;
oder
string s; getline(cin, s);
-
volkard schrieb:
mach mal vor.
mir will nicht in den kopf, wie ich aus einer funktion heraus, mäclich dem ctor von string dann noch speicher vom stack abzocke und der speicher überlebt das funktionsende.Stack war das falsche Wort, ich meinte vielmehr nicht-dynamischen Speicher. Also Speicher, mit auto oder static Lebensdauer. Den Aufbau eines Allokators kannst du im Standard nachlesen und selbst herausfinden, ob du damit etwas funktionelles hinbekommst. Mir ist das leider zu umständlich, deshalb hab ich irgendwann mal, als ich zu Lernzwecken eine eigene String Klasse geschrieben habe, beides von Haus aus ermöglicht. Die Anwendung sieht dann wie folgt aus:
string<char> foo; // Freispeicher string<char, 100> bar; // Stack oder global
-
1. Besorg dir ein Buch über die C++ Standardlib, denn Streams, Strings u.a. haben alle ein Konzept, und das scheinst du noch nicht zu kennen.
2. Beschäftige dich mit Operator-Überladung, dann kannst du zumindest aus den Schnittstellen sehen, wie man damit umgeht.
3. Nicht in C denken!
-
User--- schrieb:
Ich verwende ne map zB in meinen Funktionen zum laden und speichern von INI Dateien und da ist der map-Zugriff per Name im Programm extrem praktisch, zum speichern brauch ich jedoch iteratoren um alle Elemente durchzugehen und abzuspeichern.
wie wärs mit einer sehr schnellen map ohne iteratoren und einer ein wenig langsameren map mit iteratoren?
-
Optimizer schrieb:
wstring erkennt trotzdem nicht mehr-char-zeichen, wenn du den Indexoperator benutzt. wstring weiß gar nichts, es ist nur ein Buffer mit der Funktionalität, einen anderen Buffer daran zu ketten. Die Speicherverwaltung nimmt der std::string ab, sonst nichts.
Dafür sind die Character-Traits zuständig: wenn die STL-Implementation Deines Compilers mit Unicode nicht umgehen kann, dann weißt Du, was zu tun ist.
Die Character-Traits beschreiben u.a. Collation (also Sortierung), wie Zeichen übersprungen werden usw. Ein Blick in den Standard hilft.Optimizer schrieb:
Was denn zum Beispiel? Da gibt's nichts zu übersehen, Unicode 4.0 ist eine Tabelle mit Zahlen und Zeichen. Was für den Programmierer wichtiger ist, sind die Transformationsformate.
Noch so ein Irrtum. Im Unicode-Standard sind z.B. auch Spacing und Compositing von Schriftzeichen festgelegt.
Im Chinesischen gibt es z.B. zusammengesetzte Schriftzeichen, die aus mehreren zusammengesetzt sind. Es gibt also noch Steuercodes, die das Zusammensetzen von Zeichen steuern. Ein Unicode Code-Point muß nicht unbedingt ein Schriftzeichen sein.
Das gleiche gilt für Kana-Überschriften von Kanji im Japanischen. Da gibt es auch spezielle Shift- und Kompositing-Modi.
Außerdem gibt es jede Menge Arten von Spacing, wie z.B. Vertikal-Spacing, hoch und runter, usw.
Den Unicode Standard muß man benutzen, wenn man Unicode-fähige Programme schreiben will, ansonsten wird das Programm nicht mehrsprachfähig.
Das wirst Du dann sehen, wenn sich der erste Chinese beschwert, daß er in Deinem Programm nix eingeben kann, oder ein Araber meckert über das falsch gruppierte Arabisch.
Optimizer schrieb:
Nein. std::wstring ist komplett unbrauchbar und immer plattform- sowie Compiler-abhängig.
C++ generell ist plattform- und compilerabhängig. Falls Du das noch nicht gemerkt hast, wird's langsam Zeit dafür.
Die Mindestgröße von wchar_t ist 16 Bit. Das entspricht unter Windows genau einem Unicode-CodePoint. Windows verwendet UTF-16 zur Codierung von Unicode-Zeichen.
Unter UNIXen ist wchar_t meist 32 Bit, dies erlaubt die Verwendung von UTF-32.
Das spielt aber für Unicode keine Rolle, da CodePoints in Unicode immer mindestens 32-Bit-Breit sind.
D.h. auf Systemen mit UTF-16 Codierung (wie Windows) muß man halt erst nach UTF-32 wandeln.
Dafür und für viele andere Sachen ist der Unicode Standard gedacht.
-
volkard schrieb:
User--- schrieb:
Ich verwende ne map zB in meinen Funktionen zum laden und speichern von INI Dateien und da ist der map-Zugriff per Name im Programm extrem praktisch, zum speichern brauch ich jedoch iteratoren um alle Elemente durchzugehen und abzuspeichern.
wie wärs mit einer sehr schnellen map ohne iteratoren und einer ein wenig langsameren map mit iteratoren?
das must du aber dem standard komitee um die ohren hauen, nicht uns
da war doch auch noch das problem, dass size() für list ebenfalls konstante komplexität hat, obwohl das ebenfalls platzverschwendung (wenn auch nur einmal pro container) bedeutet.
-
Power Off schrieb:
Noch so ein Irrtum. Im Unicode-Standard sind z.B. auch Spacing und Compositing von Schriftzeichen festgelegt.
Im Chinesischen gibt es z.B. zusammengesetzte Schriftzeichen, die aus mehreren zusammengesetzt sind. Es gibt also noch Steuercodes, die das Zusammensetzen von Zeichen steuern. Ein Unicode Code-Point muß nicht unbedingt ein Schriftzeichen sein.
Das gleiche gilt für Kana-Überschriften von Kanji im Japanischen. Da gibt es auch spezielle Shift- und Kompositing-Modi.
Außerdem gibt es jede Menge Arten von Spacing, wie z.B. Vertikal-Spacing, hoch und runter, usw.
Den Unicode Standard muß man benutzen, wenn man Unicode-fähige Programme schreiben will, ansonsten wird das Programm nicht mehrsprachfähig.
Das wirst Du dann sehen, wenn sich der erste Chinese beschwert, daß er in Deinem Programm nix eingeben kann, oder ein Araber meckert über das falsch gruppierte Arabisch.
Deswegen musst du nicht mit dem Unicode-Standard vertraut sein. Oder hast du vor, deine eigene Ein- und Ausgabe zu programmieren? Es ging hier in diesem Thread um Strings. Ich weiß sehr genau, dass ein Unicode Code-Point nicht unbedingt ein Schriftzeichen sein muss und genau diese Erkenntnis fehlt dem wstring ebenso wie die Erkenntnis, dass ein wchar_t auch nicht ein Schriftzeichen sein muss. Naja, also warum man den Unicode-Standard durchgelesen haben muss, ist jetzt immer noch nicht klar. Ich bin jetzt schon davon ausgegangen, dass wir die Ausgabe nicht selber zeichnen, sondern sowas wie wcout << myString machen.
Nein. std::wstring ist komplett unbrauchbar und immer plattform- sowie Compiler-abhängig.
C++ generell ist plattform- und compilerabhängig. Falls Du das noch nicht gemerkt hast, wird's langsam Zeit dafür.
Noch so'n dummer Spruch. Das interessiert hier für dieses Thema kein Stück, ob du es schaffst, das Programm für einen Toaster zu compilieren. Es geht gar nicht um die plattformunabhängigkeit von C++, sondern des wstrings. Diese sieht so aus, dass nicht festgelegt ist, welche Zeichenkodierung für wchar_t verwendet wird, oder willst du das leugnen? Naja kannst du ja schlecht, schließlich schreibst du gleich anschließend:
D.h. auf Systemen mit UTF-16 Codierung (wie Windows) muß man halt erst nach UTF-32 wandeln.
Uiuiui. Also nix einfach wstring benutzen und auf jeder Plattform kommt das selbe bei raus. Ganz schön unabhängig das Teil, so wie die Integer-Arithmetik in C++ halt auch. Unabhängig kann man natürlich so definieren, dass sich der Code überall compilieren lässt, wenn man das auch noch nutzen will, dann sollte man allerdings auch noch den Anspruch stellen, dass sich das Programm gleich verhält.
Nehm ich das wchar_t myString[40], kann das auf jedem System was anderes sein, es könnte ein Viertel des zehnten Zeichens sein, es könnte das vollständige 18. Zeichen sein, es kann das 40. Zeichen sein. Geile String-Klasse haben wir da. Dass basic_string nicht mehr ist als ein templatisierter buffer mit Konkatenationsmöglichkeit, kann man aber eigentlich auch auf dem ersten Blick erkennen.EDIT: Übrigens alles recht sinnlos, wir schweifen schon wieder ab. Zähl mir doch einfach mal die ganzen Features auf, die wstring mit sich bringt um
- mit Multibyte-Zeichenkodierungen umgehen zu können
ODER
- zeig mir die Stelle im Standard, wo steht, dass ein wchar_t immer ein UCS4-Zeichen ist, so dass keine Unterstützung Multibyte-Kodierung erforderlich wäreEiner dieser beiden Punkte ist hinreichend, um mich davon zu überzeugen, dass wstring tatsächlich für Unicode geeignet ist.
-
Optimizer schrieb:
Dass basic_string nicht mehr ist als ein templatisierter buffer mit Konkatenationsmöglichkeit, kann man aber eigentlich auch auf dem ersten Blick erkennen.
Schau Dir doch mal Kapitel 21.1.3.2 in ISO 14882:2003 an.
Da steht die Deklaration (nicht Definition!) von char_traits<wchar_t>.
Die Methoden sind u.a. assign(), eq(), lt(), compare(), length(), find(), move(), copy(). Bei find() bspw. muß schon auf Systemspezifika Rücksicht genommen werden, bei compare(), eq(), lt() auch.
Wenn ein Compilerhersteller die Klasse im Header definiert, anstatt nur zu deklarieren, und in dem Fall keine Spezialroutinen aufruft, dann ist das eben nur eine "dummes Brot" Implementation der Klasse.
Normalerweise sollte im Header die Klasse nur deklarieren, und die Implementation in der Library sein. Dort werden dann die entsprechenden Unicode-Routinen aufgerufen, sofern das System Unicode unterstützt.
MBCS wird ja schon seit 15 Jahren vom C Standard unterstützt (seit C90), wchar_t übrigens auch. Übrigens bedeutet auf Unicode-fähigen Systemen MBCS meist UTF-8.
Natürlich sind diese Funktionen nicht so toll, verglichen mit dem, was man vielleicht erwarten würde, aber das ist war schon immer so. Die gehen halt stillschweigend davon aus, daß Du z.B. den Unicode-Standard zur Hand hast.
Dann sind diese Klassen und Funktionen durchaus nützlich.
Von Portabilität kann ja wie gesagt, bei C++ eh keine Rede sein, da ja viele Dinge implementationsabhängig sind. Das fängt bei der Breite der Datentypen an, geht über Byte-Order und Bitorder, sowie Kodierung, etc. -- das liegt im Ermessen des Programmierers, mehr oder weniger portable Programme zu schreiben, oder es sein zu lassen. "stdint.h" z.B. ist auch noch nicht so lange dabei. Früher hat man halt seine eigenen Header dafür gemacht.
So muß man halt auch den wchar_t Typ betrachten.
Es hindert Dich ja niemand daran, z.B. eine string-Klasse von basic_string abzuleiten mit den character traits und dem Zeichentyp Deiner Wahl (z.B. long oder int).
Die Funktionalität mag zwar oft beschränkt sein, das heißt aber noch lange nicht, daß wstring generell unnütz ist.
Wenn jemand z.B. eine Unicode-Anwendung mit irgendeinem portablen Framework schreibt, so hat er schon Kapselungen für Unicode usw.
Andere, reine speicherbasierte Lösungen, die für einen Spezialzweck geschrieben wurden, und nur auf einem Plattformtyp laufen (z.B. Linux) können sehr wohl wstring benutzen. (oder auch eine Windows Anwendung z.B.)
-
Ich verstehe das schon, dass das alles wunderbar generisch ist und dass man sich auch leicht mit dem System selber was basteln kann. Dass man dafür dann auch den Unicode Standard braucht, ist ebenfalls einzusehen.
Aber wstring ist IMHO viel zu grob spezifiziert, als dass man etwas hätte, mit dem man verlässlich portabel arbeiten könnte. Wie du selber schon sagst, kann allein schon ein wchar_t alles mögliche sein. Schließlich bezog sich meine Kritik auf die Spezifikation von wstring, also dem, was man ohne Riesenaufwand bekommt.
AFAIK ist nicht mal vorgegeben, dass wchar_t überhaupt irgendein Unicode-Transformationsformat darstellt, auch wenn es scheinbar durchgehend so ist. Viele andere sinnvollere Kodierungen gibt es ja auch nicht. Mit so einer allgemeinen Spezifikation ist natürlich die Zukunft des wstring für die nächsten 2000 Jahre gesichert, weil die nie geändert werden muss. Ob ich den dann in der Gegenwart verwenden will und ob so etwas das Ganze wirklich portabler macht, ist eine andere Frage.
-
volkard schrieb:
User--- schrieb:
Ich verwende ne map zB in meinen Funktionen zum laden und speichern von INI Dateien und da ist der map-Zugriff per Name im Programm extrem praktisch, zum speichern brauch ich jedoch iteratoren um alle Elemente durchzugehen und abzuspeichern.
wie wärs mit einer sehr schnellen map ohne iteratoren und einer ein wenig langsameren map mit iteratoren?
Das wäre ne feine Sache, wobei man da auch noch bei anderen Teilen der STL ne light version rausbringen könnte
-
Power Off schrieb:
Die Mindestgröße von wchar_t ist 16 Bit.
Nope.
-
groovemaster schrieb:
Nope.
Stimmt, kann auch genauso gross wie "char" sein, hab's dann gesehen, als ich fuer Optimizer im Standard nachgeguckt hab. Da stand, dass wchar_t so gross sein muss, dass es jedes Zeichen des erweiterten Zeichensatzes aufnehmen kann. Wenn's keinen gibt, kann natuerlich wchar_t so gross sein wie char.