Probleme bei einlesen von arrays über Console
-
@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.
-
@Ravensouth sagte in Probleme bei einlesen von arrays über Console:
Was das genau bedeutet, weiß ich leider noch nicht.
Warum nicht? Du kennst doch sicher z.B. trigonometrishe Funktionen wie Sinus. Was machen die? Was sind Parameter, was geben sie zurück? Kannst du das abstrahieren?
-
Hallo @Ravensouth ,
Eine Funktion (siehe auch Methode) ist so etwas wie ein kleines Unterprogramm. Du vergibst einen sprechenden Namen, wie addiereGanzzahlen, und damit die Funktion weiß, welche Werte sie addieren soll übergibst Du der Funktion addiereGanzzahlen zwei Werte (wert1 und wert2) als Parameter.Sieht jetzt schon mal so aus:
addiereGanzzahlen( int wert1, int wert2);
Voila, jetzt brauchen wir nur noch das Ganzzahl-Ergebnis, das kennzeichnen wir, indem wir den Rückgabetyp davor schreiben…
int addiereGanzzahlen( int wert1, int wert2);
Jetzt noch die Ausführung definieren (ein bisschen komplexer zum Verständnis)…
int addiereGanzzahlen( int wert1, int wert2) { int retVal = wert1 + wert2; // hier wird addiert und die Summe einer Variablen zugewiesen return retVal; // hier wird der Wert zurückgeliefert };
Jetzt nutzen wir unsere kleine Funktion:
... int meinZuBerechnenderWert = addiereGanzzahlen( 123, 456 ); ...
meinZuBerechnenderWert sollte jetzt den Wert 579 haben.
Funktionen, die keinen Rückgabewert liefern sollen, werden mit dem Schlüsselwort void eingeleitet.void tuWasOhneWasZuLiefern( … );
Zum Anfang sollte das reichen, ansonsten gibt’s da noch ne Menge nachzulesen.
-
@Mechanics Sowas hatten wir im Abitur. Kommt sicherlich im Studium auch noch dran. Habe sowieso das Gefühl, als würde sich Mathe und Informatik bei uns jetzt ziemlich stark überschneiden wie sonst nie zuvor.
-
@Helmut-Jakoby Ach so. Jetzt verstehe ich wie man die Funktion in der Praxis anwendet. Ein sehr gutes Beispiel. Danke dir
-
@hustbaer
Man nutzt überhaupt niemals scanf.
Man nutzt fgets+sscanf.
Das funktioniert dann auch in stdin redirections via commandline-Pipe und auch für beliebig viele (vorher unbekannte Anzahl von - alledings gleichtypisierten) Inputs.
-
@Ravensouth sagte in Probleme bei einlesen von arrays über Console:
Ich habe nmax begrenzt,
Mache aus "int nmax=40" ein enum { NMAX=40 };
dann sind deine Arrays keine VLA, und dein Code nähert sich etwas einer professionellen Programmierung.Nutze in deinen for-Schleifen für i die initial declaration, also
for(int i=0;...;...)
-
@Wutz sagte in Probleme bei einlesen von arrays über Console:
@hustbaer
Man nutzt überhaupt niemals scanf.
Man nutzt fgets+sscanf.
Das funktioniert dann auch in stdin redirections via commandline-Pipe und auch für beliebig viele (vorher unbekannte Anzahl von - alledings gleichtypisierten) Inputs.Was soll denn da bitte der Zusammenhang sein?
-
@SeppJ
fgets kümmert sich um Newlines & Co, und sscanf kümmert sich um die eigentliche Aufgabe.
sscanf arbeitet auf dem char-Stream, und somit sauber getrennt vom Inputverfahren.
-
Was soll das mit Pipes zu tun haben?
edit: Beitrag auf das wesentliche beschränkt und Nebendiskussionen entfernt.