zwei define-Strings zusammenfügen
-
Hallo,
ich habe die Adresse einer Seite als 2 #defines gespeichert#define URL "www.xxx.de" #define PORT 0815
Im Code brauche ich sie aber als URL:PORT. Würde die defines aber nur ungern zusammenlegen.
Im Code könnte ich nunCString ganzeAdresse(URL); ganzeAdresse.AppendFormat( _T(":%d"), PORT );
Aber sie so zusammenhängen, obwohl der komplette String schon bekannt ist, wäre auch doof. Dann würde es der Kompilier nicht mehr direkt ersetzen.
wie würde man das am geschicktesten machen?
Danke
-
#define URL_PORT (URL ## ":" ## PORT)
Hmm, oder nur ein #...ich bin da nicht mehr ganz fit
MfG SideWinder
-
SideWinder schrieb:
Hmm, oder nur ein #...ich bin da nicht mehr ganz fit
Es sind zwei.
-
Eigentlich
#define URL_PORT (URL ":" #PORT)
Erklärung: Der #-Operator macht aus dem Operanten ein String-Literal. Der generierte Code wäre dann
("www.xxx.de" ":" "0815")
. Die Literale baut dir der Präprozessor zu einem Literal zusammen.Der ##-Operator würde zwei Bezeichner zu einem verketten. Aus
A ## B
wird dannAB
. Bei SideWinders Code würde also("www.xxx.de"":"0815)
rauskommen.
-
1. Define-Strings gibt es eigentlich nicht. Makros haben keinen Datentyp und sind nur eine dumme Zeichenkettenersetzung. Sie werden vor der Compilierung in die entsprechenden Codestellen eingefügt.
2. CString ist mit Sicherheit nicht C++/C++0x, wohl eher MFC (wofür ein eigenes Forum existiert). Sprich zumindest was das zusammensetzen etc. angeht, wird man dir hier kaum irgendwas mit CString erklären.
Aus 1. leitet sich bereits ab, das der gesamte String eben noch nicht bekannt ist (Zumal auch der Port nicht in Anführungsstrichen steht), du wirst hier kaum um ein Zusammensetzen herum kommen. Des weiteren würde ich keine Makros für Konstantendefinitionen verwenden, dafür gibt es const (das zudem noch Typsicher ist).
-
Hm, es ist doch etwas komplizierter als meien Variante. Korrekt ist es so:
#define URL "..:" #define PORT 1234 #define STR2(x) #x #define STR(x) STR2(x) #define URL_PORT (URL ":" STR(PORT))
-
Danke für die Antworten
Also dass der Port nicht in "" steht ist nicht so wichtig, kann ihn auch "" machen.
Habe vorher nen Code von einem Kollegen angeschaut und der hat den Port als uint gespeichert, weshalb ich es bei mir im define ohne "" geschrieben habe.Aus dem Gleichen Grund stand CString da. Hat aber so gar nichts mit MFC zu tun. Die Methode erwartet eh LPCTSTR.
Adresse und Port stehen auch von Anfang an fest.
Ich habe nun auch den Port als String geschrieben und
#define URL_PORT (URL ":" PORT)
verwendet.
Der Methode übergebe ich es nun mit (LPCTSTR) URL_PORT.
Ob das so gut ist, weiß ich nicht. Zumindest zeigt er beim Kompilieren keine Fehlermeldung.
-
Der Cast ist nicht gut, mache lieber
_T(URL_PORT)
.
-
Die Klammern um
#define URL_PORT (URL ":" STR(PORT))
sind unnötig; String-Tokens werden zusammengesetzt, bevor irgendwelche Operatoren eine Rolle spielen. Die Klammern bringen nichts, verhindern aber weiteres zusammensetzen, etwa
URL_PORT "/foo/bar.hml"
Ganz generell werden Strings, die direkt hintereinander stehen, vor der eigentlichen Kompilation zu einem Literal verschweißt. Es ist problemlos möglich,
std::cout << "Hallo, das ist\n" "ein mehrzeiliges\n" "String-Literal,\n" "das selbst auf\n" "einem Handy pro-\n" "blemlos anzeigbar\n" "sein sollte\n";
zu schreiben.
-
ipsec schrieb:
Der Cast ist nicht gut, mache lieber
_T(URL_PORT)
.wenn ich dies hinschreibe kommt die Fehlermeldung beim Kompilieren: error C3861: "L":Bezeichner wurde nicht gefunden.
Ich weiß nicht was er mit dem Bezeichner L meint, es kommt nicht mal ein L irgend wo vor.
Ohne _T funktioniert es
wenn ich anstelle #define URL_PORT (URL ":" PORT) das ganze direkt hinschreibe, also#define URL_PORT "www.xyz.de:0815"
dann funktioniert es
-
Jap, lass bei der Definition des URL_PORT-Makros die umschließenden Klammern weg, die stören hier.
Erklärung: er expandiert es z.B. zu "www.sonstwas.de:1234". Bei Unicode sollte es aber L"www.sonstwas.de:1234" sein. Das _T-Makro ist dann etwas so definiert:#ifdef UNICODE #define _T(x) L##x #else #define _T(x) x #endif
Und da stören natürlich die Klammern um den String.
Wenn du das _T weglässt, knallst du bei Unicode möglicherweise auf die Nase, da du im prinzip char* hart (mit C-Cast) in wchar_t* castest. Datenmüll könnte die Folge sein.
-
Hallo,
ich nutze kurz nochmal meinen alten Thread für eine Frage:Kann ich von einem Define String die Länge auslesen?
ich speichere im Moment die Konstante nochmals in eine std::string Variable, um dann Variable.length() ausfuehren zu koennen. Da die Konstanten ja aber vorm Kompilieren schon feststehen würde es mir besser gefallen, wenn ich die Laenge vielleicht auch als Konstante ermitteln könnte. (ja ich könnte sie selber zählen und daraus wieder eine Konstante machen aber das ist beim Abändern der Konstanten suboptimal).
Danke
-
Der Präprozessor kennt den Typ nicht. Er ersetzt einfach alle Vorkommnisse des Namens des Makros durch den Inhalt des Makros.
-
Da das Stringliteral ein Array ist, geht
template<std::size_t N> std::size_t length(char(&)[N]) { return N; }
Das sollte der Compiler auch inlinen.
-
Schlicht
sizeof(URL_PORT)
langt schon. Das lässt sich dann auch für Größenangaben von Arrays oder Template-Parameter verwenden. Obacht: Wenn du die String-Länge haben (also den Null-Terminator nicht mitzählen) willst, musst du eins abziehen:
sizeof(URL_PORT) - 1