Problem mit der Funktion "tolower" aus ctype.h



  • Sorry, aber ich hab gerade gesehen, dass ich wieder fälschlicherweise ins c++ Forum geschrieben habe. Ich programmiere eigentlich C aber mit der "Ergänzung" unseren Profs, dass wir cout als einzigen Bestandteil von C++ benutzen sollen. Könntest du vielleicht verschieben?

    Ich hab mir Funktionenaufruf angesehen. Ich kann's ja eigentlich auch. Hier ein kleines Beispiel. Ich weiß nur nicht warum das mit der tolower-Funktion nicht geht...

    Mein Beispiel:

    #include<iostream>
    #include<ctype.h>
    using namespace std;
    
    int func(int x, int y)
    {
        int ergebnis;
        ergebnis = x+y;
    }
    
    int main()
    {
     int a, b;
    
     cin >> a >> b;
    
     cout << func(a, b);
    
    system("pause");
    return 0;
    }
    


  • Das hier ist Jochen S. Code:

    #include<iostream>
    #include<ctype.h>
    using namespace std;
    
    char func(char c)
    {
    return tolower(c);
    }
    
    int main()
    {
     char c;
    
     cin >> c;
    
     cout << func(c);
    
    system("pause");
    return 0;
    }
    

    Warum darf ich an der Stelle "return tolower(c);" nicht "return tolower(char c);" schreiben? Ist das dann an der Stelle wie eine Doppeldeklaration?



  • bandchef schrieb:

    Ich hab mir Funktionenaufruf angesehen. Ich kann's ja eigentlich auch. Hier ein kleines Beispiel. Ich weiß nur nicht warum das mit der tolower-Funktion nicht geht...

    Nochmals: Weil du eine Funktionsdeklaration statt eines Funktionsaufrufs hingeschrieben hast.

    bandchef schrieb:

    Warum darf ich an der Stelle "return tolower(c);" nicht "return tolower(char c);" schreiben? Ist das dann an der Stelle wie eine Doppeldeklaration?

    Gesteh dir doch ein, dass dir hier noch einige Kenntnisse fehlen. Lies das Kapitel nochmals nach, das beschreibt, wie Funktionen deklariert, definiert und aufgerufen werden. Du verwechselst hier einiges.

    Rochen schrieb:

    Der Vollständigkeit halber: so macht man es in C++

    Das Template finde ich etwas übertrieben.



  • Du hast recht, ich werde mir diesbezüglich nochmals meine Übungen durchschauen. Ich will hier übrigens ein Programm schreiben, dass mir Zeichenketten auf Gleichheit überprüft. Ich melde mich später dazu wieder wenn ich die Funktionsaufrufe besser drauf hab.



  • bandchef schrieb:

    Mein Beispiel:

    #include<iostream>
    #include<ctype.h>
    using namespace std;
    
    int func(int x, int y)
    {
        int ergebnis;
        ergebnis = x+y;
    }
    
    int main()
    {
     int a, b;
     
     cin >> a >> b;
     
     cout << func(a, b);
     
    system("pause");
    return 0;
    }
    

    Das funktioniert doch auch nicht!



  • Belli schrieb:

    Das funktioniert doch auch nicht!

    Vielleicht zufällig doch, undefiniertes Verhalten. Es ist hier durchaus denkbar, dass das berechnete Ergebnis in dem Register liegt, in dem auch die Rückgabe stehen würde, wenn es sie gäbe.



  • Ein moderner Compiler würde sowas nicht mal kompilieren.



  • Nexus schrieb:

    Ein moderner Compiler würde sowas nicht mal kompilieren.

    Ja, aber nur weil system nicht deklariert ist.
    Nimmt man diese Zeile raus, kommen Warnungen erst bei -Wall, kompillieren tut er es erst nicht mehr bei einem zusätzlichen -Werror. Mein Compiler ist `gcc version 4.4.5 (Debian 4.4.5-10)', ich sehe ihn als sehr modern an.



  • ModernerKompailerNutzer schrieb:

    Mein Compiler ist `gcc version 4.4.5 (Debian 4.4.5-10)', ich sehe ihn als sehr modern an.

    Ich hingegen sehe es als Bug an, wenn man in einer Funktion mit Rückgabewert int kein return -Statement haben muss.



  • Nexus schrieb:

    Ein moderner Compiler würde sowas nicht mal kompilieren.

    Du meinst, ein buggy Compiler? Was für einen Grund sollte ein Compiler sonst haben, sich mutwillig über den Standard hinwegzusetzen?



  • Ich dachte, das würde so im C++-Standard stehen, aber es ist tatsächlich "nur" undefiniertes Verhalten.

    Bashar schrieb:

    Du meinst, ein buggy Compiler? Was für einen Grund sollte ein Compiler sonst haben, sich mutwillig über den Standard hinwegzusetzen?

    Weil er auf diese Weise offensichtliche Fehler vermeidet, auch ohne dass dies im Standard explizit steht. Ich sehe nicht, wieso du das so dramatisch als "mutwillig darüber hinweggesetzt" bezeichnest. Ich bin sehr froh über gemeldete Fehler zur Kompilierzeit, hier schadet die Meldung wirklich nichts.

    Oder hast du etwa einen sinnvollen Anwendungsfall?



  • Es hindert dich niemand, deinen Compiler mit der Option -Werror=return-type aufzurufen, dann hast du deinen Error. Da ich davon ausgehe, dass du als errorphiler (fehlerliebender) Programmierer eh unter -pedantic -Wall -Wextra -Werror kompillierst, hast du das Problem gar nicht und kannst den nicht ganz so radiklen Programmierern die Freiheiten lassen, die C++ einem gewährt. Jedem das Seine.



  • Sinnvoll kann es dann sein, wenn der Programmier weiß, was er macht.

    int f1()
    {
    	_asm
    	{
    		mov eax, 20; <- Edit: Gewohnheitssemikolon
    	}
    }
    

    Einen anderen Fall kenne ich aber nicht.



  • ModernerKompailerNutzer schrieb:

    Da ich davon ausgehe, dass du als errorphiler (fehlerliebender) Programmierer eh unter -pedantic -Wall -Wextra -Werror kompillierst

    Nein, ich benutze Visual Studio.

    ModernerKompailerNutzer schrieb:

    hast du das Problem gar nicht und kannst den nicht ganz so radiklen Programmierern die Freiheiten lassen, die C++ einem gewährt. Jedem das Seine.

    Ja. Nur schade, dass diese Regel eine weitere unnötige Fehlerquelle in C++ ist, die Anfängern, welche standardmässig nicht 4 Spezialflags an g++ übergeben, Sorgen bereitet. Ich war jedenfalls schon ab und zu froh um diese Fehlermeldung.

    Vicious Falcon schrieb:

    Sinnvoll kann es dann sein, wenn der Programmier weiß, was er macht.

    int f1()
    {
    	_asm
    	{
    		mov eax, 20; <- Edit: Gewohnheitssemikolon
    	}
    }
    

    Einen anderen Fall kenne ich aber nicht.

    Lustig ist, dass VS genug intelligent ist, diesen Fall zu erkennen und keinen Fehler zu verursachen. Also genau wie es sein sollte 🙂

    Nicht immer ist alles schlecht, was sich nicht an den Standard hält. Es wäre zum Beispiel von Vorteil gewesen, hätten einige Standardbibliotheken den Bug von std::bind1st und std::bind2nd nicht implementiert. Naja, mit std::bind ist das Thema eh vom Tisch.



  • Nexus schrieb:

    Ich dachte, das würde so im C++-Standard stehen, aber es ist tatsächlich "nur" undefiniertes Verhalten.

    Aber auch nur, wenn die Ausführung tatsächlich das Ende der Funktion erreicht. In dem Beispiel mag das ja so sein, aber im Allgemeinen ist das gar nicht möglich, das zu erkennen.

    Einfaches Beispiel, um das zu verdeutlichen:

    bool p();
    void g();
    int f() {
      if (p())
        return 0;
      else
        g(); // kein return? ja, aber ... s.u.
    }
    
    void g() {
      throw 1;
    }
    

    Man kann also nicht in den Standard reinschreiben, dass der Compiler sowas erkennen muss. Und wenn man es auf die Fälle beschränkt, wo es möglich ist (geht das?), kann man es auch gleich sein lassen.

    Oder hast du etwa einen sinnvollen Anwendungsfall?

    Nö, aber darum geht es ja auch nicht.



  • Nexus schrieb:

    Lustig ist, dass VS genug intelligent ist, diesen Fall zu erkennen und keinen Fehler zu verursachen.

    Ja, der VC 6 hat immer noch eine Warnung ausgespuckt, die neueren MS-Compiler sind wirklich verdammt gut 👍 .



  • Bashar schrieb:

    Aber auch nur, wenn die Ausführung tatsächlich das Ende der Funktion erreicht. In dem Beispiel mag das ja so sein, aber im Allgemeinen ist das gar nicht möglich, das zu erkennen.

    Da sind wir uns völlig einig. Aber ich sagte ja: "Ich hingegen sehe es als Bug an, wenn man in einer Funktion mit Rückgabewert int kein return -Statement haben muss." Und da hat es ein return . Sobald ein return oder throw in der Funktion vorkommt, kompiliert der Code auch unter VS. Hingegen kann eine Funktion, die immer eine Exception wirft, ruhig void als Rückgabetyp haben.

    Falls man doch dem Fall begegnet, in dem man unbedingt einen Rückgabetyp ohne Rückgabewert haben muss, kann man den Fehler immer noch zu einer Warnung umwandeln. Das finde ich um einiges sinnvoller, als in 99% der Fälle Programmfehler kompilieren zu lassen.



  • Nexus schrieb:

    Aber ich sagte ja: "Ich hingegen sehe es als Bug an, wenn man in einer Funktion mit Rückgabewert int kein return -Statement haben muss." Und da hat es ein return .

    In einer Verzweigung ja, in der anderen nicht. Wenn dich stört, dass g immer wirft, kannst du das Beispiel beliebig komplizierter machen, z. B. als nächste Stufe

    bool p();  // gibt abwechelnd true und false zurück
    void g();
    int f() {
      if (p())
        return 0;
      else
        g(); // kein return? ja, aber ... s.u.
    }
    
    void g() {
      if(p())
        throw 1;
    }
    


  • Hast du meinen letzten Beitrag noch gesehen? Ich glaube nämlich, da bin ich auf diese Fälle mehr oder weniger eingegangen. 😉


Anmelden zum Antworten