Anfängerproblemchen mit recht schwieriger Aufgabe



  • Nochmals vielen Dank für die zahlreichen Antworten.

    Leider komm ich zwischendrinne manchmal nicht mehr mit, da mir wahrscheinlich der Hintergrund fehlt. Ich habe bloß verstanden das mein Programm bei großen Zahlen zu langsam ist oder? Wie mach ich das besser? Wäre cool wenn mir das jemand auch erklären könnte, da ich sonst wieder bloß Bahnhof verstehe 😃 !

    @ Vicious Falcon: Danke! Aber was meinst du mit: "die 1 wird als Primzahl gewertet" . Ich nehm den Fall der 1 doch in der main vorher raus durch eine IF-Schleife. Ja und das mit "9876543210" hab ich schon festgestellt, da kommt er wie in eine Endlosschleife. Aber Warum? Und wie, wo und warum kann ich das mit einem cin.clear() beheben?



  • Ich hatte ja geschrieben, dass es nur eine Kleinigkeit ist, in einer allgemein gültigen Funktion sollte aber auch der Fall n==1 betrachtet werden.

    if (p==1 || p%2 == 0) return false;
    

    Bei dem Einlesen kannst du überprüfen, ob alles geklappt hat

    #include <limits>
    int eingabe () {
    	int x = 0;
    	std::cout<<"Bitte geben sie eine natuerliche Zahl ein: ";
    	while (!(std::cin>>x) || x<1) // irgendwas ging schief
    	{
    		std::cout<<"\nDie eingegebene Zahl ist nicht natuerlich!\nBitte geben sie erneut eine natuerliche Zahl ein: ";
    		if(cin.fail()) // Input konnte nicht konvertiert werden
    		{
    			std::cin.clear(); // Failbit löschen
    			std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n'); // den Rest der Zeile ignorieren und nochmal probieren
    		}
    	}
    	return x;
    }
    

    Eine Eingabe von 4561gfrg ist immer noch gültig, es wird bis zum Auffinden von 'g' konvertiert und somit 4561 zurück gegeben.



  • Okay danke, aber die Zeile

    std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
    

    verstehe ich noch nicht bzw. was sagt diese aus? löscht sie einfach nur die Buchstaben von der Beispieleingabe?

    Und dann zu

    while (!(std::cin>>x) || x<1)
    

    Diese Schreibweise kenne ich noch nicht, aber ich interpretiere mal so:
    Auf Grund des Ausrufezeichens wird noch einer Eingabe gefragt und diese wird auch kleiner 1 getestet oder?
    Aber wenn ich nun das Beispiel eingebe "4561gfrg" was für einen Wert hat dies dann? Ich mein würde er dann auch in die Schleife gehen?
    Weil meines Anfängerwissen haben Buchstaben letzten Endes auch bloß Zahlwerte und diese wären ja dann größer 1 oder?

    Sorry für die vielen Fragen aber lerne es erst seit 1,5 Monaten.



  • Ich bin mir nicht sicher, ob ihr das überhaupt abfragen müsst, oder einfach von gültigen Eingaben ausgehen könnt.
    Trotzdem eine kurze Erklärung. Wenn cin eine Eingabe nicht konvertieren kann, wird das "Failbit" gesetzt. Die Eingabe verbleibt dabei aber im stream. Jede weitere Eingabe wird ignoriert, bis dieses "Failbit" gelöscht wurde.
    Das heißt, die Vorgehensweise ist Folgende:

    • Zahl einlesen.
    • Überprüfen, ob der Eingabestream gültig ist.
    • Wenn nicht, mit cin.clear() das "Failbit" löschen, mit cin.ignore(..) die Eingabe verwerfen und es erneut probieren.

    Der Aufruf

    std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
    

    löscht alles, bis der delim , in diesem Fall '\n', gefunden wurde.

    std::numeric_limits<streamsize>::max()
    

    liefert den größtmöglichen Wert für den typedef streamsize.
    Die Bedingung

    while (!(std::cin>>x) || x<1)
    

    bedeutet nichts weiter, als dass abgefragt werden soll, ob der Stream (cin) in einem fehlerhaften Zustand, ODER ob x<1 ist. Nur wenn eine dieser beiden Bedingungen erfüllt ist, wird der Schleifenkörper betreten, ansonsten ist alles glatt gegangen und die Funktion gibt den eingelesenen Wert zurück.



  • Okay das macht Sinn dankeschön!

    Aber muss dann vor deiner ersten While-Schleife nicht noch ein

    std::cin>>x;
    

    stehen?



  • Zuerst: ! negiert den Ausdruck !true -> false, !false -> true .

    Chillee schrieb:

    Aber muss dann vor deiner ersten While-Schleife nicht noch ein

    std::cin>>x;
    

    stehen?

    Nein, der Ablauf ist ja Folgender:

    • std::cin>>x , Einlesen in x
    • überprüfen, ob der Stream in einem konsistenten Zustand ist
    • wenn ja, dann ist der Audruck !(std::cin>>x) ja !(true) und es wird ausgewertet ob x kleiner 1 ist.
    • wenn nein, ( !(false) ) wird x<1 nicht ausgewertet und der Schleifenkörper betreten, da bei dem logischen Oder || die Bedingung sowieso erfüllt ist.


  • Okay super dankeschön. Werde es mal mit einbauen und jetzt abgeben 😉 !

    Vielen Dank nochmal an alle zahlreichen Antworten. Werde wohl jetzt öfters mal hier vorbeischauen um mir gute Tipps zu holen!

    Ich wünsche allen ein Schönes WE und einen schönen ersten Advent!

    Beste Grüße,
    Chillee



  • Chillee schrieb:

    Werde es mal mit einbauen und jetzt abgeben 😉 !

    [...]

    Ich wünsche allen ein Schönes WE und einen schönen ersten Advent!

    Beste Grüße,
    Chillee

    Halt mal, bevor Du Dich in die Kekskiste verkrümelst: Wie sieht denn jetzt das Endergebnis aus?



  • Kekskiste verkrümelst

    😃 😃 😃

    Naja ich kann jetzt nix mehr daran ändern, da ich am Freitag bis spätestens 24:00 Uhr hochladen musste.

    Leider konnte ich diese Überprüfung von Vicious Falcon nicht mehr mit einbauen, da sie bei mir, wenn ich

    g++ -o ha3.exe -Wall ha3.cpp
    

    eingab, ein paar Fehler brachte, die ich auf Grund noch mangelndes Wissens nicht beheben konnte :(.

    Dennoch hat das Programm ja funktioniert und das passt schon, weil wir sind gerade beim Gebiet "Funktionen" und da wird es wohl eher auf die Benutzung derer ankommen als auf die Eingabeüberprüfung. Zumindest hoffe ich das! 🙂

    Ich denke ich bekomme irgentwann zwischen Sonntag und Dienstag das Ergebnis, ob HA bestanden oder nicht.

    Aber hier nochmal der Quelltext, den ich abgegeben habe:

    #include <iostream>
    
    // ------- Nebenfunktionen-------
    
    // >Eingabe
    int eingabe () {
      int x = 0;
      std::cout<<"Bitte geben sie eine natuerliche Zahl ein: ";
      std::cin>>x;
    
      while (x<1) {																	// Test ob Zahl natürlich
        std::cout<<"\nDie eingegebene Zahl ist nicht natuerlich!\nBitte geben sie erneut eine natuerliche Zahl ein: ";
        std::cin>>x;
      }
      return x;
    }
    
    // >Test ob Primzahl
    bool primtest (int p) {
      int zaehler;
    
      if (p == 2) return true;
    
      if (p %2 == 0) return false;
    
      for (zaehler = 3; zaehler * zaehler <= p; zaehler = zaehler+2) {
        if (p % zaehler == 0) return false;
      }
    
      return true;
    }
    
    // >Primzahlzerlegung
    void primzer (int y) {
    
      int i = 2;
    
      while (y > 1) {
            while ((y%i != 0) || (primtest(i) == 0)) {
             i++;
        }
        std::cout<<i<<" ";
        y/=i;
      }
    }
    
    // ------ Hauptfunktion -----------
    
    int main () {
    
      std::cout<<"Primfaktorzerlegung einer natuerlichen Zahl"<<std::endl;
      std::cout<<"-------------------------------------------"<<std::endl;
      std::cout<<std::endl;
    
      int n = 0;
      n = eingabe();
      std::cout<<std::endl;
    
      if (n == 1) std::cout<<"Die eingegebene Zahl laesst sich nur durch 1 teilen!"<<std::endl;		//1 ausschliesen
      else {																						// Sonst Zerlegung beginnen
        bool k;
        k = primtest(n);
        if (k == 0) {																				//Fall: Primzahlzerlegung möglich
          std::cout<<"Die Zahl "<<n<<" laesst sich in folgende Primfaktoren zerlegen: "<<std::endl;
          primzer (n);
          std::cout<<std::endl;
        }
        else {																						//Fall: Zahl ist Primzahl!
          std::cout<<n<<" ist eine Primzahl."<<std::endl;
    	  std::cout<<"Sie ist nur durch "<<n<<" und 1 teilbar."<<std::endl;
        }
        }
    
      return 0;
    }
    

    Also ich werde euch auf jeden Fall das Ergebnis mitteilen ;)...

    Bis dahin...genießt den 1.Advent!

    Viele Grüße,
    Chillee



  • So überraschender Weise habe ich heute schon das Ergebnis erhalten. 😃

    hehe...ich danke euch vielmals, denn die HA war richtig! 🙂

    Kommentar von der Kontroleurin:

    die gesamte Zerlegung sollte in 1 Funktion - sonst in Ordnung

    Also bis bald :)...bis Freitag stehen schon wieder die nächsten HA's an, diesmal aber zu Feldern. Mal schauen, ansonsten ist es gut zu wissen, dass es hier ein paar sehr weltklasse Leute gibt!

    Viele Grüße,
    Chillee


Anmelden zum Antworten