Komisches Problem

yax

Erfahrenes Mitglied
Hey,
also ich wusste garnicht wirklich wie ich dieses Thema hier nennen soll, denn ich weiß nicht wirklich was ich falsch gemacht habe...

Ich lese schon seit längeren ein Buch über C und nun bin ich bei den verketteten Listen. Ich habe ein Programm geschrieben das mit einer verketteten Liste Abreitet. Jetzt habe ich aber ein Problem, welches miener Meinung garnichts damit zu tun hat. Wenn ich bei meinem Programm ein neues Element in der Liste erstellen wird, funktioniert die Eingabe nicht wirklich. Ich kann nämlich keinen Namen eingeben, es wird übersprungen.

Kann mir jemand helfen? :D

Code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF 255

struct Noten {
       char name[BUF];
       int note;
       struct Noten *next;
};

struct Noten *anfang = NULL;

void hinzufuegen(char *name, int note) {
     struct Noten *zeiger;
     
     if(anfang == NULL) {
       if((anfang = malloc(sizeof(struct Noten))) == NULL) {
         fprintf(stderr, "Konnte keinen Speicher anfordern\n");
         return;
       }
       strcpy(anfang->name, name);
       anfang->note = note;
       anfang->next = NULL;
     } else {
       zeiger = anfang;
       
       while(zeiger->next != NULL)
         zeiger = zeiger->next;
       
       if((zeiger->next=malloc(sizeof(struct Noten))) == NULL) {
         fprintf(stderr, "Konnte keinen Speicher anfordern\n");
         return;
       }
       zeiger = zeiger->next;
       strcpy(zeiger->name, name);
       zeiger->note = note;
       zeiger->next = NULL;
     }
}

void eingabe(void) {
     char name[BUF];
     int note;
     
     printf("Name....: ");
     fgets(name, BUF, stdin);
     printf("Note....: ");
     scanf("%d", &note);
     hinzufuegen(name, note);
}

void loesche(char *name) {
     struct Noten *weg, *vor;
     
     if(anfang != NULL) {
       if(strcmp(anfang->name, name) == 0) {
         weg = anfang->next;
         free(anfang);
         anfang = weg;
       }else {
         vor = anfang; //vor wird auf den Anfang gesetzt
         
         while(vor->next != NULL) {  //Gibt es ein nächstes Element in der Liste?
           weg = vor->next;          //Wenn Ja, dann gebe weg, die Adresse des nächsten Elementes. Beim ersten durchlauf ist vor = Anfang. Da aber anfang nicht das gesuchte Element sein kann, kann das nächste element das mögliche sein, dass gelöscht werden soll
           if(strcmp(weg->name, name) == 0) {  //Ist das Element (Im ersten durchlauf das Element nach Anfang) das gesuchte,
             vor = weg->next;         //dann bekommt das Element davor die Adresse des Elements des nächsten, als Parameter für *next, da es nach dem löschen des einen, das nächste Element wäre (Im 1. Durchlauf das 3. Element), somit steht das ELement das gelöscht werden kann "frei"
             free(weg);               //Somit wird es jetzt auch "freigelassen"
             break;                   //Und es wird aus der while()-Schleife gesprungen, da das gesuchte Element gefunden und gelöscht wurde
           }
         }
       }
     }else
       printf("Es konnte kein Element gefunden wurden\n");
}

void ausgabe(void) {
     struct Noten *zeiger = anfang;
     
     printf("\n\n");
     printf("==============================\n");
     printf("          Name      |   Note  \n");
     printf("==============================\n");
     
     if(anfang != NULL) {
       while(zeiger != NULL) {
         printf("|         %s        |    %d  |\n", zeiger->name, zeiger->note);
         zeiger = zeiger->next;
       }
       printf("\n\n");
     } else
       printf("Es sind keine Daten in der Liste vorhanden!\n\n");
}

int main(void) {
    int auswahl;
    char name[BUF];
    
    do {
      printf("Was wollen sie machen\n\n");
      printf("-1- Einen neuen Eintrag machen\n");
      printf("-2- Alle Eintraege ausgeben\n");
      printf("-3- Ein Element loeschen\n");
      printf("-0- Programm beenden\n");
      printf("Ihre Auswahl: ");
      scanf("%d", &auswahl);
      
      switch(auswahl) {
        case 1: eingabe();     break;
        case 2: ausgabe();     break;
        case 3: printf("Wie lautet der Name der geloescht werden soll: ");
                fgets(name, BUF, stdin);
                loesche(name);
                break;
        case 0: break;
        default: printf("Falsche Eingabe!!\n");
      }
    }while(auswahl != 0);
    
    system("PAUSE");
    return EXIT_SUCCESS;
}
 
Hi

scanf und gets (und Abartender beiden) haben leider manchmal ein Problem damit, im gleichen Programm verwendet zu werden.

Ich hab eine Einlesefunktion, die das (und auch ein weiteres Problem bei fgets) umgeht,
muss sie nur kurz suchen...

edit:
C++:
int readline(char *buffer, int maxlen)
{
	int i;
	if(NULL == fgets(buffer, maxlen, stdin))
		return 1;
	i = strlen(buffer) - 1;
	if(i >= 0 && buffer[i] == '\n')
		buffer[i] = '\0';
	else
	{
		while(fgetc(stdin) != '\n');
	}
	return 0;
}

Verwendung für Strings sollte klar sein: Als Parameter den String und die maximale Länge.
Wenn der Returnwert 0 ist: Alles gut. Sonst 1.

Für ein int zuerst als String einlesen und dann zB. mit sscanf herauslesen
C++:
char x[1234];
int i;
...
if(readline(x, 1234))
{
    //Fehler
}
if(1 != sscanf(x, "%d", &i))
{
    //Fehler
}

