In Ihrer GUI-Applikation wollen Sie einen Dialog zum Eingeben irgendwelcher Daten verwenden.
Genau! "I r g e n d w e l c h e" Daten.
Die Typen der Daten sind völlig(!!!) belanglos.
Tun wir es mit unsigned int! Das ist zwar kein besonders geiler Typ, aber leicht zu behandeln.
Sie lesen also in einem Buch über Visual C++ 6, wie Sie in Ihre Applikation einen Dialog einbauen können - und tun es. In diesem Dialog soll der Benutzer also eine vorzeichenlose Ganzzahl eingeben können.
Wieso denn das nicht? Weil von der Tastatur ausschließlich eine Zeichenfolge kommen kann. Will er/sie/es eine Zahl eingeben, tippt er/sie/es mit irgendeinem Körperteil oder einem Werkzeug auf Zifferntasten - vielleicht kommt noch ein Punkt vor.
Tja, und Ziffern sind nun 'mal Zeichen und sonst gar nichts.
Das ist also nun geklärt. Ihre Applikation kriegt ausschließlich Zeichen 'rein. Deshalb ist die Variable, welche diese Eingabe aufnimmt ein (proprietäres) CString-Objekt. Und aus dem Inhalt dieses Objektes soll nun ein unsigned int Wert geholt werden.
Nun ja, lesen Sie sich erst 'mal fleißig schlau über die Klasse CString.
...
Nach vielleicht 2 Stunden stellen Sie resigniert fest: "Es gibt in CString nichts, was aus einem CString-Objekt ein unsigned int herausholt." Falls doch, lassen Sie es mich wissen!
Kleine Ergänzung (20.05.2003) auf Grund einer Lesermitteilung (Danke!):
Mit der C-Standardfunktion atoi() (ASCII to Integer) lässt sich
aus einem CString auf einfache Weise ein Ganzzahlenwert gewinnen.Beispiel:
CString Zahlenstring="12345"; Diese zweifelsfrei einfache Lösung ist allerdings nicht auf beliebige Datentypen anwendbar. Auch bietet sie letztlich keine Möglichkeit, definitiv eine Ausnahme festzustellen bzw. eine solche zu werfen. |
Aber da gibt es ja noch die wundervolle Standardbibliothek. Sie schöpfen also neue Hoffnung, und das zu Recht.
Was Sie hier brauchen können, ist ein "Eingabestrom für Zeichenketten", ein istringstream, von dem Sie später per Einleseoperator ">>" konvertierend die Ganzzahl einlesen können. Das CString-Objekt verwaltet einen Puffer, in welchem ein nullterminierter C-String gepflegt wird. Dieser alte und grundlegende Typ ist immer wieder die Kommunikationsbasis.
Nun legen Sie also ein istringstream-Objekt "iss" an. Was übergeben Sie dem Konstruktor? Hier geht als Zeichenfolge nur ein string-Objekt. Also fangen Sie vorsichtig an.
Der Dialog sei unter dem Namen dlg, dessen CString-Objekt unter m_Edit1 angelegt, zwei Namen von der Stange. Aber jetzt wird es wichtig!!!
Da gibt es einen Operator LPCTSTR, der zu einem CString-Objekt einen Nur-Lese-Zeiger auf dessen nullterminierten String liefert.
1. const char* sz = LPCTSTR(dlg.m_Edit1);
Nun können Sie also auf die nullterminierte Zeichenfolge von "m_Edit1" (=Eingabefeld nach OK) per sz lesend zugreifen. Der "Strom zum Einlesen von einer Zeichenfolge" (istringstream) braucht aber einen string.
No Problem. Legen Sie einfach einen solchen an.
2. string str(sz,dlg.m_Edit1.GetLength());Sie können ein string-Objekt konstruieren lassen mit einem nullterminierten String (sz) und der Angabe, wieviele Zeichen in dem string Platz finden sollen. Es sollen selbstverständlich alle Zeichen von "dlg.m_Edit1" übernommen werden, also dlg.m_Edit1.GetLength() viele.
Nun können Sie endlich das gewünschte istringstream-Objekt anlegen.
3. istringstream iss(str);
Jetzt wird's einfach. Ihre unsigned int-Variable, in die der Zahlenwert hineinsoll, möge Zahl heißen.
4. iss >> Zahl;"Schon drin? Drin! Das ist ja einfach."
Aber geht das nicht auch in kürzerer Form?
Es geht. Sie sollten dazu das Auspacken ein wenig üben.
Sie haben drei Packete: sz, str und iss
In sz steckt nichts anderes als LPCTSTR(dlg.m_Edit1).
Also ersetzen Sie in 2. "sz" durch "LPCTSTR(dlg.m_Edit1)".
2. string str(LPCTSTR(dlg.m_Edit1),dlg.m_Edit1.GetLength());
str ist ein mit string(LPCTSTR(dlg.m_Edit1),dlg.m_Edit1.GetLength()) angelegtes string-Objekt. Also ersetzen Sie in 3. "str" durch "string(LPCTSTR(dlg.m_Edit1),dlg.m_Edit1.GetLength())".
3. istringstream iss(string(LPCTSTR(dlg.m_Edit1),dlg.m_Edit1.GetLength()));Nun brauchen Sie die Zeilen 1. und 2. nicht mehr. Das war's.
Einen hab ich noch.
Wenn Ihnen das zu beschwerlich und unübersichtlich erscheint, verwenden Sie doch einfach das folgende
Präprozessor-Makro:
#define MAKE_ISS_CSTRING(miss,mcstr) \ istringstream miss(string(LPCTSTR(mcstr),mcstr.GetLength()))"miss" steht für den Namen des istringstream-Objektes und "mcstr" für den Namen des mit dem CString-Objekt zu verbindenden Eingabe-Stringstream. Nun genügen die folgenden Anweisungen zum Anlegen und Nutzen des istringstream-Objektes:
MAKE_ISS_CSTRING(iss,dlg.m_Edit1); iss >> Zahl;
Und weil Präprozessor-Makros nicht das Wahre sind, sollten Sie vielleicht besser das folgende Compiler-Makro verwenden:
inline istringstream iss_CString(CString& cs) {return istringstream(string(LPCTSTR(cs),cs.GetLength()));}Nun benötigen Sie nur noch die beiden folgenden erträglichen Anweisungen:
istringstream iss(iss_CString(dlg.m_Edit1)); iss >> Zahl;
Halt! Noch nicht abschalten! Da kommt noch 'was Leichteres.
Beim Öffnen des Dialogs soll vielleicht der aktuelle Wert von Zahl angezeigt werden (auch nicht schlecht). Dazu verwenden Sie entweder die Methode Format() des proprietären CString oder besser einen Ausgabe-String-Stream aus der Standardbibliothek. Ich zeige Ihnen hier das Bessere.
CMyDialog dlg; ostringstream oss; oss << Zahl; dlg.m_Edit1 = oss.str().c_str(); dlg.DoModal(); |
// Das isser, der Dialog. // Die Zwischenstation // Hinein mit dem Wert, aber als string. // CString akzeptiert keinen string. // Und nun auf die Bühne. |