Zahlen aus Array vergleichen
-
TNA schrieb:
Vorab zum Verständnis: Also du willst über das Array laufen, und alle eingegebenen Zahlen die noch nicht vorgekommen sind eintragen?
Ja genau es soll schlussendlich ein kleines Lotto-Spiel werden. Man kann jede Zahl nur einmal eingeben. Zahlengenerator und Auswertung sind jetzt noch nicht im Code enthalten.
-
Und dein Versuch funktioniert nicht oder willst du nur Kommentare bzw. eine bessere Lösung?
-
TNA schrieb:
Und dein Versuch funktioniert nicht oder willst du nur Kommentare bzw. eine bessere Lösung?
Nein mein Versuch geht nicht ^^ Ich bekomm, egal welche Zahl ich eingebe, die Meldung: "Zahl schon vorhanden". Kommentare, Lösungsanzätze oder auch Verbesserungen bzw bessere Lösungen, ich nehm alles entgegen ich muss es schliesslich auch irgendwann lernen

-Thomas
-
Schleifenvariablen wie i oder j im Schleifenkopf deklarieren, system calls sind nicht gerade empfehlenswert (lahm, sicherheitslücken, vermutlich nicht portabel, ...), wenn man nur einen Zeilenumbruch will: '\n'
#include <array> #include <iostream> #include <limits> int main() { using namespace std; array<int, 6> userzahl; // int userzahl[6], aber "besser" for(unsigned i=0; i<userzahl.size(); i++) { // fand das übersichtlicher, auch zum debuggen cout<<"\n Bitte geben sie die " << i+1 << ". Zahl ein: "; cin>>userzahl[i]; while(userzahl[i] < 1 || userzahl[i] > 46){ cout<<"\n Unguelitge Eingabe\n"; cout<<"\n Bitte neue Zahl eingeben:\n"; cin>>userzahl[i]; } for(unsigned j=0;j<i;j++){ while (userzahl[i]==userzahl[j]){ cout<<"\n Zahl bereits Voranden!"; cout<<"\n Bitte neue Zahl eingeben: "; cin>>userzahl[i]; } } } cout<<"\nIhre Zahlen: "; //for (unsigned i = 0; i < userzahl.size(); ++i) //cout << userzahl[i] << ' '; for (const auto& n : userzahl) cout << n << ' '; // system("Pause"); // ist ehrlich gesagt bei Übungsprogrammen auch egal... cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); cin.get(); }P.S.: Ich hab an der eigentlich Logik nichts verändert (ich kann deinen Fehler nicht reproduzieren)
~edit: Compiler könnte meckern wegen vergleich unsigned mit signed (korrigiert), das if do while kann man zu while vereinfachen~;
-
HarteWare schrieb:
Das erklärt das Buch aber hoffentlich nicht, dass man die Schleifenvariablen wie i oder j schon davor deklarieren soll, oder dass system calls empfehlenswert sind, oder dass man endl nehmen soll, wenn man nen Zeilenumbruch will:
#include <array> #include <iostream> #include <limits> int main() { using namespace std; array<int, 6> userzahl; // int userzahl[6], aber "besser" for(unsigned i=0; i<userzahl.size(); i++) { // fand das übersichtlicher, auch zum debuggen cout<<"\n Bitte geben sie die " << i+1 << ". Zahl ein: "; cin>>userzahl[i]; while(userzahl[i] < 1 || userzahl[i] > 46){ cout<<"\n Unguelitge Eingabe\n"; cout<<"\n Bitte neue Zahl eingeben:\n"; cin>>userzahl[i]; } for(unsigned j=0;j<i;j++){ while (userzahl[i]==userzahl[j]){ cout<<"\n Zahl bereits Voranden!"; cout<<"\n Bitte neue Zahl eingeben: "; cin>>userzahl[i]; } } } cout<<"\nIhre Zahlen: "; //for (unsigned i = 0; i < userzahl.size(); ++i) //cout << userzahl[i] << ' '; for (const auto& n : userzahl) cout << n << ' '; // system("Pause"); // ist ehrlich gesagt bei Übungsprogrammen auch egal... cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); cin.get(); }P.S.: Ich hab an der eigentlich Logik nichts verändert (ich kann deinen Fehler nicht reproduzieren)
~edit: Compiler könnte meckern wegen vergleich unsigned mit signed (korrigiert), das if do while kann man zu while vereinfachen~Hi HarteWare
Danke für die Antwort.
Ich habe ein teil vom Code aus einem einem C-Code genommen den ich zuvor geschreiben habe bevor ich mich entschied dann doch direkt mit C++ anzufangen darum ist der System Call noch dadrin, aber endl wird durch alle 900 Seiten des Buches benutzt. Die Schleifenvariable wird auch immer zuvor definiert.Interpretier ich das richtig und kann so allgemein verwendet werden?
array<int, 6> userzahl; array<datentyp, Anzahl> Variablennamen; Bsp: array<char, 8> Text;Und diesen Teil verstehe ich noch nicht so ganz;
cout<<"\nIhre Zahlen: "; //for (unsigned i = 0; i < userzahl.size(); ++i) //cout << userzahl[i] << ' '; for (const auto& n : userzahl) cout << n << ' '; // system("Pause"); // ist ehrlich gesagt bei Übungsprogrammen auch egal... cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); cin.get();Gruss Thomas
-
Hallo Thomas,
BlackNeon schrieb:
for(j=0;j<i;j++){ if(userzahl[i]==userzahl[j]){ do{ cout<<"\n Zahl bereits Voranden!"; cout<<"\n Bitte neue Zahl eingeben: "; cin>>userzahl[i]; }while (userzahl[i]==userzahl[j]); } }dieser Code ist funktional falsch. Wenn Du bereits zwei Zahlen eingegeben hast, so kannst Du die zweite Zahl nochmal eingeben .. die wird zwar nicht übernommen, aber Du landest in obiger do-while-Schleife und anschließend kannst Du die erste Zahl noch einmal eingeben.
Probier's mal aus.Die tiefere Ursache dieses Fehlers liegt in der Redundanz der Eingabe in den Zeilen 8, 14 und 22 (s. Originalposting).
Versuche den Code so zu ändern, dass das Einlesen der Zahl nur an einer einzigen Stelle im Programm vorkommt.
IMHO resultieren 90% aller Programmierfehler aus Redundanzen und impliziten Annahmen.Gruß
Werner
-
Hi Werner,
Danke für die Antwort.
Werner Salomon schrieb:
dieser Code ist funktional falsch. Wenn Du bereits zwei Zahlen eingegeben hast, so kannst Du die zweite Zahl nochmal eingeben .. die wird zwar nicht übernommen, aber Du landest in obiger do-while-Schleife und anschließend kannst Du die erste Zahl noch einmal eingeben.
Probier's mal aus.Hast recht das funktioniert wirklich.

