Probleme bei einlesen von arrays über Console
-
Hallo liebe Community, ich bin seit heute neu hier im Forum. Ich habe für mein Studium die Aufgabe bekommen, zwei Arrays über die Console einzulesen und diese dann zu einem Array zu fusionieren und dann aufsteigend zu sortieren.
Bis jetzt habe ich alles hinbekommen bis auf das Einlesen über die Console. Ich bekomme es nur hin, wenn die Werte fix sind, anstatt variabel
Hier der erforderliche Codeausschnitt.
#include <stdio.h> #include <stdlib.h> int main() { int a[1000], b[1000], c[1000]; int n = 0, zahl = 0, i, j, k, z; printf("Gib maximal 10 Zahlen ein\n"); printf("Gib das erste Feld ein: "); for (n=0; n<10; n++){ scanf("%d",&a[n]); zahl = zahl + 1; } for(n=0; n<zahl; n++){ printf("%d,",a[n]); } printf("Gib das zweite Feld ein: "); zahl = 0; for (n=0; n<10; n++){ scanf("%d",&b[n]); zahl = zahl + 1; } for(n=0; n<zahl; n++){ printf("%d,",b[n]); } return 0; }
-
Aktuell verlangst du, dass genau 10 Zahlen eingegeben werden müssen. Nicht mehr und nicht weniger. Das passt nicht zu deiner Textausgabe wo es maximal 10 Zahlen sein sollen.
-
Genau da weiß ich nicht, wie ich es lösen kann bzw. soll. Sitze seit 7:30 Uhr an der Aufgabe.
Ich hatte dieses Problem noch überhaupt nicht. Ich kenne es nur so, dass man feste Zahlen in einer festen Anzahl in der Konsole eintippen und mit scanf ablesen kann. Aber wie sich das bei einem array verhält, weiß ich nicht
-
Wenn die Anzahl anstatt 10 variabel sein soll, dann sollte da statt 10 vielleicht eine Variable stehen
-
Entweder du fragst den Benutzer vorher, wie viele Zahlen eingegeben werden sollen und loopst dann bis zu dieser Zahl oder du liest solange ein, wie der Benutzer gültige Zahlen eingibt (solange das scanf erfolgreich liest). Wenn du dich da erstmal nicht mit Zahlen vs Buchstaben rumschlagen willst, kannst du auch irgendeine Zahl als Ende definieren (nennt sich Sentinel, z. B. -1, und dann checkst du eben, ob -1 eingegeben wurde. Nachteil: dieser Wert kann dann nicht im Array vorkommen)
In jedem Fall solltest du aber sicherstellen, dass die Anzahl der Werte noch in deine Array passt.
-
@SeppJ Ist mir bewusst. Ich frage mich nur, wie ich dem Scanf sagen kann, dass er schluss macht, wenn er alle eingelesenen Zahlen eingelesen hat. Selbst wenn ich in einer Schleife mitzähle, verrät mir der Computer nicht, wann keine Zahl mehr aufkommt oder gibt es eine Möglichkeit, die ich übersehe
-
@wob Dir erstmal ein großes Dankeschön für deine Vorschläge . An ersteres hatte ich auch schon gedacht sowie die Zahlen einfach untereinander niederzuschreiben. Beides hätte mich nicht so viel Zeit gekostet. Ich programmiere aber nicht nur wegen meines Studiums, sondern auch, weil ich C lernen möchte, damit mir C++ später mal leichter fällt.
Konkret muss es doch eine Möglichkeit geben, wie man Zahlen hintereinander eingeben kann und diese als Array einließt, ohne eine Anzahl vorher zu definieren (außer das Array selber).
Beispiel:
Erstes Feld: 1 4 6 3 9 //aus diesem Feld soll das Array a[n] werden.
Jetzt müsste das Programm checken, dass es sich nur um 5 Zahlen handelt, diese ließt er ein und zur Sicherheit spuckt er sie nochmal mit Kommas in die Konsole aus, um zu schauen, dass auch alles reibungslos funktioniert.
-
Schau dir mal den Rückgabewert von scanf an.
-
@Ravensouth sagte in Probleme bei einlesen von arrays über Console:
weil ich C lernen möchte, damit mir C++ später mal leichter fällt.
Damit erreichst du übrigens den gegenteiligen Effekt. Dann programmierst du hinterher C in C++, weil du es so gewöhnt bist, anstatt "richtiges" C++.
-
@Th69 Gefühlt finde ich nichts darüber, was mein Problem lösen kann.
-
@SeppJ Wenn ich es mir ausgesucht hätte, dann hätte ich C# oder C++ im Studium genommen. Leider sind die Profs aus alter Schule.
-
@Ravensouth sagte in Probleme bei einlesen von arrays über Console:
@Th69 Gefühlt finde ich nichts darüber, was mein Problem lösen kann.
Wenn du weisst wie viele Zahlen es maximal sein können, und diese Zahl relativ klein ist, dann hilft es natürlich zu erfahren wie viele Zahlen
scanf
wirklich gefunden hat.Wenn du nicht weisst wie viele Zahlen es max. werden können bzw. die Zahl sehr gross ist, dann kannst du
scanf
mehrfach aufrufen. Dabei kannst du den "conversion specifier"n
verwenden um zu erfahren wie viele Zeichenscanf
gelesen/geparsed hat. Damit kannst du dann den Zeiger für den nächsten Aufruf vonscanf
weiterschieben. Das machst du dann in einer Schleife, bis es keine weiteren Zahlen mehr gibt.
-
@Ravensouth sagte in Probleme bei einlesen von arrays über Console:
Erstes Feld: 1 4 6 3 9 //aus diesem Feld soll das Array a[n] werden.
Die Formatspecifier zum einlesen von Zahlen überlesen führende Whitespace (dazu gehören u.a Leerzeichen, Tabulatoren, Zeilenvorschub (Entertaste)) und hören beim ersten Zeichen auf, dass nicht mehr zu der Zahl passt.
Für scanf ist es egal, ob du die ZAhlen in einer Zeile schreibst oder jede in einer Zeile oder ein Mischmasch davon.Du musst also erkennen, dass nach der 9 ein '\n' von der Entertaste kommt - zwischen 9 und der Entertaste können aber noch andere Leerzeichen sein. Das macht das Ganze etwas aufwendiger.
-
EDIT: Nein, geht nicht.
Aufwendiger, ja. Aber es sollte mit%*[]
gehen. Alaint a, b, c, d, e; int const n = scanf("%d%*[ \t\v\f\r]%d%*[ \t\v\f\r]%d%*[ \t\v\f\r]%d%*[ \t\v\f\r]%d", &a, &b, &c, &d, &e); // ...
Danach steht natürlich das Newline noch im Puffer - und muss ggf. irgendwie entfernt werden wenn es beim nächsten Input nicht stören soll.
-
@hustbaer sagte in Probleme bei einlesen von arrays über Console:
Ala
Wenn du weißt, dass 5 Zahlen in der Zeile stehen, muss ja nicht dieser Aufwand gemacht werden.
Da kommt aber noch mehr dazu.
Z.B. was ist, wenn die Zeilen unterschiedlich viele Zahlen enthalten.
-
@DirkB sagte in Probleme bei einlesen von arrays über Console:
Da kommt aber noch mehr dazu.
Z.B. was ist, wenn die Zeilen unterschiedlich viele Zahlen enthalten.Dann ist der Rückgabewert von
scanf
kleiner?
(Und dass man die maximale Anzahl kennen muss, hab ich ja bereits geschrieben.)
-
@hustbaer
dein dummy-scanset ist sinnfrei, %d macht das inklusive.
-
@Wutz
Danke für die Korrektor.Also es funktioniert wenn das Newline direkt nach der letzten Zahl ist. Dann matched das dummy-scanset nicht, und scanf bricht ab. Es funktioniert aber nicht wenn nach der letzten Zahl erstmal noch ein anderes Whitespace kommt. Dann matched das dummy-scanset das andere Whitespace, scanf macht weiter, und das
%d
matched dann das folgende Newline.D.h. so kann man es nicht machen.
Gibt es überhaupt eine Möglichkeit sowas mit einem
scanf
Aufruf zu machen? Also 1...n Zahlen zu lesen bis zum nächsten Newline.
-
@hustbaer Also ich habe es mittlerweile so gelöst, nachdem ich mir meine Vorlesungsskripte durchgelesen habe.
Bei meinem Programm muss man vorher die Dimension, also die Anzahl der n's vom jeweiligen Feld eingeben. Somit kann man zwei Felder in verschiedener Länge zu einem Feld zusammenfügen und sortieren. Ich habe nmax begrenzt, was jetzt nicht notwendig gewesen wäre, aber in meinem Beispiel will ich das nicht an die Spitze treiben. Ich hatte es auch schon recht weit ohne die Angabe von der Anzahl des Feldes geschafft, sprich ohne n. Allerdings nur in Form eine Zeichenkette mit getchar. Das Problem lag dann darin, die Zeichenketten von a uns b zusammenzufügen zu Feld c. Wenn man die Zeichenekette im Integer ausgeben könnte, dann sollte es funktionieren.#include <stdio.h> int main() { int nmax = 40; int i, an, bn, nges, j, z; int ai = 0, bi = 0; int a[nmax], b[nmax], *cpr; int c[nmax]; do { printf("Maximale Anzahl im Feld: %d\n", nmax); /*Maximale Anzahl an Zahlen im Feld*/ printf("Groesse Feld a: "); /*Größe von Feld a*/ scanf("%d", &an); printf("Groesse Feld b: "); /*Größe von Feld b*/ scanf("%d", &bn); nges = an + bn; /*Größe von Feld a + Feld b*/ } while (an < 1 && bn < 1|| an > nmax && bn > nmax); /*Bedingung: Felder kleiner 1 oder größer 40 --> Wiederholung*/ for (i = 0; i < an; i++) /*Feld a und b einzeln aufgelistet, damit man die Zahlen einzeln eintippen kann*/ { printf("a[%d]= ", i); scanf("%d", &a[i]); } for (i = 0; i < bn; i++) { printf("b[%d]= ", i); scanf("%d", &b[i]); } for (i = 0; i < an; i++) /*Feld a in Feld c einfügen*/ { cpr = &a[ai]; c[i] = *cpr; ai = ai + 1; } for (i = nges-bn; i<nges; i++){ /*Unsortiert: Feld b nach Feld a in Feld c einfügen*/ cpr = &b[bi]; c[i] = *cpr; bi = bi + 1; } printf("c[] unsortiert = {"); for(i=0;i<nges;i++){ /*Unsortiert Feld c ausgeben*/ if (i == (nges-1)) { printf("%d", c[i]); /*ohne Komma, wenn letzte Zahl*/ } else{ printf("%d,", c[i]); /*mit Komma, wenn letzte Zahl noch nicht erreicht*/ }} printf("}"); printf("\nc[] sortiert = {"); for(i=0; i<nges-1; i++) /*Feld c sortieren*/ { for (j=i+1; j<nges; j++) { if (c[i]>c[j]) { z = c[i]; c[i]=c[j]; c[j] = z; } } } for (i=0; i<nges; i++) /*Feld c sortiert ausgeben*/ { if (i == nges-1){ printf("%d", c[i]); } else { printf("%d,", c[i]); } } printf("}"); return 0; }
-
...und jetzt kannst du anfangen, Funktionen zu verwenden. Ein guter Anhaltspunkt sind übrigens deine eigenen Kommentare. Immer dann, wenn du mit einem Kommentat einen Block beschreibst, sollte dieser Block wohl eine Funktion sein.
Beispiele:
-
Zeile 25 bis 34: Dein Kommentar:
/*Feld a und b einzeln aufgelistet, damit man die Zahlen einzeln eintippen kann*/
Du machst 2x das gleiche, nämlich in einer Schleife über ein Array loopen und ausgeben/einlesen. Als Funktion könntest du hier eine allgemeine Funktion zum Einlesen von n Zahlen in EIN Array erstellen udn diese dann für a und b aufrufen. -
Zeilen 36-41:
/*Feld a in Feld c einfügen*/
- also als allgemeine Funktion vielleicht "ein Feld in ein anderes einfügen"? Allgemein sollten deine Variablen nur einen kleinen Gültigkeitsbereich haben, hier z.B.ai
. Die sollte nur hier verfügbar sein, nicht global. (und wozu brauchst ducpr
?) -
Dann hast du "Feld ausgeben" in Zeile 51 bis 60 und 77 bis 86. Das ist doch 2x das gleiche, nur mit anderen Daten! Also eine Funktion machen und die dann an den beiden Stellen aufrufen.
-
Und Sortieren in Zeile 64 bis 76 ist doch auch eindeutig eine Funktion.
-
-
@wob Danke dir für deine ausführliche Hilfe. In meinen neuen Skripten steht etwas über Funktionen und bis jetzt bin ich noch nicht dahinter gestiegen. Ich habe nur gesehen, dass das etwas mit Rückgabewerten und Parametern zu tun hat wie z.B. void bezeichnung (int k) --> das wäre jetzt meines Wissens nach ein Parameter ohne Rückgabewert. Was das genau bedeutet, weiß ich leider noch nicht.