Sortierung eines Vektors mit Umlauten und Klein-/Großbuchstaben



  • Hallo,

    ich habe eine Struktur mit string-Variablen, aus der ich einen Vektor erzeuge. Diesen Vektor fülle ich und dann sortiere ich ihn mittels Definition des Standard-Operators < nach einer der string-Variablen mit der sort()-Funktion. Das klappt so weit auch schon, leider befinden sich jedoch Wörter mit Umlauten sowie kleingeschriebene Wörter stets am Ende der Liste. Diese sollten jedoch innerhalb der Liste korrekt einsortiert werden.

    Wie lässt sich das am einfachsten bewerkstelligen?

    Gruß,
    Jan



  • indem du für den comparator für sort lexicographical_compare mit einem entsprechenden character-Comparator benutzt. den könntest du vermutlich mit dem collate-facet der richtigen locale hinbekommen.

    http://www.cplusplus.com/reference/algorithm/lexicographical_compare/
    http://www.cplusplus.com/reference/std/locale/collate/



  • Hallo pumuckl...lexicographical_compare verstehe ich ja halbwegs, zumindest sortiert das Programm jetzt anders(Umlaute am Anfang der Liste anstatt am Ende), die kleinbuchstaben sind aber immer noch ganz hinten:

    return lexicographical_compare(lhs.Bezeichnung.begin(), lhs.Bezeichnung.end(), rhs.Bezeichnung.begin(), rhs.Bezeichnung.end());
    

    Aber wie genau funktioniert das mit dem collate? Ich habe zwar einen Beispielcode mit compare() gefunden, aber das Programm sortiert dann irgendwie völig kreuz und quer...

    locale loc;
    	const collate<char>& coll = use_facet<collate<char> >(loc);
    	return coll.compare(lhs.Bezeichnung.data(), lhs.Bezeichnung.data()+lhs.Bezeichnung.length(), rhs.Bezeichnung.data(), rhs.Bezeichnung.data()+rhs.Bezeichnung.length());
    

    Irgendwie ist mir noch nicht so ganz klar, wie ich meine Vektoren-Strings sortieren kann... 😕

    Gruß,
    Jan



  • Mr. Speck schrieb:

    Hallo pumuckl...lexicographical_compare verstehe ich ja halbwegs, zumindest sortiert das Programm jetzt anders(Umlaute am Anfang der Liste anstatt am Ende), die kleinbuchstaben sind aber immer noch ganz hinten:

    return lexicographical_compare(lhs.Bezeichnung.begin(), lhs.Bezeichnung.end(), rhs.Bezeichnung.begin(), rhs.Bezeichnung.end());
    

    Aber wie genau funktioniert das mit dem collate? Ich habe zwar einen Beispielcode mit compare() gefunden, aber das Programm sortiert dann irgendwie völig kreuz und quer...

    locale loc;
    	const collate<char>& coll = use_facet<collate<char> >(loc);
    	return coll.compare(lhs.Bezeichnung.data(), lhs.Bezeichnung.data()+lhs.Bezeichnung.length(), rhs.Bezeichnung.data(), rhs.Bezeichnung.data()+rhs.Bezeichnung.length());
    

    Irgendwie ist mir noch nicht so ganz klar, wie ich meine Vektoren-Strings sortieren kann... 😕

    Gruß,
    Jan

    dann guckst du noch mal den Link an und siehst, dass du die Fkt-Überladung nehmen musst:

    template <class InputIterator1, class InputIterator2, class Compare>
      bool lexicographical_compare ( InputIterator1 first1, InputIterator1 last1,
                                     InputIterator2 first2, InputIterator2 last2,
                                     Compare comp );
    

    und comp dann halt so aussieht:

    #include <string> //std::char_traits
    #include <locale> //std::locale -> std::islower, std::isupper, std::tolower, std::toupper
    
    template<typename TChar,
             typename TCharTraits = std::char_traits<TChar>,
             typename TLocale = std::locale
    >
    struct compare_ignoring_case
    {
    private:
      static bool is_lower(TChar value)
      {
        return std::islower(value, locale_type());
      }
    
      static bool is_upper(TChar value)
      {
        return std::isupper(value, locale_type());
      }
    
      static void make_lower(TChar &val)
      {
        val = std::tolower(val, locale_type());
      }
    
      static void make_upper(TChar &val)
      {
        val = std::toupper(val, locale_type());
      }
    
      static void make_compareable(TChar &lhs, TChar &rhs)
      {
        if(islower(lhs))
        {
          if(isupper(rhs))
            make_lower(rhs);
          return;
        }
    
        if(isupper(lhs))
        {
          if(islower(rhs))
            make_upper(rhs);
          return;
        }
      }
    public:
      typedef TCharTraits traits_type;
      typedef TLocale locale_type;
    
      bool operator() (TChar lhs, TChar rhs) const
      {
        make_compareable(lhs, rhs);
        return traits_type::lt(lhs, rhs);
      }
    };
    

    anwendung:

    #include <algorithm>
    #include <cstdlib> //für quick and dirty konsole offen halten
    #include <iostream>
    #include <string>
    
    //#include "my_string_comparer.h"
    
    bool string_lesser(const std::string &lhs, const std::string &rhs)
    {
    	return lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), compare_ignoring_case<char>());
    }
    
    int main()
    {
      std::string a = "ASD", b = "asd";
      std::cout << std::boolalpha << string_lesser(a, b) <<
    	  " == " << string_lesser(b, a) << std::endl;
    
      system("PAUSE"); //nicht nachmachen, weil unportabel etc - siehe konsole faq
    }
    

    MSVC schrieb:

    false == false

    sollte also funktionieren ;o)

    mir ist auf die schnelle auch kein (guter) kürzerer weg eingefallen, weil ich nicht sicher war, ob es sinnvoll ist nen eigenes char_traits zu schreiben(und halt von std::char_traits public erben lassen und dann die compare-fkt zu überdecken) - aber wenn groß und kleinschreibung interessiert(was ich angenommen habe), könnte es hier imho probleme geben)

    bb



  • habs gerad noch mal angeguckt(wollte ma gucken, was ß,S und was S,ß ergibt) und gesehen, dass ich nen ziemlich großen fehler drin hatte xD
    islower aufgerufen und wollte is_lower. und außerdem das locale-zeugs nicht berücksichtigt xD
    also müssen wir immer kleinbuchstaben nehmen, weil a<b && b<a doof ist 😉
    also jz der richtige code(nur die klasse, am aufruf ändert sich nix):

    #include <string> //std::char_traits
    #include <locale> //std::locale -> std::islower, std::isupper, std::tolower, std::toupper
    
    template<typename TChar,
             typename TCharTraits = std::char_traits<TChar>,
             typename TLocale = std::locale
    >
    struct compare_ignoring_case
    {
    public:
    	static bool uppercase;
    
    	typedef TCharTraits traits_type;
    	typedef TLocale locale_type;
    
    	explicit compare_ignoring_case(const locale_type& locale = locale_type())
    	:	locale(locale)
    	{}
    
    	bool operator() (TChar lhs, TChar rhs) const
    	{
    		make_compareable(lhs, rhs);
    		return traits_type::lt(lhs, rhs);
    	}
    private:
    	locale_type locale;
    
    	void make_compareable(TChar lhs, TChar rhs) const
    	{
    		if(uppercase)
    			make_compareable_upper(lhs, rhs);
    		else
    			make_compareable_lower(lhs, rhs);
    	}
    
    	void make_compareable_upper(TChar lhs, TChar rhs) const
    	{
    		if(is_lower(lhs))
    			make_upper(lhs);
    
    		if(is_lower(rhs))
    			make_upper(rhs);
    	}
    
    	void make_compareable_lower(TChar lhs, TChar rhs) const
    	{
    		if(is_upper(lhs))
    			make_lower(lhs);
    
    		if(is_upper(rhs))
    			make_upper(rhs);
    	}
    
    	bool is_lower(TChar value) const
    	{
    		return std::islower(value, locale);
    	}
    
    	bool is_upper(TChar value) const
    	{
    		return std::isupper(value, locale);
    	}
    
    	void make_lower(TChar &val) const
    	{
    		val = std::tolower(val, locale);
    	}
    
    	void make_upper(TChar &val) const
    	{
    		val = std::toupper(val, locale);
    	}
    };
    
    template<typename C, typename T, typename L>
    bool compare_ignoring_case<C, T, L>::uppercase = true;
    

    uppercase gibts, weil es auch nicht schaded, es einstellen zu können...
    der msvc9 optimiert es auch vollkommen raus - selbst wenn ich es später noch mal (anders) setze.
    ist nur doof, dass man es für jedes template einzeln setzen muss 😣
    eigtl würd ichs wieder rausnehmen - aber hier schadet es ja nicht, es mitzuposten^^

    randbemerkung:
    ('ß', 's') kann auf verschiedenen systemen (theoretisch) verschieden sein - aber das ist ja jeder aufruf(außer 2 buchstaben oder 2 ziffern).

    bb



  • Hallo,

    erstmal sorry für die späte Rückmeldung und vielen Dank für die Mühe...das Programm läuft bei mir leider aber noch nicht ganz fehlerfrei...

    "Übung" wird z.b. vor "Antwort" einsortiert, obwohl es eigentlich in die Nähe von "u" und nicht vor "a" gehört...laut Wikipedia gibt es bezüglich der Frage, wo genau es bei "u" einsortiert wird zwar auch noch diverse Möglichkeiten, aber ein "ü" vor dem "a" ist für mein Verständnis nicht richtig...die Umlaute sind demnach scheinbar trotz locale noch ein Problem...

    In Java gibt es dafür wohl so etwas wie eine "Sortier-Stärke":

    http://www.i-coding.de/www/de/java/liste/sortieren.html

    Ich hatte gehofft, dass es auch für C++ eine Lösung wie "Collator.SECONDARY" gibt, mit der man Umlaute und eventuell sogar Akzente wie "á" (gehört für mein Verständnis in die Nähe von "a") wie z.B in Excel korrekt sortieren kann...



  • Mr. Speck schrieb:

    "Übung" wird z.b. vor "Antwort" einsortiert, obwohl es eigentlich in die Nähe von "u" und nicht vor "a" gehört...laut Wikipedia gibt es bezüglich der Frage, wo genau es bei "u" einsortiert wird zwar auch noch diverse Möglichkeiten, aber ein "ü" vor dem "a" ist für mein Verständnis nicht richtig...die Umlaute sind demnach scheinbar trotz locale noch ein Problem...

    Japp, das ist klar, dass dies passiert - liegt einfach daran, dass ü im ascii-code eben nicht zwischen u und v liegt sondern (kA, wo vrmtl aber) vor dem a^^
    Gleiches gilt für ß...
    und das wird gleich noch mal ganz wo anders eingeordnet, wenn die buchstaben in caps verglichen werden (weil es nen extra zeichen für toupper('ß') gibt: 'SS' - wird zwar sicherlich nicht so geschrieben, aber so würde es aussehen und es ist nur ein zeichen^^)
    Würde aber relativ zu fixen gehen:
    typename TCharTraits = std::char_traits<TChar>, //uses TCharTraits::lt(TChar, TChar)
    steht in meinem code ja.

    wenn du also einfach so was baust:

    struct my_char_trait_lt
    {
      static bool lt(char lhs, char rhs)
      {
        lhs = get_char_next_to(lhs);
        rhs = get_char_next_to(rhs);
    
        return lhs < rhs;
      }
    private:
      static char get_char_next_to(char value)
      {
        switch (value)
        {
          case 'ü':
            return 'u';
          case 'Ü':
            return 'U';
          /*...*/
        }
        return value;
      }
    };
    

    nä. Problem(?): Üasd wird nicht bei Ueasd eingeordnet sondern bei Uasd

    und ich weiß nicht, was passiert, wenn nen franzose/russe/... das compiliert
    und ich weiß nicht, wer sich hinsetzen will und das für alle sonderzeichen machen will xD

    bb



  • Vielleicht ein wenig aufwändig, aber so sollte es funktionieren (ungetestet)

    int get_char_val(char a)
    {
        switch(a)
        {
            case 'a':
            case 'A':
            case 'à':
            case 'á':
            case 'À':
            case 'Á':
            case 'ä':
            case 'Ä': return 1; break;
    
            case 'b':
            case 'B': return 2; break;
    
            case 'c':
            case 'C': return 3; break;
    
            //usw
            default: return -1; break;
        }
    }
    
    //string compare verhält sich jetzt wie der < Operator
    bool string_compare(const std::string& a, const std::string &b)
    {
        for(std::string::const_iterator a_it=a.begin(), b_it=b.begin(), a_end=b.end(), b_end=b.end(); a_it != a_end && b_it != b_end; ++a_it, ++b_it)
        {
            int a_tmp = get_char_val(*a_it), b_tmp = get_char_val(*b_it);
            if( a_tmp < b_tmp )
                return true;
            if( ga_tmp > b_tmp )
                return false;
        }
        //wenn die strings bis hierhin gleich sind
        return a.size() < b.size();
    }
    
    int main()
    {
        std::vector<std::string> MeineStrings;
        sort(MeineStrings.begin(), MeineStrings.end(), string_compare); //sortieren
    }
    


  • soweit ich das beim überfliegen der Doku gesehen hatte haben die locales mit collate eine möglichkeit, chars anders zu vergleichen als nach ihrem ASCII-Wert. Ich würde dann erwarten dass umlaute bei einer derutschen locale entsprechend einsortiert werden. Vielleicht hab ich da die Möglichkeiten der locales aber auch überschätzt.



  • pumuckl schrieb:

    soweit ich das beim überfliegen der Doku gesehen hatte haben die locales mit collate eine möglichkeit, chars anders zu vergleichen als nach ihrem ASCII-Wert. Ich würde dann erwarten dass umlaute bei einer derutschen locale entsprechend einsortiert werden. Vielleicht hab ich da die Möglichkeiten der locales aber auch überschätzt.

    hatte ich anders verstanden:

    <a href= schrieb:

    http://www.cplusplus.com/reference/std/locale/collate/compare/">
    For the standard specialization of char and wchar_t the function returns the same as lexicographical_compare, which performs a character code (ASCII) comparison between the individual characters of both sequences, returning an alphabetical ordering for alphabetical strings.

    bb



  • Übrigens, weil ich es gerad zufällig gesehen habe...
    In den meinVZ-Seiten (was imho in Java geschrieben ist), wird auch so sortiert, wie ich das gepostet hab^^ (..., a..z, ..., ü_ä_ö)

    bb



  • pumuckl schrieb:

    soweit ich das beim überfliegen der Doku gesehen hatte haben die locales mit collate eine möglichkeit, chars anders zu vergleichen als nach ihrem ASCII-Wert. Ich würde dann erwarten dass umlaute bei einer derutschen locale entsprechend einsortiert werden. Vielleicht hab ich da die Möglichkeiten der locales aber auch überschätzt.

    Ich denke, das std::collate<> genau die richtige Baustelle ist. Der Trick besteht darin, jeden zu vergleichenden String in eine 'standardisierte Darstellung' zu konvertieren (etwa Ä->AE und ß->SS) und dann diesen entstanden String zu vergleichen. Ersteres passiert in der Methode collate<>::do_transform.

    Und so sollte es gehen:

    #include <algorithm>
    #include <locale>
    #include <iostream>
    #include <iterator>
    #include <numeric>
    #include <string>
    #include <vector>
    
    class Compare : public std::collate< char >
    {
    protected:
        virtual string_type do_transform( const char* low, const char* high ) const
        {
            const std::locale loc;
            string_type res;
            for( ; low != high; ++low )
            {
                char c = std::toupper( *low, loc );
                switch( c )
                {
                case 'Ä':
                    res.append( "AE" );
                    break;
                case 'Ö':
                    res.append( "OE" );
                    break;
                case 'Ü':
                    res.append( "UE" );
                    break;
                case 'ß':
                    res.append( "SS" );
                    break;
                default:
                    res.append( 1, c );
                }
            }
            return res;
        }
        virtual int do_compare( const char* low1, const char* high1,
             const char* low2, const char* high2 ) const
        {
            const string_type s1 = do_transform( low1, high1 );
            const string_type s2 = do_transform( low2, high2 );
            if( s1 == s2 )
                return 0;
            return s1 < s2? -1: 1;
        }
        virtual long do_hash( const char* low, const char* high ) const
        {
            const string_type tmp = do_transform( low, high );
            return std::accumulate( tmp.begin(), tmp.end(), long(0) );
        }
    };
    
    struct Foo // Mr. Specks struct, die einen string enthält
    {
        Foo( const std::string& name = "<noname>" )
            : m_name( name )
        {}
        bool operator<( const Foo& b ) const
        {
            return m_locale( m_name, b.m_name );
        }
        friend std::ostream& operator<<( std::ostream& out, const Foo& foo )
        {
            return out << foo.m_name;
        }
    
        std::string m_name;
        static std::locale m_locale;
    };
    
    std::locale Foo::m_locale = std::locale( std::locale(), new Compare );
    
    int main()
    {
        using namespace std;
        vector< Foo > v;
        v.push_back( Foo( "Übung" ) );
        v.push_back( Foo( "August" ) );
        v.push_back( Foo( "Straße" ) );
        v.push_back( Foo( "straße" ) );
        v.push_back( Foo( "augusT" ) );
        v.push_back( Foo( "ulm" ) );
    
        sort( v.begin(), v.end() );
        copy( v.begin(), v.end(), ostream_iterator< Foo >( cout, "\n" ) );
        cout << endl;
    
        return 0;
    }
    

    Natürlich lassen sich in do_transform noch weitere Zeichen - wie etwa 'á' - hinzufügen.

    Gruß
    Werner



  • 1. würdest du es auch so machen, werner? das muss doch iwie toller gehen, als alles einzeln anzugeben?!

    const std::locale loc; //standard locale
            string_type res; 
            for( ; low != high; ++low ) 
            { 
                char c = std::toupper( *low, loc ); //BÄM! bei allen (nationalen) sonderzeichen
                switch( c ) 
                { 
                case 'Ä': 
                    res.append( "AE" ); 
                    break; 
                case 'Ö': 
                    res.append( "OE" ); 
                    break; 
                case 'Ü': 
                    res.append( "UE" ); 
                    break; 
                case 'ß':  //ich glaube nicht, dass das richtig ist...
                    res.append( "SS" ); 
                    break;
    

    und vor allem: was passiert denn nun, wenn ich in meinem Windows keine deutsche Sprache habe sondern nur Französisch oder so?
    was passiert dann beispielsweise bei case 'Ä' ?
    ich meine - bei nem deutschen steht im compilat dann iwann case 123 -> "AE" oder so und bei nem franzosen ist #123 aber vll nen ô oder so...
    das kann doch nicht wirklich der richtige ansatz sein!?

    bb



  • unskilled schrieb:

    1. würdest du es auch so machen, werner? das muss doch iwie toller gehen, als alles einzeln anzugeben?!

    Ja - nach meinem Kenntnisstand ist das der Weg. Du kannst natürlich auch noch Tabellen aufstellen, so dass es vielleicht etwas eleganter aussieht; aber am Prinzip ändert das nichts.

    unskilled schrieb:

    const std::locale loc; //standard locale
            string_type res; 
            for( ; low != high; ++low ) 
            { 
                char c = std::toupper( *low, loc ); //BÄM! bei allen (nationalen) sonderzeichen
    

    Gut erkannt. Natürlich gehe ich davon aus, dass die hier verwendete Locale zum Rest des Codes passt.
    Besser wäre hier wahrscheinlich:

    const std::locale loc("german"); //deutsche locale
    

    unskilled schrieb:

    und vor allem: was passiert denn nun, wenn ich in meinem Windows keine deutsche Sprache habe sondern nur Französisch oder so?
    was passiert dann beispielsweise bei case 'Ä' ?
    ich meine - bei nem deutschen steht im compilat dann iwann case 123 -> "AE" oder so und bei nem franzosen ist #123 aber vll nen ô oder so...
    das kann doch nicht wirklich der richtige ansatz sein!?

    Für Französisch muss man ein französisches Compare schreiben. Das Sortieren hängt von der Sprache und vor allen vom verwendeten Zeichensatz ab.

    Gruß
    Werner



  • Werner Salomon schrieb:

    Für Französisch muss man ein französisches Compare schreiben. Das Sortieren hängt von der Sprache und vor allen vom verwendeten Zeichensatz ab.

    Hmm... Das stinkt ja...
    Déjà-vu und über müssen doch mit dem gleichen C++ Code verglichen werden können...
    Wird man wohl deine Lösung zusammen mit wide-strings nutzen müssen...

    bb



  • unskilled schrieb:

    Déjà-vu und über müssen doch mit dem gleichen C++ Code verglichen werden können...

    ja - mit einem Deutsch-französischen Compare 😉

    unskilled schrieb:

    Wird man wohl deine Lösung zusammen mit wide-strings nutzen müssen...

    Genauso ..

    Das Problem beim Sortieren ist doch zum einen das Groß-/Klein-Schreiben. Da kommt es darauf an, wie es der User gerne hätte und das zweite sind die Besonderheiten bei Zeichen wie ä bzw. á. Beide haben Zeichencodes die jenseits von a-z bzw. A-Z liegen, aber nach den nationalen Sortierungsgewohnheiten jeweils in die Nähe des a gehören. Und das muss man halt gesondert behandeln.

    Gruß
    Werner



  • Mit Windows-Funktionen klappt das übrigens ganz prima:

    #include <functional>
    #include <algorithm>
    #include <string>
    extern "C" {
      #include <windows.h>
    }
    
    struct Cmp: public std::binary_function<std::string &, std::string &, bool> {
    
      bool operator()(const std::string &lhs, const std::string &rhs) const {
        int rc = CompareString(LOCALE_USER_DEFAULT, 0, 
                               lhs.c_str(), -1, rhs.c_str(), -1);
        return rc == CSTR_LESS_THAN;
      }
    };
    
    int main(int argc, char *argv[]) {
    
      std::vector<std::string> strings;
      strings.push_back("Déjà-vu");
      strings.push_back("Bäche");
      strings.push_back("Ärger");
      strings.push_back("Bass");
      strings.push_back("Strass");
      strings.push_back("Bässe");
      strings.push_back("Degen");
      strings.push_back("Straße");
      strings.push_back("Ähre");
      strings.push_back("Destruktor");
      strings.push_back("Bär");
    
      strings.push_back("déjà-vu");
      strings.push_back("bäche");
      strings.push_back("ärger");
      strings.push_back("bass");
      strings.push_back("strass");
      strings.push_back("bässe");
      strings.push_back("degen");
      strings.push_back("straße");
      strings.push_back("ähre");
      strings.push_back("destruktor");
      strings.push_back("bär");
    
      std::sort(strings.begin(), strings.end(), Cmp());
      for(std::vector<std::string>::iterator iter = strings.begin();
          iter != strings.end(); ++iter) {
        CharToOem(iter->c_str(), const_cast<char *>(iter->c_str()));
        std::cout << *iter << std::endl;
      }
      return 0;
    }
    

    Gibt folgendes aus:

    ähre
    Ähre
    ärger
    Ärger
    bäche
    Bäche
    bär
    Bär
    bass
    Bass
    bässe
    Bässe
    degen
    Degen
    déjà-vu
    Déjà-vu
    destruktor
    Destruktor
    strass
    Strass
    straße
    Straße
    

    Das CharToOem() sorgt nur dafür, dass die Shell es auch anständig anzeigt.

    Ich muss sagen, dass ich, statt entsprechende Compare-Tabellen für alle möglichen Sprachen zu schreiben, lieber Funktoren für alle möglichen Betriebssysteme schreiben würde.

    Stefan.



  • jopp - da hast du definitiv recht ^^
    aber das kann ja auch keiner wissen, der die winapi nicht auswendig kennt ;o)

    btw:

    extern "C" {
      #include <windows.h>
    }
    

    wieso tust du das? imho ist das intern eh iwo(dort wo es halt nötig ist^^) mit #ifdef __cplusplus extern "C" { #endif geregelt - oder lieg ich da falsch?! (viel mehr als das es sie gibt weiß ich ja über die winapi auch nicht ;o))

    bb



  • unskilled schrieb:

    jopp - da hast du definitiv recht ^^
    aber das kann ja auch keiner wissen, der die winapi nicht auswendig kennt ;o)

    Ich kenn's auch nur, weil ich mich hundert Jahre lang mit dem C-Locale und Verwandten herumgeschlagen habe. Und irgendwann aufgegeben 😉

    Beispielsweise habe ich diese Sortiererei mit Standard-C++ auch versucht und bin gescheitert. Oder habe versucht herauszufinden, wie man mit Standard-C++ den Komma-Separator ermitteln kann. Dazu hatte ich hie auch mal eine Anfrage laufen und keiner wusste es.

    Das Windows-API ist in dieser Hinsicht sehr viel einfacher und übersichtlicher, also verwende ich jetzt immer die.

    unskilled schrieb:

    btw:

    extern "C" {
      #include <windows.h>
    }
    

    wieso tust du das? imho ist das intern eh iwo(dort wo es halt nötig ist^^) mit #ifdef __cplusplus extern "C" { #endif geregelt - oder lieg ich da falsch?! (viel mehr als das es sie gibt weiß ich ja über die winapi auch nicht ;o))

    bb

    Hab gerade mal nachgeschaut - allerdings nur flüchtig: In windows.h des GCC (MinGW) konnte ich sowas nicht finden, ebenfals nicht im Header des Visual Studio (2005). Keine Ahnung, ob es auch ohne extern "C" funktionieren würde. Ich mache das schon lange so - aus reiner Gewohnheit 😉

    Stefan.



  • Habe mir nicht alle Posts durchgelesen, aber vielleicht ist ja hier was dabei.


Anmelden zum Antworten