PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C -> FiFo -> Problem



hunter
30-01-2004, 14:40
Ich will ein Array anlegen und nach FiFo Verfahren Werte anhängen bzw. vorne rausholen.

Hab mir gedacht ich mache es nach dem Schema:

- Array anlegen
- Funktion NextIn(int n) soll einen neuen Wert anhängen
- Funktion NextOut() soll den ersten Wert auslesen und alle eins aufrücken lassen
- Main läuft Schleife durch und bietet Optionen an: Input, Output, Liste Ende

Jetzt treten da aber irgendwie haufenweise Fehler auf:

- Feldlänge ist nicht wie gewünscht
- Case spuckt regelmäßig default aus, obwohl Eingabe gültig
- Schleife läuft dann zwei mal durch (einmal ungültig und dann wieder auf Eingabe wartend)
- Funktionen arbeiten nicht wie gewünscht

Irgendwie kann ich da den Fehler nicht erkennen. Ich hänge das Programm mal an. Vieleicht kann mir da jemand weiterhelfen.

Jack's Cancer
30-01-2004, 18:56
Ein Fehler ist, dass du das return in NextOut falsch gesetzt.
return beendet die Funktion sofort, so dass die nachfolgenden Befehle im else-Teil nicht ausgeführt werden.

Ein anderes Problem ist, denke ich, dass bei einer zweiten Abfrage der Eingabe noch das ENTER als Eingabe gelesen wird. Da kenn ich mich aber nicht konkret aus. Abhilfe könnte vielleicht jeweils ein fflush(stdin) nach den scanf-Aufrufen bringen.

Dann sind die Bedingung in den For-Schleifen falsch gesetzt. Dies sind keine Abbruchbedingungen, sondern sondern solche, die erfüllt sein müssen damit die Schleifen durchlaufen werden. Das >= muss in ein < umgewandelt werden.

Bei den Einfüge- und Ausleseoperationen weiss ich jetzt nicht wie das gemeint sein soll. Warum wird FirstIn erhöht und erniedrigt? FirstIn und zaehler haben dann ja immer dieselben Werte. Demnach wird bei der Ausgabe nichts zu sehen sein.

wraith
30-01-2004, 19:11
Original geschrieben von Jack's Cancer

Ein anderes Problem ist, denke ich, dass bei einer zweiten Abfrage der Eingabe noch das ENTER als Eingabe gelesen wird. Da kenn ich mich aber nicht konkret aus. Abhilfe könnte vielleicht jeweils ein fflush(stdin) nach den scanf-Aufrufen bringen.
http://www.comeaucomputing.com/techtalk/#flushinput
:)

hunter
30-01-2004, 21:12
Danke. Hab das noch mal gründlich durchdacht und umgeschrieben. Dann habe ich die ganzen Funktionen manuell gestartet und getestet. Es funktioniert auch einwandfrei und wie es soll. Der blöde zaehler ist auch rausgeflogen.

Aber das mit der ungültigen Eingabe passiert immer noch. Vermutlich wirklich weil das Enter ja auch ein Zeichen ist. Der von dir angegebene Befehl funktioniert allerdings nicht.

Wenn ich das noch in den Griff bekommen könnte, würde das Prog vollständig laufen.


Ich hänge das aktuelle Programm noch mal an. Bin mir sicher das jetzt nur noch in der while Schleife was nicht stimmt.

wraith
30-01-2004, 21:27
Original geschrieben von hunter

Aber das mit der ungültigen Eingabe passiert immer noch. Vermutlich wirklich weil das Enter ja auch ein Zeichen ist. Der von dir angegebene Befehl funktioniert allerdings nicht.
Den Link lesen und verstehen.
Dann folgende Funktion einfügen


void eatToNL(FILE * inputStream)
{
int c;
/* Eat till (& including) the next newline */
while ((c = getc(inputStream)) != EOF)
if (c == '\n')
break;
}

und dann nach den scanfs eatToNL(stdin); einfügen.

hunter
30-01-2004, 21:32
Danke. Jetzt funktionierts.

panzi
30-01-2004, 21:39
also wenn's c++ angehn würd, dann würd ich dir std::queue vorschlagen.
in c++ gibts viele coole container: http://www.fredosaurus.com/notes-cpp/stl/containers.html

hunter
30-01-2004, 21:48
Nur unglücklicherweise heißt die Vorlesung "C" und nicht "C++". :)

panzi
30-01-2004, 23:42
Ok, mir war langweilig (obwohl ich was zu tun hätt...)
Hab eine fifo "Klasse" in c gecoded. Wieder mal ein Teil von "libpanzi". ;)

Die "Klasse" unterstützt die Typen int, long, char, float, double sowie auch den c-string (char*) intern. Man muss nur den jeweiligen "Konstruktor" wählen.

test_fifo.c zeigt wie man's verwendet.


PS: fifo.h in einen Ordner namens libpanzi haun, und der Ordner in dem libpanzi liegt in den include Path. (oder die #include Anweisungen in den .c Datein ändern.)

panzi
31-01-2004, 00:15
Ok, jetzt geh ich aaber schlafen...

Hab's noch ein wenig erweiter:
Mit fifo_copy(src, dest) kann man ein fifo "Objekt" kopiern.
Hab auch noch support für size_t hinzugefügt. Man könnt das noch um alle typen wich auch long long, unsignet int usw. erweitern. Wobei's für unsigned wohl wurscht ist, da man einfach anders castet und es trotzdem richtig funkt. (es geht ja darum die richtige storage size zu haben, Rest is wurscht.)

Und hab noch support für fifo selber hinzugefügt. Also ein fifo "Objekt" kann andere fifo "Objekte" speichern! Dazu hab ich einfach nen copier programmiert, welcher ein fifo_t malloct und dann (wenn != NULL) fifo_copy darauf anwendet. Und der deallocator wendet fifo_clear und free darauf an.

wraith
31-01-2004, 09:28
@panzi
Ich glaube 'code bloat' beschreibt den Code am besten ;),teilweise versteckt hinter Makros.

Es geht viel simpler,ohne für jeden Typ neue Funktionen zu schreiben (was ist wenn ich ein struct speichern will?)
Ändere den Type void *data in char *data,und jeder Funktion übergibst du Größe in Bytes des Typs mit dem du arbeitest.
Orientiere dich an qsort,da wurde auch nicht für jeden Typ eine extra Funktion geschrieben.

panzi
31-01-2004, 14:31
Original geschrieben von wraith
@panzi
Ich glaube 'code bloat' beschreibt den Code am besten ;),teilweise versteckt hinter Makros.

Es geht viel simpler,ohne für jeden Typ neue Funktionen zu schreiben (was ist wenn ich ein struct speichern will?)
Ändere den Type void *data in char *data,und jeder Funktion übergibst du Größe in Bytes des Typs mit dem du arbeitest.
Orientiere dich an qsort,da wurde auch nicht für jeden Typ eine extra Funktion geschrieben.

Naja, aber eben bei structs kann's da zu problemen kommen. Denn dann würd' ja immer nur ne flat copy g'macht werden, und beim löschen würden möglicherweiße in der struct gepointete variablen nicht gelöscht werden....

Ich hab halt lieber c++, und da überläd man einfach operator = bzw. schreibt man einen konstruktor und destruktor.


PS: Hab im fifo_copier nen Fehler!
In fifo.c in Zeile 208 (nach dem if(reply != NULL) {) folgendes einfügen:

fifo_init(reply, ((const fifo_t*)data)->copier, ((const fifo_t*)data)->deallocator);