Gruß
 
Zuletzt bearbeitet:
Okay, ich hab auch noch scanf() im Programm, stimmt :D

Ich habe deine Funktion ausprobiert, aber die Eingabe für Name wird immer noch übersprungen...
 
Ich habe ja alle scanf und fgets funktionen durch deine Funktion ersetzt, und ich habe immer noch das gleiche Problem
 
Ich werds bei mir einmal kompilieren...

also ich kann einfügen, löschen, ausgeben und beenden ohne Probleme.

C++:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF 255

int readline(char *buffer, int maxlen)
{
    int i;
    if(NULL == fgets(buffer, maxlen, stdin))
        return 1;
    i = strlen(buffer) - 1;
    if(i >= 0 && buffer[i] == '\n')
        buffer[i] = '\0';
    else
    {
        while(fgetc(stdin) != '\n');
    }
    return 0;
}

struct Noten {
       char name[BUF];
       int note;
       struct Noten *next;
};
 
struct Noten *anfang = NULL;
 
void hinzufuegen(char *name, int note) {
     struct Noten *zeiger;
     
     if(anfang == NULL) {
       if((anfang = (struct Noten *)malloc(sizeof(struct Noten))) == NULL) {
         fprintf(stderr, "Konnte keinen Speicher anfordern\n");
         return;
       }
       strcpy(anfang->name, name);
       anfang->note = note;
       anfang->next = NULL;
     } else {
       zeiger = anfang;
       
       while(zeiger->next != NULL)
         zeiger = zeiger->next;
       
       if((zeiger->next=(struct Noten *)malloc(sizeof(struct Noten))) == NULL) {
         fprintf(stderr, "Konnte keinen Speicher anfordern\n");
         return;
       }
       zeiger = zeiger->next;
       strcpy(zeiger->name, name);
       zeiger->note = note;
       zeiger->next = NULL;
     }
}
 
void eingabe(void) {
     char name[BUF];
     char not[BUF];
     int note;
     
     printf("Name....: ");
     readline(name, BUF);
     printf("Note....: ");
     readline(not, BUF);
     sscanf(not,"%d",&note);
     hinzufuegen(name, note);
}
 
void loesche(char *name) {
     struct Noten *weg, *vor;
     
     if(anfang != NULL) {
       if(strcmp(anfang->name, name) == 0) {
         weg = anfang->next;
         free(anfang);
         anfang = weg;
       }else {
         vor = anfang; //vor wird auf den Anfang gesetzt
         
         while(vor->next != NULL) {  //Gibt es ein nächstes Element in der Liste?
           weg = vor->next;          //Wenn Ja, dann gebe weg, die Adresse des nächsten Elementes. Beim ersten durchlauf ist vor = Anfang. Da aber anfang nicht das gesuchte Element sein kann, kann das nächste element das mögliche sein, dass gelöscht werden soll
           if(strcmp(weg->name, name) == 0) {  //Ist das Element (Im ersten durchlauf das Element nach Anfang) das gesuchte,
             vor = weg->next;         //dann bekommt das Element davor die Adresse des Elements des nächsten, als Parameter für *next, da es nach dem löschen des einen, das nächste Element wäre (Im 1. Durchlauf das 3. Element), somit steht das ELement das gelöscht werden kann "frei"
             free(weg);               //Somit wird es jetzt auch "freigelassen"
             break;                   //Und es wird aus der while()-Schleife gesprungen, da das gesuchte Element gefunden und gelöscht wurde
           }
         }
       }
     }else
       printf("Es konnte kein Element gefunden wurden\n");
}
 
void ausgabe(void) {
     struct Noten *zeiger = anfang;
     
     printf("\n\n");
     printf("==============================\n");
     printf("          Name      |   Note  \n");
     printf("==============================\n");
     
     if(anfang != NULL) {
       while(zeiger != NULL) {
         printf("|         %s        |    %d  |\n", zeiger->name, zeiger->note);
         zeiger = zeiger->next;
       }
       printf("\n\n");
     } else
       printf("Es sind keine Daten in der Liste vorhanden!\n\n");
}
 
int main(void) {
    int auswahl;
    char name[BUF];
    
    do {
      printf("Was wollen sie machen\n\n");
      printf("-1- Einen neuen Eintrag machen\n");
      printf("-2- Alle Eintraege ausgeben\n");
      printf("-3- Ein Element loeschen\n");
      printf("-0- Programm beenden\n");
      printf("Ihre Auswahl: ");
      readline(name, BUF);
     sscanf(name,"%d",&auswahl);
      
      switch(auswahl) {
        case 1: eingabe();     break;
        case 2: ausgabe();     break;
        case 3: printf("Wie lautet der Name der geloescht werden soll: ");
                readline(name, BUF);
                loesche(name);
                break;
        case 0: break;
        default: printf("Falsche Eingabe!!\n");
      }
    }while(auswahl != 0);
    
    system("PAUSE");
    return EXIT_SUCCESS;
}

Gruß
 
Zuletzt bearbeitet:
Okay!? Also ich weiß jetzt nicht wirklich wieseo, aber es funktioniert jetzt auch.. Ich gehe mal beide Dateien durch, und gucke was ich bei meiner Falsch gemacht habe :)

Vielen Dank sheel :)

Edit: Ich hab's. Ich habe ein scanf übersehen :D :D
 
Zuletzt bearbeitet:
@sheel: ich hab mir eben nochmal die funktion angeschaut. Ich verstehe das was unter else steht nicht. Müsste das nicht so lauten****
Code:
else {
  while((i=fgetc(stdin)) != '\n');
}

Falls ich jetzt etwas Falsches gesagt habe, korrigiere mich bitte :)
 
Zurück