Überprüfen ob Zahl schon im Array
-
Außerdem wird so, wie es da steht, der zweite Schleifendurchlauf in der Funktion ist_in_feld nie erreicht, und das Verhalten ist für anzahl == 0 undefiniert.
-
Ja für anzahl==0 ist das ja nicht so wichtig oder?
Ich meine wenn ich überpüfe, ob meine Zahl unter den ersten null Einträgen ist, macht das eher wenig Sinn oder? Dann ist das Feld ja eh noch leer...
Oder versteh ich da was falsch?Ja das mit dem Schleifendurchlauf ist mir auch schon aufgefallen.
Für die zweite Komponente geht noch alles glatt, dann merkt er wenn die Zahl bereits in der ersten eingelesen wurde.Allerdings kann ich die zweite Komponente auch in die dritte schreiben, da die Funktion ja nach dem ersten Durchlauf "0" zurückliefert, also signalisiert, die Zahl ist noch nicht im Feld.
Hat da jemand nen Denkanstoß?
Hab schon paar Dinge versucht aber nix davon hat funktioniert...
-
int ist_in_feld(int feld[], int zahl, int anzahl) { int i; for (i=0; i<anzahl; i++) { if (feld[i]==zahl) return 1; else return 0; } }
Ablauf in Worten:
Wenn feld[0]==zahl, gib 1 zurück andernfalls gib 0 zurück Funktion beendet sich auf jeden Fall.
Das Problem ist das
else
, es verhindert einen zweiten Schleifendurchlauf. Und jetzt denk mal scharf nach, wohin dasreturn 0;
gehört...
-
Oh mein Gott, jetzt sitz ich hier seit ner halben Stunde und mach mir genau über die von dir angesprochene Tatsache mit dem 100%igen beenden der Funktion Gedanken und der Satz
Und jetzt denk mal scharf nach, wohin das return 0; gehört...
hat das ganze offensichtlich gemacht...
else weg und das return 0; hinter die geschweifte Klammer der for-Schleife.
-
m0pf schrieb:
Ja für anzahl==0 ist das ja nicht so wichtig oder?
Wieso soll das nicht wichtig sein? Wenn deine Funtkion bei lerren Array nur einen zufälligen Wert zurückliefert und an Hand dieses Wertes Dein Array sein erstes Element erhält oder nicht, dann ist das problematisch.
m0pf schrieb:
Ich meine wenn ich überpüfe, ob meine Zahl unter den ersten null Einträgen ist, macht das eher wenig Sinn oder? Dann ist das Feld ja eh noch leer...
Oder versteh ich da was falsch?Ja, du verstehst das völlig falsch. Bei einen leeren Array brauchst Du halt nur nicht nachschauen ob der Wert enthalten ist. Du kannst gleich eine 0 zurückgeben.
m0pf schrieb:
Ja das mit dem Schleifendurchlauf ist mir auch schon aufgefallen.
Für die zweite Komponente geht noch alles glatt, dann merkt er wenn die Zahl bereits in der ersten eingelesen wurde.Allerdings kann ich die zweite Komponente auch in die dritte schreiben, da die Funktion ja nach dem ersten Durchlauf "0" zurückliefert, also signalisiert, die Zahl ist noch nicht im Feld.
Hat da jemand nen Denkanstoß?
Hab schon paar Dinge versucht aber nix davon hat funktioniert...Das Problem ist, Deine Schleife entscheidet schon im ersten Durchlauf, ob eine 1 oder 0 zurückgeliefert werden soll. Wenn die Zahl gefunden wurde, kannst Du gleich eine 1 zurückliefern. Wenn nicht, mußt Du aber erst das Ende der Schleife abwarten. Dann klappst auch mit leeren Arrays.
mfg Martin
-
So um auch die Sache mit den leeren Arrays zu klären hier mal mein Code der jetzt (soweit ich das einschätze) funktioniert:
# include <stdio.h> int ist_in_feld(int feld[], int zahl, int anzahl) { int i, a; for (i=0; i<=anzahl; i++) { if (feld[i]==zahl) return 1; } return 0; } void lies_perm(int feld[], int n) { int laenge, j, zahl; for (j=0; j<n; j++) { printf("Perm_%i = ", j+1); scanf("%i", &zahl); if (zahl<1 || zahl>n) { printf("Der eingegebene Wert ist zu gross oder zu klein.\n"); j--; } else if (ist_in_feld(feld, zahl, j)==1) { printf("%i wurde bereits eingelesen.\n", zahl); j--; } else feld[j]=zahl; } }
-
m0pf schrieb:
So um auch die Sache mit den leeren Arrays zu klären hier mal mein Code der jetzt (soweit ich das einschätze) funktioniert:
Hallo,
er sollte jetzt funktionieren. Dennoch zwei Tips:
1. Schalte die Warnungen des Compilers nicht aus und ignoriere diese nicht, bevor Du Code hier postest.
2. Achte darauf, daß Dein Code ordentlich formatiert ist, wenn Du möchtest, daß andere Ihre Freizeit opfern, um Deinen Code zu analysieren.mfg Martin
-
Ok, vielen Dank schonmal für die Hilfe bisher.
Sorry falls mein Code noch keine so guten Einrückungen etc. hat, aber bin kompletter Neuling in C.
Falls ich eurer Meinung nach etwas "lesbarer" gestalten könnte wäre ich konstruktiver Kritik nicht abgeneigt.Zu den Compiler-Meldungen:
Natürlich versuche ich diese erst selbst zu beheben, sonst lern ich die Sache ja auch nicht. Nur wenn ich wirklich nach intensiver Überlegung nicht drauf komme frage ich hier nach.Wo wir gerade beim intensiven Überlegen sind
Ich sollte ebenfalls eine Funktion schreiben, die mir das Signum einer Permutation berechnet.Kann mir jemand sagen, ob der so passt?
Beispiele haben bisher keine Fehler geliefert.int perm_signum(int feld[], int n) { int b, c, inv, signum; inv=0; for(b=1; b<n; b++) { //laufe alle Indizes durch for (c=0; c<b; c++) { //durchlaufe alle Indizes kleiner b if (c<b && feld[c]>feld[b]) //überprüfe Inversionen inv++; } } if (inv%2==1) signum=-1; else signum=1; return signum; }
Vielleicht kann mir da ja auch jemand was zu meiner Codeformatierung sagen wenns nicht zu viele Umstände macht
-
Leerzeilen und Einrücke bei geschweiften Klammern hilft enorm!
int perm_signum(int feld[], int n) { int b, c, inv, signum; inv=0; for(b=1; b<n; b++) { //laufe alle Indizes durch for (c=0; c<b; c++) { //durchlaufe alle Indizes kleiner b if (c<b && feld[c]>feld[b]) //überprüfe Inversionen inv++; } } if (inv%2==1) signum=-1; else signum=1; return signum; }
viele machen es aber auch wie folgt:
int perm_signum(int feld[], int n) { int b, c, inv, signum; inv=0; for(b=1; b<n; b++) //laufe alle Indizes durch { for (c=0; c<b; c++) //durchlaufe alle Indizes kleiner b { if (c<b && feld[c]>feld[b]) //überprüfe Inversionen inv++; } } if (inv%2==1) signum=-1; else signum=1; return signum; }
-
Jeder hat seinen persönlichen Stil, ich hab folgenden:
int perm_signum(int feld[], int n) { int b, c, inv=0; for (b=1; b<n; b++) /* Bearbeite jedes Element aus feld[] */ for (c=0; c<b; c++) /* Bearbeite bis zum aktuellen Element */ if (feld[c]>feld[b]) /* Hier hab ich c<b rausgenommen */ inv++; /* stilhilfe hat das nicht eingerückt */ return inv%2 ? -1 : 1; /* Signum ist abhängig von der Parität */ }
Wichtig: Das Kommentarzeichen
//
ist im Standard C nicht definiert, daher musst du/* ... */
verwenden.
Ich rücke mit 4 Leerzeichen ein, manche (der Linuxkernel) verwenden 8.
Ich mag vertikale Ausrichtung, weil es schick aussieht und mit guten Editoren (Emacs, Vim) manchmal eine gewisse Vereinfachung beim Refaktorisieren bietet.Die Klammern hab ich mal rausgenommen, wenn von vornherein klar ist, dass es nicht mehrere braucht, würde ich dir das empfehlen. Ansonsten immer Klammern setzen, von aussen bis dahin, wo du welche brauchst. Wenn das zweite for aus zwei Anweidungen bestehen würde, musst du auch um das erste eine Klammer setzen.
Eine öffnende Klammer auf eine einzelne Zeile zu setzen finde ich Platzverschwendung, die schliessende auf eine einzelne zeigt die Trennung zum restlichen Code an. Das gilt überall, nur bei Funktionen nicht, weil die sich als einziges Konstrukt von C nicht schachteln lassen (hier jede Klammer auf eine neue Zeile).Kommentare, und das gilt ganz allgemein, sollten nie offensichtliche Dinge beschreiben. "laufe alle Indizes durch" ist nichtsaussagend, sowas lässt du besser weg. (Und wenn es professioneller wird, ist Englisch eine bessere Sprache für die Kommentare.)
signed int perm_signum(int field[], size_t n) { int inv=0, *pa, *pb; for (pa=field; n>=0; --n, ++pa) for (pb=field; pb<pa; ++pb) if (*pb > *pa) ++inv; return inv%2 ? -1 : 1; }
Das nur so am Rande.
-
HumanInterpreter schrieb:
Wichtig: Das Kommentarzeichen // ist im Standard C nicht definiert, daher musst du /* ... */ verwenden.
Aus Wikipedia Varianten der Programmiersprache C
Wichtigste Neuerungen von C99
....
- Zulassen des aus C++ bekannten Zeilenkommentars „//“.