Array of Boolean lässt sich nicht ändern



  • Hallo zusammen,
    seit nun ca. 1 Woche bin ich dabei mir C++ beizubringen.
    Jetzt bin ich bei einem Programm, dass mir Primzahlen zwischen zwei Grenzen (a= Untergrenze, b=Obergrenze) liefern soll auf ein Problem gestoßen:

    Sobald die folgende Procedure einen Teiler findet (was funktioniert), soll sie den Array an der betreffenden Stelle auf false ändern (Das funktioniert nicht).

    Hier der betreffende Abschnitt:

    bool primzahlenFinden (int a, int b) {
    
        bool hilfsarray [(b-a)];
        int hilf;
        for ( hilf=2; hilf<128;hilf++) {
            hilfsarray[hilf]=1;
        }
        for ( ; a<=b ; a++) {
    //        cout << "\na = " << a;
            for (hilf=2;hilf<a;hilf++) {
    //            cout << "\nhilf = " << hilf;
    //            cout << "\n" <<a<<" % "<<hilf<<" = " << (a % hilf);
                if (a % hilf == 0) {
    //                cout << "\nhilfsarray["<<a<<"] davor  = " << hilfsarray[a];
                    hilfsarray[a]=false;
    //                cout << "\nhilfsarray["<<a<<"] danach = " << hilfsarray[a];
                }
            }
        }
        return hilfsarray;
    }
    

    Wenn ihr die "//" am Anfang einiger Zeilen entfernt, könnt ihr glaub ich ganz gut seh'n, was nicht klappt 😉

    Hoffe, das war jetzt einigermaßen verständlich 😉

    Gruß Jörg



  • Kurz noch eine andere Frage: Wie heißt deine C++-Literatur?



  • Das soll kompilieren? C++ kennt keine Arrays dynamischer Größe. Dann ist der Rückgabetyp deiner Funktion auch noch "bool", du versuchst aber ein "bool*" zurückzugeben, auch noch auf Speicher, der nach der Funktion gar nicht mehr existiert. Zudem scheint mir eine Funktion, die wie folgt aufgebaut ist sinnvoller:

    std::vector<unsigned> get_prims(unsigned lower, unsigned upper)
    {
      std::vector<unsigned> prims;
      // füllen mit .push_back()
      return prims;
    }
    


  • Gugelmoser schrieb:

    Kurz noch eine andere Frage: Wie heißt deine C++-Literatur?

    Das Buch heißt C++ für Dummies.

    @cooky451:
    Das kann gut sein, dass das sinnvoller ist - nur verstehe ich das (noch) nicht. Wie gesagt bin ich erst seit einer Woche dran.
    Läuft übrigens ohne Fehler durch - tut halt nur nicht, was es soll.



  • Dann nutzt du einen ziemlich kaputten Compiler. Welchen?



  • Da kann dir gleich an mehreren Stellen was um die Ohren fliegen:

    Zeile 3:
    Das ist kein gültiger C++ Code, da Arraygrößen zur Übersetzungszeit bekannt sein müssen. a und b sind aber erst zur Laufzeit bekannt. Ausserdem führst du keine Überprüfung für b > a durch, wenn b < a ist wird´s schnell seltsam.

    Zeile 5+6
    Du gehst davon aus, dass dein Hilfsarray genau 128 Elemente hat. Wenn´s weniger hat erzeugst du undefiniertes Verhalten, weil du in Speicher schreibst, der dir nicht gehört. Wenn´s mehr hat sind nur die ersten 128 Elemente initialisiert, in den übrigen stehen Zufallswerte.

    Zeile 8:
    Du greifst auf Indizes zu, die mit Sicherheit außerhalb der Grenzen liegen. Die Nummerierung geht immer von 0..N-1. Wenn z.B. a = 7 und b = 10 geht deine Schleife von 7 bis 10 einschließlich.

    Zeile 20:
    Laut Signatur gibt die Funktion einen bool zurück, du gibts aber ein Array of bool zurück, da stimmt entweder der Rückgabetyp oder der Rückgabewert nicht.



  • cooky451 schrieb:

    Dann nutzt du einen ziemlich kaputten Compiler. Welchen?

    Das Programm heißt Code::Blocks. Der Compiler an sich heißt "GNU GCC".

    @Doc:

    Das mit den unbekannten Größen zur Compilezeit schien es gewesen zu sein. Ich habe jetzt alle Arrays auf 128 begrenzt und die Rückgabe angepasst - jetzt funktionierts 😉

    Vielen Dank



  • JörgK schrieb:

    Das mit den unbekannten Größen zur Compilezeit schien es gewesen zu sein. Ich habe jetzt alle Arrays auf 128 begrenzt und die Rückgabe angepasst - jetzt funktionierts 😉

    Nein, das Programm ist immer noch falsch. Zudem hast du deinen Compiler falsch konfiguriert, wenn er das Programm ernsthaft durchgelassen hat, so wie es oben steht.

    Bitte nenne alle deine Dateien *.cpp, und kompiliere mit: g++ -std=c++0x -pedantic -Wall. Danach poste dein Programm noch mal hier - ich ahne Fürchterliches! 😉

    Edit: Und dann lies auch die Compilerwarnungen.



  • cooky451 schrieb:

    g++ -std=c++0x -pedantic -Wall

    -Wextra wäre auch noch nicht schlecht. Und -Werror , damit er die Warnungen nicht einfach ignorieren kann.



  • Hallo,
    also die cpp Datei habe ich - das dahinter hab ich (nicht verstanden und deswegen) gegoogelt, aber ohne Erfolg.
    Vielleicht könntest du mir einfach sagen, warum mein Compiler es nicht hätte bearbeiten dürfen, damit ich's beim nächsten Mal besser machen kann 😉

    Ganz davon abgesehen, macht das Programm wieder nun nur noch Schwachsinn (Fragt mich nicht warum 😕 ). Ich glaube fast, dass es sinnvoller ist, wenn ich einfach noch mal von vorne anfange.

    Gruß Jörg



  • -Weffc++ 😃



  • wunreg schrieb:

    cooky451 schrieb:

    g++ -std=c++0x -pedantic -Wall

    -Wextra wäre auch noch nicht schlecht. Und -Werror , damit er die Warnungen nicht einfach ignorieren kann.

    Ich habe nie irgendwelche Warnungen igonriert. Mein Programm hat einfach in der jetzigen Version keine ausgegeben

    -------------- Build: Debug in primzahlen ---------------
    
    Compiling: main.cpp
    Linking console executable: bin\Debug\primzahlen.exe
    Output size is 588.48 KB
    Process terminated with status 0 (0 minutes, 0 seconds)
    0 errors, 0 warnings
    

    Alle Errors und Warnungen davor habe ich immer nach bestem Wissen behoben.

    ---
    Ich erstell mir jetzt besser einen Acc, damit keine Doppelposts mehr kommen



  • wunreg schrieb:

    cooky451 schrieb:

    g++ -std=c++0x -pedantic -Wall

    -Wextra wäre auch noch nicht schlecht. Und -Werror , damit er die Warnungen nicht einfach ignorieren kann.

    Vielleicht, als MSVC Nutzer habe ich erst mal nur das geschrieben, was mir eingefallen ist. Wobei ich meine mich zu erinnern, dass bei -Wextra manchmal komische Warnungen kommen, und als Anfänger möchte man das Programm ja zumindest mal testen, wenn man sich die Warnungen dann nicht später durchlesen kann (-Werror), kann das frustrieren.

    @JörgK
    Nicht von vorne anfangen, sondern aktuelles Programm posten.

    @JörgK schrieb:

    das dahinter hab ich (nicht verstanden und deswegen) gegoogelt, aber ohne Erfolg.

    Da du deine IDE nutzt, kannst du das bestimmt da einstellen. Irgendwie auf "Einstellungen->Compiler" oder so etwas, da kann man die Parameter sicher einstellen.

    Das erste Beispiel oben hätte nicht kompilieren dürfen, weil (wie schon erwähnt) die Größe von Arrays in C++ eine Compilezeitkonstante muss, und der Rückgabetyp der Funktion nicht zu dem passt, was du zurückgegeben hast.



  • cooky451 schrieb:

    @JörgK
    Nicht von vorne anfangen, sondern aktuelles Programm posten.

    @JörgK schrieb:

    das dahinter hab ich (nicht verstanden und deswegen) gegoogelt, aber ohne Erfolg.

    Da du deine IDE nutzt, kannst du das bestimmt da einstellen. Irgendwie auf "Einstellungen->Compiler" oder so etwas, da kann man die Parameter sicher einstellen.

    Das erste Beispiel oben hätte nicht kompilieren dürfen, weil (wie schon erwähnt) die Größe von Arrays in C++ eine Compilezeitkonstante muss, und der Rückgabetyp der Funktion nicht zu dem passt, was du zurückgegeben hast.

    1. Bittesehr:
    #include <cstdlib>
    #include <cstdio>
    #include <iostream>
    
    using namespace std;
    
    bool primzahlenFinden (int a, int b) {
    
        bool hilfsarray [128];
        int hilf;
        for ( hilf=0; hilf<128;hilf++) {
            hilfsarray[hilf]=1;
        }
        for ( ; a<=b ; a++) {
    //      cout << "\na = " << a;
            for (hilf=2;hilf<a;hilf++) {
    //          cout << "\nhilf = " << hilf;
    //          cout << "\n" <<a<<" % "<<hilf<<" = " << (a % hilf);
                if (a % hilf == 0) {
    //              cout << "\nhilfsarray["<<a<<"] davor  = " << hilfsarray[a];
                    hilfsarray[a]=false;
    //              cout << "\nhilfsarray["<<a<<"] danach = " << hilfsarray[a];
                }
            }
        }
        return hilfsarray [128];
    }
    
    int main()
    {
        int i;
        int untereGrenze;
        int obereGrenze;
    
        cout << "Geben Sie die Grezen an, in denen nach Primzahlen gesucht  werden soll!" << endl;
        cout << "Untere Grenze: ";
        cin >> untereGrenze;
        cout << "Obere Grenze: ";
        cin >> obereGrenze;
    
        bool primarray[128];
        primarray[128] = primzahlenFinden(untereGrenze, obereGrenze);
        for (i=untereGrenze;i<=obereGrenze;i++) {
            if ( not primarray[i] ) {
                cout << i << "\n";
            }
        }
        system("PAUSE");
        return 0;
    }
    
    1. Das mit dem std scheint er nicht zu verstehen:
    -------------- Build: Debug in primzahlen ---------------
    
    mingw32-g++.exe -Wall -fexceptions  -g     -c "W:\Eigene Dateien\Eigene Dokumente\C++ Code\Conversion\primzahlen\main.cpp" -o obj\Debug\main.o -std=c++0x -pedantic -Wall
    cc1plus.exe: error: unrecognized command line option "-std=c++0x"
    Process terminated with status 1 (0 minutes, 0 seconds)
    0 errors, 0 warnings
    


  • Lass das std=c++0x weg. Ist nicht so wichtig.

    Du fällst schon wieder auf eine Eigenheit von Arrays rein: Man kann sie nicht zurückgeben. Ich empfehle dir, in deinem Buch weiterzulesen, bis du bei std::vector<> angelangt bist. Mit dem geht das nämlich.

    Du solltest die Funktionssignatur so wählen:

    void primzahlenFinden (int a, int b, bool hilfsarray [128])
    

    Und dann aufrufen mit

    primzahlenFinden(untereGrenze, obereGrenze, primarray);
    

    BTW @pyhax: Weffc++ warnt, wenn man privat von boost::noncopyable erbt 👎



  • Ja, -Weffc++ ist nicht immer sinvoll, deswegen nehme ich dazu immer noch -Wno-error=effc++ und -Wno-error=unused-parameter 🙂



  • Wunreg schrieb:

    Du solltest die Funktionssignatur so wählen:

    void primzahlenFinden (int a, int b, bool hilfsarray [128])
    

    Und dann aufrufen mit

    primzahlenFinden(untereGrenze, obereGrenze, primarray);
    

    Gut, ich weiß, dass ich noch nicht viel weiß, aber müsste ich nicht, wenn ich nichts zurückgebe mit Zeigern arbeiten ?
    So wie oben übergebe ich noch nur die Werte in primArray, ohne, dass diese dann geändert würden, oder?



  • Hmm, das ist eine weitere Eigenheit von Arrays: Als Parameter sind sie immer Zeiger.
    Aber mit Zeigern geht es genauso, nur gehört es dann stilistisch dazu, ihre Grösse mit zu übergeben. Ändere das dahingehend, wenn du willst.



  • Wunreg schrieb:

    Du solltest die Funktionssignatur so wählen:

    void primzahlenFinden (int a, int b,bool hilfsarray [128])
    

    Welchen Sinn soll es haben, das hilfsarray mit einer Größenangabe zu versehen?



  • Hab's jetzt wie folgt abgeändert:

    // wie bisher...
    void primzahlenFinden (int a, int b, bool hilfsarray[128]) {
    int hilf; 
    //wie bisher
    }
    int main() {
    //wie bisher
        bool primarray[128];
        primzahlenFinden(untereGrenze, obereGrenze, primarray);
    //wie bisher
    }
    

    Nun funktioniert alles wie es soll und es gibt auch mit den Parametern keine Errors oder Warungen.

    Vielen Dank.


Log in to reply