Probleme mit: scanf("%s" &var); gets(var);



  • Hallo,

    manchen von euch mag unten beschriebenes Problem trivial vorkommen, ich bitte euch dennoch mir zu helfen.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Mitarbeiter
    	{
    	char Vorname[30];
    	char Nachname[30];
    	char Geschlecht;
    	unsigned int p_no;
    	struct Mitarbeiter *next;
    	}; 
    
    struct Mitarbeiter *insert(struct Mitarbeiter *list, unsigned int *p_numb, char *gesch, char vorn[], char nach[])
    
    {
    	struct Mitarbeiter *new_node = (struct Mitarbeiter*)malloc(sizeof(struct Mitarbeiter));
    
    	if (new_node == NULL)
    		{
    		printf("\nFEHLER! Nicht genuegend Speicher frei!");
    		return list;
    		}
    
    	new_node->p_no = *p_numb;
    	new_node->Geschlecht = *gesch;
    	strcpy(new_node->Vorname, vorn);
    	strcpy(new_node->Nachname, nach);
    
    	new_node->next = list;
    	list = new_node;
    
    	return list;
    
    }
    
    int main ()
    
    {
    	int i, anzahl;
    
    	struct Mitarbeiter *list = NULL;
    
    	unsigned int p_numb;
    	char gesch;
    	char vorn[30];
    	char nach[30];
    
    	printf("\nAnzahl der einzugebenden Mitarbeiter: ");
    	scanf("%d", &anzahl);
    
    	for(i = 0; i < anzahl; i++)
    	{
    		printf("\n%d. Mitarbeiter", i+1);
    		printf("\nVorname: ");
    		//scanf("%s", &vorn);
    		gets(vorn);
    		printf("Nachname: ");
    		//scanf("%s", &nach);
    		gets(nach);
    		printf("Geschlecht: ");
    		scanf("%c", &gesch);
    		printf("Personalnr.: ");
    		scanf("%d", &p_numb);
    		list = insert(list, &p_numb, &gesch, vorn, nach);
    		printf("-------------------------");
    	}
    
    	return 0;
    }
    

    Das Programm soll einfach nur Listen erstellen mit der jeweiligen struct.
    Allerdings wird beim Ausführen und beim Angelangen bei der Eingabe, immer der "Vorname" übersprungen und so betrachtet, als wäre er gar nicht da...

    Hatte die Eingabe der Elemente auch in eine extra Funktion verpackt bzw. in der Funktion "insert" selbst.. gleiches Problem nur unterschiedliche Sprünge.

    Vielen Dank schon mal!



  • Mit den Listen kenn ich mich noch nicht wirklich auf, das hab ich noch vor mir (Ja, da werden noch ein paar Fragen auftauchen).

    Aber ich würde generell mal fgets zum String einlesen verwenden.
    Das Vorname übersprungen wird... Steht da dann gar nicht´s drin? Oder Käse?
    Würde vermuten es ist nach der Eingabe von

    printf("\nAnzahl der einzugebenden Mitarbeiter: ");
        scanf("%d", &anzahl);
    

    noch was im Tastaturpuffer, bzw. im Stream.
    😕



  • Sorry, nach der eingabe von

    printf("Personalnr.: ");
            scanf("%d", &p_numb);
    

    Meinte ich??



  • Danke für die schnelle Antwort

    hab jetzt fflush(stdin); mit eingebaut:

    for(i = 0; i < anzahl; i++)
    	{
    		fflush(stdin);
    
    		printf("\n%d. Mitarbeiter", i+1);
    		printf("\nVorname: ");
    		//scanf("%s", &vorn);
    		gets(vorn);
    
    		printf("Nachname: ");
    		//scanf("%s", &nach);
    		gets(nach);
    
    		printf("Geschlecht: ");
    		scanf("%c", &gesch);
    
    		printf("Personalnr.: ");
    		scanf("%d", &p_numb);
    
    		list = insert(list, &p_numb, &gesch, vorn, nach);
    		printf("-------------------------");
    	}
    

    funktioniert jetzt einwandfrei... wobei mir der Hintergrund noch nicht wirklich klar ist.

    fgets() wird doch nur für Streams verwendet, oder lieg ich da falsch?


  • Mod

    Die Lösung ist denkbar schlecht. fflush(stdin) ist nicht portabel (weißt du überhaupt, was das macht?). gets is dangerous and should not be used. Außerdem ist es in C11 sogar aus dem Standard geflogen!

    Benutz lieber etwas wie

    scanf(" %157[^\n]", employee->first_name); // 157 = länge deines char-Arrays - 1
    

    Das beseitigt sowohl dein Problem, ist zugleich aber portabel und sicher.



  • Kein gets() verwenden! Schreibt über alles Puffer hinweg bei böswilligen/fehlerhaften Eingaben.
    Compilerwarnungen einschalten! Z.B. ist %d der conversion specifier für (signed) int und nicht für unsigned .

    Wenn Du auf gets() verzichtest werden auch führende Leerzeichen ignoriert. Ausser bei %c - s.u.

    for(i = 0; i < anzahl; i++)
        {
          printf("\n%d. Mitarbeiter", i+1);
    
          printf("\nVorname: ");
          scanf("%29s", vorn);  // beachte die width (30-1=29 wg. "terminating null byte")
    
          printf("Nachname: ");
          scanf("%29s", nach);  // kein & vor der Variable sonst habe ich ja einen char**
    
          printf("Geschlecht: ");
          scanf(" %c", &gesch); // beachte das Leerzeichen: führende Whitespaces werden ignoriert
    
          printf("Personalnr.: ");
          scanf("%u", &p_numb);  // u wg. unsigned
    
          list = insert(list, &p_numb, &gesch, vorn, nach);
          printf("-------------------------");
        }
    

    Und zuguterletzt: was soll denn das Schlüsselwort typedef hier?

    typedef struct Mitarbeiter{
      ...
    };
    

    SeppJ hat einen Teil meiner Antwort vorweggenommen und sogar noch besser gelöst. Ich lass das jetzt trotzdem mal so stehen...



  • Bei Arrays kommt kein Adressoperator vor den Namen

    Und ich denke, dass die Funktion insert nicht die Adressen von p_numb und gesch braucht.



  • Danke für die Antworten!

    Hab die Methode nun so umgesetzt wie vorgeschlagen.
    Der Code funktioniert.

    Zu dem fflush(stdin); :
    Leider hab ich nicht viel Ahnung davon. Ich dachte, dass mir die Funktion den Puffer löscht, der bei mehreren scanf() Funktionen entstehen kann.
    Sozusagen "bereinigt"?

    Zu dem typdef:

    typedef struct Mitarbeiter
    	{
    	char Vorname[30];
    	char Nachname[30];
    	char Geschlecht;
    	unsigned int p_no;
    	struct Mitarbeiter *next;
    	};
    

    macht natürlich nicht viel Sinn.. liegt aber daran, dass die Thematik noch neu für mich ist und entsprechend verwirrend.


Anmelden zum Antworten