Werner Salomon schrieb:
Versuche den Code so zu ändern, dass das Einlesen der Zahl nur an einer einzigen Stelle im Programm vorkommt.
Für einen blutigen Anfänger ist das einfacher gesagt als getan
aber ich geb mein bestets eine Lösung zu finden, ansonsten meld ich mich später wieder, wenn mein Kopf raucht und ich noch keine Lösung hab.
-
BlackNeon schrieb:
Hi Werner,
Danke für die Antwort.
Werner Salomon schrieb:
dieser Code ist funktional falsch. Wenn Du bereits zwei Zahlen eingegeben hast, so kannst Du die zweite Zahl nochmal eingeben .. die wird zwar nicht übernommen, aber Du landest in obiger do-while-Schleife und anschließend kannst Du die erste Zahl noch einmal eingeben.
Probier's mal aus.Hast recht das funktioniert wirklich.

Werner Salomon schrieb:
Versuche den Code so zu ändern, dass das Einlesen der Zahl nur an einer einzigen Stelle im Programm vorkommt.
Für einen blutigen Anfänger ist das einfacher gesagt als getan
aber ich geb mein bestets eine Lösung zu finden, ansonsten meld ich mich später wieder, wenn mein Kopf raucht und ich noch keine Lösung hab.So die Köpfe sind am rauchen, hab mich mit einem Mitarbeiter zusammengesetzt und das versucht zu lösen. Die einzige Möglichkeit die wir gefunden besteht darin es mit Funktionen zu lösen aber, da ich nicht gerade viel Ahnung davon hab wie das richtig funktioniert, fällt dies auch weg. Ich/Wir währen um einen Tipp oder einen Lösungsanzsatz froh, wenn möglich im Spaghetticode (Ohne Funktionen und Verweise).
Danke und Gruss
Thomas
-
Wie wäre es damit, für die Überprüfung ob eine Zahl bereits vorhanden ist einfach ein Set zu nehmen, dann kann man sich die Aufwändige Schleife sparen und die Zahlen sind gleich sortiert, was bei Lottozahlen ja durchaus sinnvoll ist:
#include <iostream> #include <set> using namespace std; const int AnzahlZahlen = 6; bool valueinvalid(int value) { return userzahl[i] < 1 || userzahl[i] > 46; } int main() { set<int> Zahlen for(int i=0; i<AnzahlZahlen; i++) { cout<<"\n Bitte geben sie eine Zahl ein: "; int userzahl; for (cin>>userzahl; valueinvalid(userzahl); cin>>userzahl;) { cout<<"\n Unguelitge Eingabe"<<endl; cout<<"\n Bitte neue Zahl eingeben: "<<endl; } auto ret = Zahlen.emplace(userzahl) for(;!ret.second;cin>>userzahl,Zahlen.emplace(userzahl)) { cout<<"\n Zahl bereits Voranden!"; cout<<"\n Bitte neue Zahl eingeben: "; } } } cout<<"\n Ihre Zahlen:"; for (const auto& n : userzahl) cout << n << ' '; }Wenn es unbedingt ein Array sein muss würde ich zumindest einen Algorithmus für die Überprüfung auf doppelte Zahlen nehmen.
-
Hallo Thomas,
BlackNeon schrieb:
Werner Salomon schrieb:
Versuche den Code so zu ändern, dass das Einlesen der Zahl nur an einer einzigen Stelle im Programm vorkommt.
So die Köpfe sind am rauchen, hab mich mit einem Mitarbeiter zusammengesetzt und das versucht zu lösen. Die einzige Möglichkeit die wir gefunden besteht darin es mit Funktionen zu lösen aber, da ich nicht gerade viel Ahnung davon hab wie das richtig funktioniert, fällt dies auch weg. Ich/Wir währen um einen Tipp oder einen Lösungsanzsatz froh, wenn möglich im Spaghetticode (Ohne Funktionen und Verweise).
Ja, ja - ein scheinbares einfache Problem; und doch so schwierig!
Nehmen wir mal an Du überlegst, wie es in Deinem Programm ab Zeile 7 weiter geht. Dort soll eine Zahl eingegeben und geprüft werden. Bei negativem Prüfergebnis soll die Eingabe wiederholt werden.
Beginne wie folgt:for(;;) // forever, bis Eingabe ok (s.u.) { cout << "\n Bitte geben sie eine Zahl ein: "; cin >> userzahl[i]; // und hier kommt jetzt die Prüfung; falls alles ok, wird die Schleife mit 'break;' verlassen }Zuerst die Prüfung, ob die Zahl im Intervall von 1 bis 46 liegt:
const int MINI = 1; const int MAXI = 46; // Konstanten vermeiden die Redundanz von Zahlen const int N = 6; int userzahl[N]; for (int i = 0; i < N; ++i) { for(;;) // forever, bis Eingabe ok (s.u.) { cout << "\n Bitte geben sie eine Zahl ein: "; cin >> userzahl[i]; if( MINI <= userzahl[i] && userzahl[i] <= MAXI ) // prüfe ob die Zahl im geforderten Intervall liegt { // die Zahl liegt im Intervall // ... ggf. weitere Prüfungen break; // Schleife verlassen, Eingabe ist ok } else { // die Zahl liegt nicht im Intervall cout << " Ungueltige Eingabe - Zahl liegt nicht im geforderten Intervall [" << MINI << ".." << MAXI << "]" << endl; } }Anschließend kann man jetzt die zweite Prüfung einbauen. Also überprüfen, ob die Eingabe doppelt ist. Verständlicher Weise muss die Zahl jetzt mit jeder der bereits eingegebenen verglichen werden. Dazu benutze ich eine
for-Schleife. Wenn diefor-Schleife verlassen wird, muss klar sein, ob eine gleiche Zahl gefunden wurde. Das erreiche ich, indem ich den Laufindex auf das Ende prüfe (also hier==i) - dann wurde keine gleiche Zahl gefunden.for(;;) // forever, bis Eingabe ok (s.u.) { cout << "\n Bitte geben sie eine Zahl ein: "; cin >> userzahl[i]; if( MINI <= userzahl[i] && userzahl[i] <= MAXI ) // prüfe ob die Zahl im geforderten Intervall liegt { // die Zahl liegt im Intervall int j = 0; // 'j' erst hier, aber außerhalb der for-Schleife in der nächste Zeile deklarieren, da der Index später noch gebraucht wird for( ; j < i; ++j ) { if( userzahl[i] == userzahl[j] ) break; // einfach abbrechen; 'j' wird nicht weiter erhöht und ist demnach !=i } if( j == i ) // Ende erreicht; keine Zahl war gleich break; // Schleife verlassen, Eingabe ist ok cout << " Zahl bereits vorhanden!" << endl; } else { // die Zahl liegt nicht im Intervall cout << " Ungueltige Eingabe - Zahl liegt nicht im geforderten Intervall [" << MINI << ".." << MAXI << "]" << endl; } }Gruß
Werner
-
Wenn du mal gross bist, lernst du solche Programme zu schreiben:
#include <iostream> #include <algorithm> #include <iterator> #include <boost/algorithm/clamp.hpp> #include <boost/range/algorithm/count.hpp> #include <boost/iterator/filter_iterator.hpp> int main() { std::vector<int> userzahl; std::copy_n(boost::make_filter_iterator([&](int i){ return (i==boost::algorithm::clamp(i, 1, 46) && !boost::range::count(userzahl, i)) || !(std::cout << "Ungueltige Eingabe\n"); }, std::istream_iterator<int>(std::cin)), 6, std::back_inserter(userzahl)); }
-
Bin leider nicht so der Boost-Experte aber schwer beeindruckt. Wie wäre es als Herausforderung mit der kompaktesten Lösung mit C++ Bordmitteln?
-
Die Schwierigkeit ist, die Abbruchbedingung zu setzen. Bei copy_if braucht es dann als Hack, std::cin in einen Fehlerstatus zu setzen, damit die Eingabe stoppt:
#include <iostream> #include <algorithm> #include <vector> #include <iterator> int main() { std::vector<int> userzahl; std::copy_if(std::istream_iterator<int>(std::cin), std::istream_iterator<int>{}, std::back_inserter(userzahl), [&](int i) { if (userzahl.size() == 6) return std::cin.setstate(std::ios_base::failbit), false; return (1<=i && i<=46 && std::count(userzahl.begin(), userzahl.end(), i)) || !(std::cout << "Ungueltige Eingabe\n"); }); std::cin.clear(); }
-
Hallo zusammen
Danke für die Antworten, die ich leider erst jetzt gelesen habe und doch schon eine Lösung gefunden habe dank eines Denkanstosses unseres Progress-Programmierers, der mir gezeigt hat wie er das ganze im Progress geschreiben hat.
Vor 10min habe ich das Lottospiel noch ganz fertig geschrieben und wollte euch noch meine Lösung vorstellen, inklusive Auswertung, Zahlengenerator und Resultat. Die ganzen Kommentare im Code waren für das Debugging, lasst euch davon nicht iritieren. Der Code ist wahrscheinlich viel zulange für das was ich machen wollte aber jeder fängt mal klein bzw. in diesem Fall mit nem grossen Code an
#include <iostream> #include <cstdlib> #include <string> #include <time.h> using namespace std; int zahleneingabe(); int main() { int userzahl[6] = {0, 0, 0, 0, 0, 0}; int genzahl[6] = {0, 0, 0, 0, 0, 0}; int neuezahl, neuegen, i, j, resultat=0; const int x=1,y=46; for(i=0; i<6; i++){ neuezahl=zahleneingabe(); //cout<<"neuezahl: "<<neuezahl; if(neuezahl < 1 || neuezahl > 46){ cout<<"\n Zahl ungueltig!\n";//<<i; i--; } else{ //cout<<"else"; for(j=-1;j<i;j++){ //cout<<"neu: "<<neuezahl; if(userzahl[j]==neuezahl){ cout<<"\n Zahl schon vorhanden!\n";//<<userzahl[j]<<" : "<<neuezahl<<" "<<" j: "<<j<<" i: "<<i; i--; }else{ userzahl[i] = neuezahl; } } } } cout<<"\n Ihre Zahlen: "<<userzahl[0]<<" "<<userzahl[1]<<" "<<userzahl[2]<<" "<<userzahl[3]<<" "<<userzahl[4]<<" "<<userzahl[5]<<endl; //cout<<"\n Lottozahlen werden erzeugt!\n"; srand((unsigned)time(NULL)); for(int k=0; k<6; k++){ genzahl[k] = (rand()%46); genzahl[k]++; for(int l=0; l<k; l++){ if(genzahl[k]==genzahl[l]){ k--; } } } cout<<"\n Lottozahlen: "<<genzahl[0]<<" "<<genzahl[1]<<" "<<genzahl[2]<<" "<<genzahl[3]<<" "<<genzahl[4]<<" "<<genzahl[5]<<"\n"; //cout<<"\n Zahlen werden verglichen"; for(int m=0;m<6;m++){ for(int n=0;n<6;n++){ if(genzahl[m]==userzahl[n]){ resultat++; } } } //cout<<"\n Resultat wird ausgegeben"; if(resultat==0){ cout<<"\n Sie haben "<<resultat<<" von 6 Zahlen richtig! Sorry, versuch es nocheinmal!\n\n"; }else{ cout<<"\n Sie haben "<<resultat<<" von 6 Zahlen richtig! Glueckwunsch!\n\n"; } cin.get(); return 0; } int zahleneingabe(){ int neuezahl; cout<<"\n Bitte Zahl eingeben: "; cin>>neuezahl; return neuezahl; }Irgendwann vieleicht einmal
Noch verstehe ich deinen Code nicht.cpppro schrieb:
Wenn du mal gross bist, lernst du solche Programme zu schreiben:
#include <iostream> #include <algorithm> #include <iterator> #include <boost/algorithm/clamp.hpp> #include <boost/range/algorithm/count.hpp> #include <boost/iterator/filter_iterator.hpp> int main() { std::vector<int> userzahl; std::copy_n(boost::make_filter_iterator([&](int i){ return (i==boost::algorithm::clamp(i, 1, 46) && !boost::range::count(userzahl, i)) || !(std::cout << "Ungueltige Eingabe\n"); }, std::istream_iterator<int>(std::cin)), 6, std::back_inserter(userzahl)); }Ja wir haben Stunden damit verbracht bis wir auf eine Lösung gekommen sind um genau zusein 1,5 Arbeitstage. Naja aber nur so lernt man. Danke für deine ausfürhliche Antwort ich werde mir davon noch Notizen machen und noch in meinen Code einbinden so gut es geht.
Werner Salomon schrieb:
Ja, ja - ein scheinbares einfache Problem; und doch so schwierig!
Nehmen wir mal an Du überlegst, wie es in Deinem Programm ab Zeile 7 weiter geht. Dort soll eine Zahl eingegeben und geprüft werden. Bei negativem Prüfergebnis soll die Eingabe wiederholt werden.
Beginne wie folgt:for(;;) // forever, bis Eingabe ok (s.u.) { cout << "\n Bitte geben sie eine Zahl ein: "; cin >> userzahl[i]; // und hier kommt jetzt die Prüfung; falls alles ok, wird die Schleife mit 'break;' verlassen }Zuerst die Prüfung, ob die Zahl im Intervall von 1 bis 46 liegt:
const int MINI = 1; const int MAXI = 46; // Konstanten vermeiden die Redundanz von Zahlen const int N = 6; int userzahl[N]; for (int i = 0; i < N; ++i) { for(;;) // forever, bis Eingabe ok (s.u.) { cout << "\n Bitte geben sie eine Zahl ein: "; cin >> userzahl[i]; if( MINI <= userzahl[i] && userzahl[i] <= MAXI ) // prüfe ob die Zahl im geforderten Intervall liegt { // die Zahl liegt im Intervall // ... ggf. weitere Prüfungen break; // Schleife verlassen, Eingabe ist ok } else { // die Zahl liegt nicht im Intervall cout << " Ungueltige Eingabe - Zahl liegt nicht im geforderten Intervall [" << MINI << ".." << MAXI << "]" << endl; } }Der "set" befehl ist mir noch unbekannt und konnte den Code nur teilweise verstehen. Aber trotzdem Danke

TNA schrieb:
Wie wäre es damit, für die Überprüfung ob eine Zahl bereits vorhanden ist einfach ein Set zu nehmen, dann kann man sich die Aufwändige Schleife sparen und die Zahlen sind gleich sortiert, was bei Lottozahlen ja durchaus sinnvoll ist.
Ihr könnt nach Lust und Laune meinen Code noch in Fetzen reissen und Verbesserunsvorschläge bringen. Wie gesagt man lernt ja nie aus

Nochmals Danke für all die Hilfe

Gruss Thomas