Programmieren - alles kontrollieren 4.941 Themen, 20.715 Beiträge

Problem mit Arrays (Borland C++ 5.0)

Selecta / 9 Antworten / Baumansicht Nickles

Hi, ich wollte ein Programm schreiben, das ganz viele eingegebene Zahlen eines Memo Feldes überprüft und ggf. doppelte ausgibt.
Das Problem: Es gibt bei mehreren doppelten Zahlen auch mehrmals die doppelten aus. Aber es soll zum Beispiel bei der Eingabe "1111" nur "1" ausgeben, weil 1 ist nunmal doppelt, wie oft ist vollkommen egal.

Quelltext:

void __fastcall TfrmMain::edtEingabeKeyDown
(TObject *Sender, WORD &Key,TShiftState Shift)
{
if(Key==VK_RETURN){
Zahlen[i]=StrToInt(edtEingabe->Text);
memoEingabe->Lines->Add(IntToStr(Zahlen[i]));
i++;
edtEingabe->SelectAll();
}
}
//---------------------------------------------------------------------------

void __fastcall TfrmMain::btnEingabeClick(TObject *Sender)
{
for (int d=0; d!=i; d++)
{
for(int c=d+1;c!=i;c++){
if (Zahlen[d] == Zahlen[c])
{
memoAusgabe->Lines->Add(Zahlen[c]);
}
}
}
}
Mir ist schon klar warum das so ist. ABer wie kann ich denn Zahlen[c] selber an Positionen überprüfen ? Zahlen[c(2,0)] oder Ähnliches funktioniert nicht.
Möchte einfach wissen wie ich von Arrays Stellen ausgeben kann.

GreeTz Selecta

P.S: Komplette Lösungen akzeptiere ich auch ;)

bei Antwort benachrichtigen
mr.escape Selecta „Problem mit Arrays (Borland C++ 5.0)“
Optionen

Zuerst etwas grundsätzliches:
Wenn es nicht ausdrücklich erforderlich ist, sollte:
for (int d=0; d!=i; d++)
oder auch
for(int c=d+1;c!=i;c++)
dringend vermieden und stattdessen lieber:
for (int d=0; d<i; d++)
bzw.
for(int c=d+1;c<i;c++)
geschrieben werden.

Das problem mit "1111" und "1" ist laut frage eigentlich keines, denn "1111" und "1" sind unterschiedliche zahlen. Lediglich die ziffern sind gleich.
Die verwendung von StrToInt() verweist auf das interesse nach zahlen und nicht nach ziffern!
Wenn aber doch ziffern gemeint sein sollten (also höchstens die gigantische menge von zehn unterschiedlichen), dann müsste direkt edtEingabe->Text verarbeitet werden.
z.b.:

//annahme: edtEingabe->Text ist ein char*
//wenn nicht: umwandeln bzw. sicherstellen, dass der [] operator das erwartete macht
//und ersatz von strlen() durch die passende funktion
int stlen=strlen(edtEingabe->Text), actpos;
for(actpos=0;actpos<stlen;actpos++){
  //!!! ACHTUNG hier werden einfache und nicht doppelte hochkommata verwendet !!!
  if(edtEingabe->Text[actpos]>='0' && edtEingabe->Text[actpos]<='9'){
    Zahlen[i]=edtEingabe->Text[actpos]-'0';
    memoEingabe->Lines->Add(IntToStr(Zahlen[i]));
    i++;
  }
}


Die ausgabe im anschluss kann eine benutzung von qsort() gewaltig beschleunigen (besonders bei "ganz viele eingegebene Zahlen")

mr.escape

"The man who trades freedom for security does not deserve nor will he ever receive either." - Benjamin Franklin"Wer seine Freiheit aufgibt, um Sicherheit zu erreichen, wird beides verlieren." - Georg Christoph Lichtenberg
bei Antwort benachrichtigen
Selecta mr.escape „Zuerst etwas grundsätzliches: Wenn es nicht ausdrücklich erforderlich ist,...“
Optionen

Mein Fehler:

ich meinte nicht 1111 sondern 1 1 1 1.
BZW als Memo:

Eingabe:

1
1
1
1

Ausgabe SOLL sein:
1

IST ABER:

1
1
1
1

Verstehst du es jetzt ? Der soll nur 1x das doppelte ausgeben.

bei Antwort benachrichtigen
mr.escape Selecta „Mein Fehler: ich meinte nicht 1111 sondern 1 1 1 1. BZW als Memo: Eingabe: 1 1 1...“
Optionen

