Array - Doppelt eingegebene Zahlen erkennen



  • Servus, eine kurze Frage.
    Ich habe mir ein Array mit 6 Feldern erstellt und möchte diese nach und nach mit Werten füllen.
    Sollten 2 Felder den selben Wert haben, möchte ich dies als Fehler ausgeben und korrigieren lassen, durch erneute Eingabe.
    Ich komme gerade einfach nicht auf die Lösung, wie ich die Werte untereinander vergleiche.
    Über einen Denkansatz wäre ich dankbar.

    int zahl[5];
    for (int i = 0; i < size(zahl); i++)
    	{
    			cout << "Zahl " << i + 1 << " eingeben: ";
    			cin >> zahl[i];
    			cout << zahl[i] << endl;
            }
    


  • Mach in der Schleife eine 2. verschachtelte Schleife, die von 0 bis i - 1 läuft. Nennen wie die Laufvariable dieser Schleife j. Dann kannst du in der Schleife zahl[i] mit zahl[j] vergleichen.



  • Habe es mal so gemacht, wie beschrieben.
    Nach der Eingabe des ersten Wertes, wird mir gesagt, dass die Zahl doppelt ist.
    Der erste Wert, wird auch bei folgenden Werten als doppelt erkannt.
    Andere Werte bsp. der 2. Wert ist gleich 5 und der 3. Wert ist auch 5. Dann wird cout nicht ausgegeben.

    Wie funktioniert denn in der verschachtelten Schleife das -1?
    Das kannte ich bisher noch nicht.

    int zahl[5];
    for (int i = 0; i < size(zahl); i++)
    	{
    			cout << "Zahl " << i + 1 << " eingeben: ";
    			cin >> zahl[i];
    			cout << zahl[i] << endl;
    
                            for (int j = 0; j-1 ; j++)
    			{
    				if (zahl[i] == zahl[j])
    				{
    					cout << "Zahl ist doppelt\n";
     				}
    			}
            }
    


  • j-1 in der 2. for-Schleife ist ja auch nicht die richtige Bedingung (dies entspricht j-1 != 0 ).
    Die Schleifenvariable j mußt du, wie @hustbaer schon geschrieben hat, mit i-1 vergleichen.



  • @Th69 Stimmt, habe es falsch übernommen. Dies hatte ich auch probiert mit i-1. Dennoch stürzt das Programm nach einer Eingabe ab.



  • @Lumberjack sagte in Array - Doppelt eingegebene Zahlen erkennen:

    Dies hatte ich auch probiert mit i-1.

    Du sollst die Laufvariable j mit i-1 vergleichen
    Die Schleife läuft, solange die Bedingung wahr ist.
    i-1 ist nur unwahr, wenn i 1 ist.
    j < i-1 ist etwas ganz anderes.

    Dein Array hat nur Platz für 5 Elemente



  • Es muß j < i dort stehen.



  • Komme damit leider auch nicht wirklich weiter.
    Wenn der erste Wert bspw. 5 ist und der 2. Wert auch, dann wird kein cout ausgegeben.
    Erst beim 3. Wert, wird mir gesagt, dass 5 doppelt ist.
    Liegt das am Index des Arrays?

            int zahl[5];
    	for (int i = 0; i < size(zahl); i++)
    	{
    			cout << "Zahl " << i + 1 << " eingeben: ";
    			cin >> zahl[i];
    			cout << zahl[i] << endl;
    			for (int j = 0; j < i-1; j++)
    			{
    				if (zahl[i] == zahl[j])
    				{
    					cout << "Zahl ist doppelt\n";
    				}
    			}
    	}
    


  • Sorry, hatte mich vertan (oben editiert).
    Es muß entweder j < i oder j <= i-1 lauten.

    Aber gerade so etwas ist das Entscheidende beim Code erstellen/programmieren, daß man Fehler findet und versucht, deren Ursache zu finden und zu beheben (selten sind Programme auf Anhieb fehlerfrei).



  • Vielen Dank für eure Antworten. Soweit funktioniert es super.
    Allerdings, wenn ich das jetzt richtig verstanden habe, wird die verschachtelte Schleife beim ersten Durchgang nicht durchlaufen. Beim zweiten Durchgang dann, hat [j], den zuerst eingegebenen Wert von [i] das wiederholt sich dann bis zum Ende von der ersten Schleife. Also ist quasi der Index immer um eine Stelle versetzt.



  • @Lumberjack Die innere Schleife läuft über alle bisher eingegebenen Werte. Die fängt immer wieder bei 0 an.
    Bei jedem Durchlauf der äußeren Schleife.



  • Jetzt hatte ich vor, die doppelt eingegebene Zahl, zu korrigieren nach Aufforderung.
    Allerdings klappt das nicht so ganz wie ich mir das vorstelle.
    Ist der Weg komplett falsch, oder eher ein Fehler drinnen?

    int zahl[5];
    for (int i = 0; i < size(zahl); i++)
    	{
    			cout << "Zahl " << i + 1 << " eingeben: ";
    			cin >> zahl[i];
    			for (int j = 0; j < i; j++)
    			{
    				if (zahl[i] == zahl[j])
    				{
    					do
    					{
    					cout << "Zahl " << zahl[i] << " ist doppelt\n";
    					cout << "Bitte keine doppelten Zahlen verwenden\n";
    						cout << "Zahl " << i + 1 << " eingeben: \n";
    						cin >> zahl[i];
    
    					} while (zahl[i] == zahl[j]);
    				}				
    			}
    	}
    }
    

  • Mod

    Was heißt denn "nicht so ganz"? Bitte präzise Problembeschreibungen! Liegt dein Problem darin, dass bei einer Eingabe von 1 2 3 3 zwar die zweite 3 bemängelt wird, man sie aber dann mit einer 2 ersetzen kann? Denn das wäre möglich, aber ich weiß nicht, ob du das überhaupt das Problem ist, das du meinst.



  • @SeppJ Ganz genau. Muss ich nächstes mal dran denken, genauer zu beschreiben.
    Aber so wie du es geschrieben hast, stimmt es.
    bsp: 1.. 2.. 3.. dann kommt die Fehlermeldung bei der Eingabe von 3: doppelt.
    Eingabe 2: doppelt.
    Eingabe 1: doppelt.
    Wenn man das einige male eingibt, akzeptiert das Programm dann eine doppelte Zahl.


  • Gesperrt

    Ich denke, ich hätte dies wohl ausnahmsweise mal mit einem goto gelöst:

    #include <iostream>
    #define N 10
    
    typedef struct
    {
        int id;
        int value;
        char const *name;
    } E;
    
    int main(int argc, char const *argv[])
    {
        E ea[N];
        for (size_t i = 0; i < N;)
        {
        begin:
            std::cout << i + 1 << ". Eingabe:\n";
            std::cout << "Bitte id:\n";
            int id;
            std::cin >> id;
            for (int j = i - 1; j >= 0; j--)
            {
                if (id == ea[j].id)
                {
                    std::cout << "id schon vorhanden\n";
                    goto begin;
                }
            }
            E *e = &ea[i++];
            e->id = id;
            e->value = rand(); // hier nach Inhalt fragen
            e->name = "abc";   // hier was Sinnvolles
        }
        for (size_t i = 0; i < N; i++)
        {
            E *e = &ea[i];
            std::cout << e->id << " " << e->value << " " << e->name << "\n";
        }
        return 0;
    }
    
    

    Ein anderer Ansatz wäre, das Array immer sortiert zu halten, also sortiert einfügen und Binärsuche...

    Noch ein anderer Ansatz wäre, alle Zahlen zu sammeln, zu mischen und die ersten n Zahlen einzufügen...

    Es kommt auf den Anwendungsfall an, denke ich



  • @EinNutzer0
    Bei dem Code kommen mir einige Fragen auf.
    Bin noch nicht so erfahren in C++


  • Gesperrt

    @Lumberjack sagte in Array - Doppelt eingegebene Zahlen erkennen:

    Bei dem Code kommen mir einige Fragen auf

    Frag' ruhig, dafür ist ein Forum doch da... Hier gibt es kein Redeverbot oder Maulkörbe wie in manch anderen Foren...

    Und ja, du hast recht, das ist eigentlich ein Mix aus C und C++...


  • Mod

    Argh, nein. Bitte nicht so! Das ist ein super Beispiel wie man es gut meint und doch Spaghetticode produziert. Das mag jetzt noch durchschaubar sein, aber da fehlt doch nur ein weiterer Featurewunsch. Der ist in so eine Struktur nur noch mit weiteren Hacks einbaubar und dann hat man das Schlamassel!

    Wie man es stattdessen macht: Problem in sauber definierte Teilprobleme zerlegen. Deren Lösung ist dann auch meistens trivial, und super kapselbar. Daraus kann man dann höhere Logik bauen. Hier hätte man Teilprobleme:

    • Einzelne Zahl einlesen (brauchen wir nicht mehr extra programmieren, das macht cout >> für uns)
    • Gucken, ob eine Zahl schon vorhanden ist

    Daraus aufbaubar:

    • Einlesen einer Zahl, die noch nicht vorhanden ist

    Daraus aufbaubar:

    • 5x einlesen einer Zahl, die noch nicht vorhanden ist
    #include <iostream>
    using namespace std;
    
    int read_number_for_position(int position)
    {
    	int number;
    	cout << "Zahl für Position " << position << " eingeben: ";
    	cin >> number;
    	return number;
    }
    
    bool number_exists(int number, int *array, int upper_bound)
    {
    	for (int i=0; i<upper_bound; ++i)
    	  if (array[i] == number) return true;
    	return false;
    }
    
    void write_unique_number_to_position(int *array, int position)
    {
    	array[position] = read_number_for_position(position + 1);
    	while(number_exists(array[position], array, position))
    	{
    		cout << "Die Zahl gibt es schon, bitte eine andere Zahl eingeben. ";
    		array[position] = read_number_for_position(position + 1);
    	}
    }
    
    void write_N_unique_numbers_to_array(int *array, int N)
    {
    	for (int i=0; i<N; ++i)
    		write_unique_number_to_position(array, i);
    }
    
    
    int main() {
    	const int length = 5;
    	int array[length];
    	write_N_unique_numbers_to_array(array, length);
    	for (int i=0; i<length; ++i) cout << array[i] << ' ';
    }
    


  • @Lumberjack sagte in Array - Doppelt eingegebene Zahlen erkennen:

    Jetzt hatte ich vor, die doppelt eingegebene Zahl, zu korrigieren nach Aufforderung.
    Allerdings klappt das nicht so ganz wie ich mir das vorstelle.
    Ist der Weg komplett falsch, oder eher ein Fehler drinnen?

    int zahl[5];
    for (int i = 0; i < size(zahl); i++)
    	{
    			cout << "Zahl " << i + 1 << " eingeben: ";
    			cin >> zahl[i];
    			for (int j = 0; j < i; j++)
    			{
    				if (zahl[i] == zahl[j])
    				{
    					do
    					{
    					cout << "Zahl " << zahl[i] << " ist doppelt\n";
    					cout << "Bitte keine doppelten Zahlen verwenden\n";
    						cout << "Zahl " << i + 1 << " eingeben: \n";
    						cin >> zahl[i];
    
    					} while (zahl[i] == zahl[j]);
    				}				
    			}
    	}
    }
    

    Du könntest im Fall wo du eine doppelt eingegebene Zahl erkennst einfach eine Meldung ausgeben und dann den Index i um eins zurücksetzen. Dann wird beim nächsten Durchlauf der äusseren Schleife die selbe Zahl nochmal angefordert.

    Also quasi

    			for (int j = 0; j < i; j++)
    			{
    				if (zahl[i] == zahl[j])
    				{
    					cout << "Zahl " << zahl[i] << " ist doppelt\n";
    					cout << "Bitte keine doppelten Zahlen verwenden\n";
    					i--;
    					break;
    				}				
    			}
    


  • @SeppJ von deinem Beispiel kann ich einiges lernen. Danke.

    @hustbaer Funktioniert super, minimalistisch und trifft den Nagel auf den Kopf. Vielen Dank.
    Da hätte ich mal drauf kommen können 😵

    Erstaunlich, wie viele Wege doch nach Rom führen.


Anmelden zum Antworten