Was sagt der C++ Standard zu toupper



  • Habe folgendes Testprogramm geschrieben:

    #include <vector>
    #include <string>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    
    bool up_case_comp(const string& s1,const string& s2)
    {
    	string i1 = s1;
    	transform(i1.begin(),i1.end(),i1.begin(), _toupper);
    	string i2 = s2;
    	transform(i2.begin(),i2.end(),i2.begin(), _toupper);
    	return  i1.compare(i2) < 0;
    }
    
    int main()
    {
    	vector<string> theList;
    	theList.push_back("alice");
    	theList.push_back("Hello");
    	theList.push_back("below");
    	theList.push_back("hello");
            sort(theList.begin(), theList.end(), up_case_comp);
            vector<string>::const_iterator it;
    	for(it = theList.begin(); it != theList.end(); it++)
    		cout << *it << endl;
    	return 0;
    }
    

    Output schrieb:

    alice
    below
    Hello
    hello

    wenn ich mit g++ 3.3.5 kompiliere. Soweit so gut.
    Kompiliere ich den gleichen Code aber mit MSVC 6.0 erscheint der Output unsortiert. Hmm. 😕
    Jetz habe ich in meiner up_case_comp() _toupper mit toupper ersetzt.
    Juhuu Output ist sortiert. wahrscheinlich ist _toupper nicht Standardkonform.
    Jetzt mache ich den Quercheck und compiliere die Version mit toupper mit g++. Das kompiliert nicht mal. Scheinbar gibt es in den headern von g++ gar keine funktion toupper die zu transform kompatibel ist.

    wenn ich eine funktion

    int mytoupper( const int & c ) {
       return toupper(c);
    }
    

    verwende dann funktioniert es wieder.
    Bin ich über ein nicht Standardkonformität bei beiden g++ und MSCV6.0 gestolpert ?
    Kurt



  • toupper ist standardkonform, _toupper nicht.



  • waren nicht alle Bezeichner mit _ oder __ Compilerabhänig ?



  • SeppSchrot schrieb:

    toupper ist standardkonform, _toupper nicht.

    Heisst das jetzt g++ ist der Böse, oder könnte es ein vom Standard nicht geregeltes Implementationsdetail sein dass toupper nicht mit transform kompatibel ist ?
    Kurt



  • beim g++ bis 3.4 gab es bei toupper irgend ein Problem. Ich glaub das war als Macro implementiert oder so etwas. Naja, nimm einfach g++ 3.4 oder 4.0 🙂



  • kingruedi schrieb:

    beim g++ bis 3.4 gab es bei toupper irgend ein Problem. Ich glaub das war als Macro implementiert oder so etwas. Naja, nimm einfach g++ 3.4 oder 4.0 🙂

    Danke. Jetzt habe ich endlich einen Grund auf 3.4 umzusteigen.
    Kurt



  • Scheinbar gibt es in den headern von g++ gar keine funktion toupper die zu transform kompatibel ist.

    Da irst du dich. transform erwartet keinen festen Typ. Der letzte Parameter ist ein Template-Parameter und wird beim Aufruf passend hergeleitet. Und hier genau ist jetzt das Problem. Im Namespace std gibt es mehr als eine toupper-Funktion. Aus diesem Grund ist:

    transform(i1.begin(),i1.end(),i1.begin(), toupper);
    

    schlicht mehrdeutig und damit kein gültiges C++.

    Die logische Alternative:

    transform(i1.begin(),i1.end(),i1.begin(), static_cast<int (*)(int)>(toupper));
    

    wiederum ist nicht portabel, da der C++ Standard keine festen Signaturen vorschreibt.

    Die standkonforme und portable Lösung ist die Variante mit mytoupper. Wenn du jetzt noch das char <-> unsigned char <-> int Problem (das ich hier jede Woche mindestens einmal erkläre) berücksichtigst, dann wird's am Ende sogar korrekt.



  • Wenn du es jede Woche min. einmal erklärst, wieso tust du es nicht dann in dein C++ FAQ auf deiner Seite? (Auch wenn ich garnicht weiß, worum es bei dem Problem geht ;))



  • gute frage 🤡 👍



  • Brutus schrieb:

    Wenn du es jede Woche min. einmal erklärst, wieso tust du es nicht dann in dein C++ FAQ auf deiner Seite? (Auch wenn ich garnicht weiß, worum es bei dem Problem geht ;))

    Weil mir schlicht kein guter Titel einfällt. Ein Titel wie "Was muss man bei der Benutzung von Character-Classification und -Conversion-Funktionen wie z.B. tolower beachten?" hört sich für den vorbeistreifenden Leser imo etwa so an: Bla Bla Bla, Langweilig, Bla Bla?



  • Schreib am Anfang

    #include <cctype>
    

    dazu. Dann gibts auch toupper.



  • HumeSikkins schrieb:

    Brutus schrieb:

    Wenn du es jede Woche min. einmal erklärst, wieso tust du es nicht dann in dein C++ FAQ auf deiner Seite? (Auch wenn ich garnicht weiß, worum es bei dem Problem geht ;))

    Weil mir schlicht kein guter Titel einfällt. ...

    Wie wär's den mit

    HumeSikkins schrieb:

    ...das char <-> unsigned char <-> int Problem...

    ? 😃
    evtl. noch "... und toupper/tolower" dahinter ...

    Gruß,

    Simon2.


Anmelden zum Antworten