dringende Anfängerhilfe verkettete Liste

Schnelle objektorientierte, kompilierende Programmiersprache.
Capatcha
Beiträge: 13
Registriert: Sa Nov 28, 2009 2:03 pm

dringende Anfängerhilfe verkettete Liste

Beitrag von Capatcha » Sa Nov 28, 2009 2:13 pm

Hallo Community,
bin so ziemlich verzweifelt und weiß echt nicht mehr weiter, deshalb versuche ich mal hier Hilfe zu finden.

Die Aufgabenstellung die ich machen muss ist eigentlich einfach, aber für mich fast ein Ding der Unmöglichkeit. :(

Es geht um eine einfach verkettete Liste. Und zwar soll man eine "Einkaufslistenverwaltung" Programmieren.

Die Aufgabenstellung findet man im Anhang.

Habe es anhand eines Buchs und mit Internetrecherche zu lösen, aber nach nun 4h weiß ich einfach nicht mehr weiter.
Natürlich poste ich auch das, was ich bis jetzt geschrieben habe.

Code: Alles auswählen

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct elem {
 char name[20];
 int anzahl;
 int kategorie;
 struct elem *next;
};



int main(void) {
    int anzahl;
    int kategorie;
    struct elem
    *anfang = NULL, *cursor;
    char name[20];


    while (1) {
        printf("\nProdukt:");
        fgets(name, 20, stdin);
        printf("\nAnzahl:");
        scanf("%d", &anzahl);
        printf("\nKategorie:");
        scanf("%d", &kategorie);

        if (strlen (name) == 1 , anzahl == 1 , kategorie == 1)
                    break;

        cursor =malloc(sizeof(struct elem));

        if (cursor == NULL) {
            printf("Speicherplatzmangel\n");
            exit(1);
            }

        strcpy(cursor -> name, name);
        cursor -> next = anfang;
        anfang = cursor;
        }

printf("Ausgabe");
while(cursor!=NULL) {
    printf("%s", cursor -> name);
    cursor = cursor -> next;
    }

    return 0;
}
Ich hoffe ihr könnt mir Laien sagen, wo ich den Fehler gemacht habe. Wahrscheinlich habe ich so viele Fehler gemacht, dass euch übel wird.

Hoffe echt auf eure Hilfe.

-Capatcha
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: dringende Anfängerhilfe verkettete Liste

Beitrag von Kerli » Sa Nov 28, 2009 2:59 pm

Capatcha hat geschrieben:Hallo Community,
bin so ziemlich verzweifelt und weiß echt nicht mehr weiter, deshalb versuche ich mal hier Hilfe zu finden.
Hallo, wilkommen bei uns! Da bist du genau an die richtige Stelle gekommen :P

So wie es scheint hast du das Prinzip einer verketteten Liste eh schon verstanden, aber ohne zu wissen was denn nicht geht können wir schwer sagen was du falsch machst. Nur eine Zeile ist mir aufgefallen, die ziemlich sicher von dir nicht absichtlich so geschrieben ist:

Code: Alles auswählen

if (strlen (name) == 1 , anzahl == 1 , kategorie == 1)
break;
Das break dort nur dann ausgeführt wenn die erste Bedingung erfüllt ist, also das "strlen(name) == 1". Der Kommaoperator gibt nämlich immer das Ergebnis der linken Seite zurück. Du brauchst wahrscheinlich eher den logischen Oder-Operator. Schau dazu am Besten einfach in unser Wiki.

Ein zweites Problem ist das einlesen von Text aus der Konsole mit fgets, da dir das immer das zurückgibt was gerade im Eingabebuffer drinnen steht. [/* edit: Stimmt nicht. Ich hab wohl etwas zu vorschnell gepostet :P */] Stattdessen kannst du auch scanf verwenden, oder besser, damit du auch die Länge des eingelesenen Strings begrenzen kannst zb getchar (in einer Schleife...).
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Capatcha
Beiträge: 13
Registriert: Sa Nov 28, 2009 2:03 pm

Re: dringende Anfängerhilfe verkettete Liste

Beitrag von Capatcha » Sa Nov 28, 2009 3:38 pm

Hi, danke für die schnelle Hilfe.

Stimmt, die Abbruchbedingung ist Schwachsinn.
Vor allem, da es nur abgebrochen werden sollte, falls das zu eingegebende "Produkt" nicht eingegeben wird.

Auch muss ich sagen, dass ich diesen Code großteils vom Buch abgetippt habe und einige Sachen abgeändert.

Mein Problem ist, dass ich pro Produkt die Anzahl und die Kategorie mit angeben soll.
Wenn ich das jetzt in meinem Programm mache, dann kann ich beim ersten durchlauf die drei Sachen (Produkt, Anzahl, Kategorie) eingeben. Beim zweiten Durchgang kann ich beim Produkt nichts mehr eingeben. Das wird einfach übersprungen und so kann ich die Eingabe auch nicht abbrechen (da wenn nichts beim Produkt steht, es die Abbruchbedingung ist, aber da ich ja nichts eingeben kann bzw. immer etwas dasteht was man nicht sieht, kann ich es nicht abbrechen).

Ich glaube mein großes Problem beim Code liegt derzeit bei dem Scanf und fgets.
Kann mir einer sagen, wie ich das mit getchar am besten löse? Probiere es in der Zwischenzeit selber, aber ich glaube ich mache wieder mal einen Anfängerfehler.

Mfg
-Capatcha

Capatcha
Beiträge: 13
Registriert: Sa Nov 28, 2009 2:03 pm

Re: dringende Anfängerhilfe verkettete Liste

Beitrag von Capatcha » Sa Nov 28, 2009 4:39 pm

Habe dieses Problem nun gelöst.

Jetzt weiß ich aber nicht, wie ich bei Aufgabe b diesen "void print" Befehl angehe.

Kann mir da einer Tipps geben?

Ach ja, im Anhang der bisher geschriebene Code:

Code: Alles auswählen

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct elem {
 char name[20];
 int anzahl;
 int kategorie;
 struct elem *next;
};

void loescheTastaturpuffer()
{
  int c;
  while( ((c = getchar()) != EOF) && (c != '\n') )
     ;
}




int main(void) {
    int anzahl;
    int kategorie;
    struct elem
    *anfang = NULL, *cursor;
    char name[20];


    while (1) {
        printf("\nProdukt:");

        fgets(name, 20, stdin);
        if (strlen (name) == 1)
                    break;

        printf("\nAnzahl:");
        scanf("%d", &anzahl);
        printf("\nKategorie:");
        scanf("%d", &kategorie);
        loescheTastaturpuffer();



        cursor =malloc(sizeof(struct elem));

        if (cursor == NULL) {
            printf("Speicherplatzmangel\n");
            exit(1);
            }

        strcpy(cursor -> name, name);
        cursor -> next = anfang;
        anfang = cursor;
        }


    return 0;
}

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: dringende Anfängerhilfe verkettete Liste

Beitrag von Kerli » Sa Nov 28, 2009 5:19 pm

Capatcha hat geschrieben:Ich glaube mein großes Problem beim Code liegt derzeit bei dem Scanf und fgets.
Genau. Das was ich vorher darüber gesagt habe hat nicht so ganz gestimmt. Richtig ist, dass fgets bis zum ersten Newline oder End-of-File in einem Eingabestrom liest. Bei deiner Kombination ist jetzt das Problem dass aus irgendeinem Grund ein Newline im EIngabestrom steht. Aus dem Grund solltest du vor dem Einlesen ein eventuell anstehendes Newline verwerfen:

Code: Alles auswählen

char tmp = getchar();
if( tmp && tmp != '\n' ) // War ein Newline oder Nullcharakter da?
  putc(tmp,stdin);      // Wenn nicht, dann wieder zurück in den Eingabestrom...
fgets( /*...*/ );
Wenn du direkt mit getchar einlesen möchtest (vor allem sinnvoll wenn die Eingabe unbekannte Länge haben kann) dann musst du einfach in einer Schleife solange Zeichen mit getchar aus dem Eingabestrom holen bis ein EOF (End of File) ankommt. Dabei musst du in einer Variable mitzählen wie viele Zeichen du schon gelesen hast damit du weißt ob noch Platz für weitere Zeichen vorhanden ist und auch an welche Stelle diese geschrieben werden sollen.

zb:

Code: Alles auswählen

char str[20];
int i;
for( i = 0; i < 19; ++i )
{
  char read = getchar();
  switch( read )
  {
    case '\n':  // Bei Newline und EOF Ende der Eingabe
    case EOF:
      break;
    default:
      str[i] = read;
  }
  ++i;
}
str[i] = 0; // Terminieren nicht vergessen...
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Capatcha
Beiträge: 13
Registriert: Sa Nov 28, 2009 2:03 pm

Re: dringende Anfängerhilfe verkettete Liste

Beitrag von Capatcha » Sa Nov 28, 2009 5:39 pm

Danke nochmals für die Hilfe.
Ist total ärgerlich, wenn man etwas programmieren soll, aber wichtige befehle nicht lernt und deshalb das Programm beinahe ein ding der Unmöglichkeit wird...

Also langsam glaube ich, dass ich das Programmieren schön knicken kann...

Soll jetzt das gerade ausgewählte Element in der Konsole ausgeben. Mittels der allgemeinen Funktion "void print(struct elem* elemen)";

Wenn ich es in der main Funktion mache, dann klappt es:

Code: Alles auswählen

   printf("Aktueller Eintrag:\n\n------------------------------------------------------------------\n");
    printf("Produkt:\t %s", cursor);
    printf("Menge:\t\t %d\n", anzahl);
    printf("Kategorie:\t %d\n", kategorie);
    printf("------------------------------------------------------------------\n");
Jetzt will ich diese Zeilen in eine Unterfunktion schieben, aber irgendwie klappt das bei mir nie.

Code: Alles auswählen

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct elem {
 char name[20];
 int anzahl;
 int kategorie;
 struct elem *next;
};

void loescheTastaturpuffer()
{
  int c;
  while( ((c = getchar()) != EOF) && (c != '\n') )
     ;
}

void print(*cursor, int a, int k){

    printf("Aktueller Eintrag:\n\n------------------------------------------------------------------\n");
    printf("Produkt:\t %s", cursor);
    printf("Menge:\t\t %d\n", a);
    printf("Kategorie:\t %d\n", k);
    printf("------------------------------------------------------------------\n");

    }


int main(void) {

    int anzahl;
    int kategorie;
    struct elem
    *anfang = NULL, *cursor;
    char name[20];


    while (1) {
        printf("\nProdukt:");

        fgets(name, 20, stdin);
        if (strlen (name) == 1)
                    break;

        printf("\nAnzahl:");
        scanf("%d", &anzahl);
        printf("\nKategorie:");
        scanf("%d", &kategorie);
        loescheTastaturpuffer();



        cursor =malloc(sizeof(struct elem));

        if (cursor == NULL) {
            printf("Speicherplatzmangel\n");
            exit(1);
            }

        strcpy(cursor -> name, name);
        cursor -> next = anfang;
        anfang = cursor;
        };


    print(cursor, anzahl, kategorie); //Das gerade gewählte Element ausgeben


    return 0;
}
wenn ich den Code kompilieren will, dann klappt es nicht und ich bekomme Fehlermeldungen.

Hier die Fehlermeldungen:
|22|error: (Each undeclared identifier is reported only once|
|19|error: syntax error before '*' token|
||In function `print':|
|22|error: `cursor' undeclared (first use in this function)|
|22|error: (Each undeclared identifier is reported only once|
|22|error: for each function it appears in.)|
|23|error: `a' undeclared (first use in this function)|
|24|error: `k' undeclared (first use in this function)|
||=== Build finished: 6 errors, 0 warnings ===|


Was habe ich hier falsch gemacht? :(

PS: Programmiere erst seit 2 Wochen und ich hoffe ihr verzeiht mir meine Anfängerfehler.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: dringende Anfängerhilfe verkettete Liste

Beitrag von cloidnerux » Sa Nov 28, 2009 5:48 pm

Code: Alles auswählen

void print(*cursor, int a, int k){
cursor hat keinen Typ-spezifizierer(int, void, etc.)

Code: Alles auswählen

*anfang = NULL, *cursor;
Wieder das selbe, zwei Pointer ohne Typ-spezifezierer.
Daher auch deine fehlermeldungen.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Benutzeravatar
stampuhh
Beiträge: 211
Registriert: Sa Nov 07, 2009 4:39 pm
Wohnort: Paderborn

Re: dringende Anfängerhilfe verkettete Liste

Beitrag von stampuhh » Sa Nov 28, 2009 5:53 pm

hey,

bin selber noch recht neu dabei aber ich habe mal etwas gebastelt.

Code: Alles auswählen

void print(struct elem *cursor, int a, int k){

    printf("Aktueller Eintrag:\n\n------------------------------------------------------------------\n");
    printf("Produkt:\t %s", cursor->name);
    printf("Menge:\t\t %d\n", a);
    printf("Kategorie:\t %d\n", k);
    printf("------------------------------------------------------------------\n");

    }
Wieder das selbe, zwei Pointer ohne Typ-spezifezierer.
Die Zuweisung von cursor in der main ist ok würde ich sagen. Steht nur in der Zeile davor.

Du musst allerdings in der main den Aufruf der print-Methode innerhalb der while(1) (also innerhalb der Unendlichschleife) machen sonst wird es nie ausgegeben!

edit: was mir gerade noch aufgefallen ist: Die Variablen Anzahl und Kategorie werden nie dem Element zugewiesen. Du gibst sie einmal aus und überschreibst sie im nächsten Durchlauf mit neuen Werten. Wenn du schon ein struct hast dann könntest du es doch auch nutzen.

Code: Alles auswählen

        
cursor->anzahl = anzahl;
cursor->kategorie = kategorie;
gruß stampuhh
NachDenkSeiten.de

Capatcha
Beiträge: 13
Registriert: Sa Nov 28, 2009 2:03 pm

Re: dringende Anfängerhilfe verkettete Liste

Beitrag von Capatcha » Sa Nov 28, 2009 6:13 pm

Hi,
danke für die Antworten.
Finde es total super, dass hier einem so schnell geholfen wird. Vor allem einem Anfänger.

Also dann habe ich gleich mal ein paar Fragen, da ich ja auch verstehen will, was programmiert wird. :)

*Ich übergebe ja in der Main funktion bei print als ersten Parameter "cursor". Warum muss ich dann im Unterprogramm (void print) "struct elem *cursor" schreiben?
*Warum steht in der Unterfunktion jetzt "cursor->name"? Was macht eigentlich dieser "->" Befehl genau?
*Habe dieses while (1) vom Buch übernommen, weiß aber nicht warum hinter dem "while" eine "(1)" steht.

Hmm, muss wohl ein Listenelement formatiert an der Konsole ausgeben.
Sprich, besteht meine Liste jetzt aus den Einträgen:
Butter 1 1
Toast 1 2
Käse 2 3

dann soll ich zum Beispiel Toast eingeben und er soll mir dann das Listenelement formatiert an der Konsole ausgeben.

Wie mache ich das denn nun? :(

Benutzeravatar
stampuhh
Beiträge: 211
Registriert: Sa Nov 07, 2009 4:39 pm
Wohnort: Paderborn

Re: dringende Anfängerhilfe verkettete Liste

Beitrag von stampuhh » Sa Nov 28, 2009 6:26 pm

Ich versuche es einfach mal zu erklären.
Capatcha hat geschrieben: *Ich übergebe ja in der Main funktion bei print als ersten Parameter "cursor". Warum muss ich dann im Unterprogramm (void print) "struct elem *cursor" schreiben?
Damit in der Methode bekannt ist von welchem Typ "cursor" ist. du hast ja auch "int a" geschrieben und nicht einfach nur "a". Genauso verhält es sich mit "cursor". "struct elem" ist der Typ von dem "cursor" ist.
Capatcha hat geschrieben: *Warum steht in der Unterfunktion jetzt "cursor->name"? Was macht eigentlich dieser "->" Befehl genau?
Das ist ein Zeiger auf das Element "name" in deiner struct elem. "cursor" ist sozusagen das Oberelement und "name" ist ein Teil davon. Und um auf "name" zuzugreifen musst du diesen "->" Operator anwenden. Ich glaube dass kann dir einer der Erfahrenen hier besser erklären ;)
Capatcha hat geschrieben: *Habe dieses while (1) vom Buch übernommen, weiß aber nicht warum hinter dem "while" eine "(1)" steht.
"1" heißt in C "true", also "wahr". Die Schleife wird also solange durchlaufen wie die Bedingung die in der Klammer steht erfüllt ist. "1" (= true) ist aber immer erfüllt, was bedeutet, dass die Schleife endlos durchlaufen wird. Also eine einfache Endlosschleife ;)
Capatcha hat geschrieben: Hmm, muss wohl ein Listenelement formatiert an der Konsole ausgeben.
Sprich, besteht meine Liste jetzt aus den Einträgen:
Butter 1 1
Toast 1 2
Käse 2 3

dann soll ich zum Beispiel Toast eingeben und er soll mir dann das Listenelement formatiert an der Konsole ausgeben.

Wie mache ich das denn nun? :(
Du musst deine Liste solange durchlaufen bis du das entsprechende Element gefunden hast. Also eine Schleife schreiben, die jedes Element überprüft ob der Name == Toast ist. Wenn es so ein Element gibt dann kann die Schleife erfolgreich verlassen werden.
Hoffe das hilft dir schon mal etwas.

edit: Ich kann dir das hier mal empfehlen Listen. Da ist das sehr gut erklärt und sollte jetzt auch ohne Fehler sein. Bei deinem Aufbau ist das Problem, dass du die Listen so nicht durchlaufen kannst, da du den Anfang der Liste nicht kennst. Oder anders gesagt hast du glaube ich noch nicht mal eine Liste wenn ich das richtig überschaut habe, sondern nur ein Element was du immer wieder überschreibst :|

gruß stampuhh
Zuletzt geändert von stampuhh am Sa Nov 28, 2009 6:58 pm, insgesamt 2-mal geändert.
NachDenkSeiten.de

Antworten