Gut, das ist was anderes.
Das problem liegt in den zwei schleifen. Diese bewirken, dass nur die zahlen ausgegeben werden, die später im array nochmal auftauchen, d.h. alle zahlen werden n*(n-1)/2 mal ausgegeben, wenn n ihre anzahl im array ist. Zahlen die es nur einmal gibt, tauchen nie auf (wegen if (Zahlen[d] == Zahlen[c]) und d!=c).
Zudem läuft die erste schleife zu weit, was die zweite schleife zwar einfach korrigiert, aber die unglückliche formulierung der schleifenendbedingung macht so etwas sehr fehleranfällig (z.b. aus versehen bei d+2 beginnen und dann kommt die seeeeeehr lange schleife weil c!=i übersprungen wird).
Die richtige lösung müsste so aussehen (ohne sortieren, einfach brute force):
memoAusgabe->Lines->Add(Zahlen[0]);//gibt es auf jeden fall, ausgeben
for (int d=1; d<i; d++){//prüfe Zahlen[d] beginnend bei d=1
  for(int c=0;c<d;c++){
    if (Zahlen[d] == Zahlen[c])//oops, gibt es schon und wurde darum auch schon ausgegeben
      break;//beende "for c" und mache bei "for d" weiter
    memoAusgabe->Lines->Add(Zahlen[d]);//ok, Zahlen[d] taucht zum ersten mal auf
  }
}


mr.escape

"The man who trades freedom for security does not deserve nor will he ever receive either." - Benjamin Franklin"Wer seine Freiheit aufgibt, um Sicherheit zu erreichen, wird beides verlieren." - Georg Christoph Lichtenberg
bei Antwort benachrichtigen
Selecta Nachtrag zu: „Problem mit Arrays (Borland C++ 5.0)“
Optionen

Das klappt leider nicht.

Gebe ich dies ein:

1
1
1
1
1

Gibt er: 1 aus. RICHTIG.

ABER:

gebe ich:

1 // Also 2x doppelte Zahlen
1
1
1
1
2
2
2
2
2

Gibt er:

1
1
1
1
1
2
2
2
2
2
1
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2

aus...

Ach ich bin ratlos ...

bei Antwort benachrichtigen
mr.escape Selecta „Das klappt leider nicht. Gebe ich dies ein: 1 1 1 1 1 Gibt er: 1 aus. RICHTIG....“
Optionen

Ja, stimmt. Richtig kommentiert, aber der code war falsch. Das sollte es aber sein:
memoAusgabe->Lines->Add(Zahlen[0]);//gibt es auf jeden fall, ausgeben
for (int d=1; d<i; d++){//prüfe Zahlen[d] beginnend bei d=1
  int gut=1;
  for(int c=0;c<d;c++){
    if (Zahlen[d] == Zahlen[c]){//oops, gibt es schon und wurde darum auch schon ausgegeben
      gut=0;
      break;//beende "for c"
    }
  }
  if(gut)//kein duplikat, ausgeben
    memoAusgabe->Lines->Add(Zahlen[d]);//ok, Zahlen[d] taucht zum ersten mal auf
}


mr.escape

"The man who trades freedom for security does not deserve nor will he ever receive either." - Benjamin Franklin"Wer seine Freiheit aufgibt, um Sicherheit zu erreichen, wird beides verlieren." - Georg Christoph Lichtenberg
bei Antwort benachrichtigen
Selecta mr.escape „Ja, stimmt. Richtig kommentiert, aber der code war falsch. Das sollte es aber...“
Optionen

Danke es funktioniert !

GReeTz Selecta

bei Antwort benachrichtigen
Selecta Nachtrag zu: „Problem mit Arrays (Borland C++ 5.0)“
Optionen

Nein doch nicht ganz, er gibt auch die zahlen aus, wenn sie nur 1x ausgegeben werden.

GreeTz Selecta

Also bei:

1
2
3

gibt er

1
2
3
aus.

bei Antwort benachrichtigen
mr.escape Selecta „Nein doch nicht ganz, er gibt auch die zahlen aus, wenn sie nur 1x ausgegeben...“
Optionen

Hatte übersehen, dass nur (mehrfache) duplikate ausgegeben werden sollen. Nächster versuch:
for (int d=1; d<i; d++){//prüfe Zahlen[d] beginnend bei d=1
  int dupli=0;
  for(int c=0;c<d;c++){
    if (Zahlen[d] == Zahlen[c]){//duplikat
      if(++dupli>1)
        break;//beende "for c", da zweites oder noch späteres duplikat
    }
  }
  if(dupli==1)//erstes duplikat, ausgeben
    memoAusgabe->Lines->Add(Zahlen[d]);
}


mr.escape

"The man who trades freedom for security does not deserve nor will he ever receive either." - Benjamin Franklin"Wer seine Freiheit aufgibt, um Sicherheit zu erreichen, wird beides verlieren." - Georg Christoph Lichtenberg
bei Antwort benachrichtigen
Selecta Nachtrag zu: „Problem mit Arrays (Borland C++ 5.0)“
Optionen

Ok jetzt klappts. Danke für deine Mühen. Hat mir sehr geholfen !

GreeTz Selecta

bei Antwort benachrichtigen