Elegante Lösung für Strings mit Defines



  • Hi!

    Gibt es eine elegante Lösung, um einen zentral definierten String mir einem lokal vorgegebenen zu konkatenieren?

    Z.B.:

    #define OUTDIR ((wchar_t*)argv[2])
    ...

    copyFile("install.reg", OUTDIR "\\install2.reg");

    funktioniert so nicht...

    Ich könnte es zwar über

    wchar_t* file = OUTDIR;

    file = wcsncat(file , "\\install.reg", sizeof("\\install.reg") );

    lösen, aber das ist nicht besonders kompakt... (vor allem bei vielen wiederholten Aufrufen).

    Hat das jemand eine elegante Lösung mit Defines?

    MfG

    Matg40



  • Es gibt eine Lösung ohne den Präprozessor zu verwenden. Die Typendefinition von std::basic_string nämlich: std::wstring.

    grüße



  • Diese automatische Verkettung, die du dort ausnutzen willst, klappt nur mit String-Literalen und nicht mit Variablen (die Ansätze zum Whitespace-Overloading haben sich leider als Aprilscherz entpuppt :D).

    Du könntest eventuell umsteigen auf std::string bzw. std::wstring anstelle von char*/wchar_t*):

    #define OUTDIR(file) (string(argv[2]) + file).c_str();
    
    CopyFile("install.reg",OUTDIR("\\install2.reg"));
    

    (eventuell könntest du dir auch auf CString-Basis etwas zusammenbauen)

    PS: Bitte entscheide dich zunächst einmal, ob du mit char oder wchar_t arbeiten willst - so eine bunte Kombination ist selten besonders gesund.



  • Hi!

    Erst mal vielen Dank für die schnellen Lösungen !!!

    Ich habe jetzt nur noch ein Problem: von 'const unsigned short *' zu 'char *' zu kommen.

    Beim einfachen Cast ( (char*) wideString.c_str() ) wird nur das erste Zeichen verwendet.

    Ich habe (vereinfacht) folgenden Code:

    wstring wideString = wstring((wchar_t*)argv[3]);

    copyFile("install.reg", wideString.c_str() );

    Dabei hat er mit dem zweiten Parameter das Problem (copyFile erwartet zweimal char*) ....

    MfG

    Matg40



  • Wie gesagt, du solltest kein Mix aus char und wchar_t verwenden. Nutz die entsprechende Funktion.

    grüße



  • Wieso mischst du überhaupt UNICODE (wchar_t) mit ASCII (char)? Entscheide dich bitte für eins und ziehe diese Entscheidung konsequent durch.

    (wenn du wirklich char-Daten in einer UNICODE-Umgebung benötigst, mußt du entsprechende Typumwandlungen vornehmen, z.B. über CW2A())



  • Matg40! Es ist naiv zu glauben, das du durch einen Cast einen char-String in einen wide String umwandeln kannst. Das funktioniert leider nicht so einfach (schön wäre es ja). Du brauchst dafür eine vernünftige Konvertierungsroutine, die auch die locales beachtet und jedes einzelne char-Zeichen konvertiert (das macht ein Cast nicht!).

    Ich hatte mal im Internet das hier gefunden und es funktioniert sehr gut:

    /* string2wstring.h */
    #pragma once
    
    #include <string>
    #include <vector>
    #include <locale>
    #include <functional>
    #include <iostream>
    
    // Put this class in your personal toolbox...
    template<class E,
    class T = std::char_traits<E>,
    class A = std::allocator<E> >
    
    class Widen : public std::unary_function<
    	const std::string&, std::basic_string<E, T, A> >
    {
    	std::locale loc_;
    	const std::ctype<E>* pCType_;
    
    	// No copy-constructor, no assignment operator...
    	Widen(const Widen&);
    	Widen& operator= (const Widen&);
    
    public:
    	// Constructor...
    	Widen(const std::locale& loc = std::locale()) : loc_(loc)
    	{
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6.0...
    		using namespace std;
    		pCType_ = &_USE(loc, ctype<E> );
    #else
    		pCType_ = &std::use_facet<std::ctype<E> >(loc);
    #endif
    	}
    
    	// Conversion...
    	std::basic_string<E, T, A> operator() (const std::string& str) const
    	{
    		typename std::basic_string<E, T, A>::size_type srcLen =
    			str.length();
    		const char* pSrcBeg = str.c_str();
    		std::vector<E> tmp(srcLen);
    
    		pCType_->widen(pSrcBeg, pSrcBeg + srcLen, &tmp[0]);
    		return std::basic_string<E, T, A>(&tmp[0], srcLen);
    	}
    };
    
    // How to use it...
    int main()
    {
    Widen<wchar_t> to_wstring;
    std::string s = "my test string";
    std::wstring w = to_wstring(s);
    std::wcout << w << L"\n";
    }
    

    Ich lege mir diese Headerdatei in jedes Projekt, das ich neu anlege. Die main() kommentiere ich dann einfach aus. Wenn du eine eigene Library-Sammlung hast, leg sie da am besten gleich mit rein.

    Und wie von meinen Vorrednern bereits gesagt: entscheide dich für std::string oder std::wstring in deinen Programmen.



  • Artchi schrieb:

    [...]entscheide dich für std::string oder std::wstring in deinen Programmen.

    IMHO muss man beachten, dass Unicode (also std::wstring/wchar_t) nicht für Win95/98/Me zur Verfügung steht!


Anmelden zum Antworten