fgets() und return 0



  • Hallo,

    Da mir gesagt wurde scanf() und gets() seien zu vermeiden und stattdessen lieber fgets() zu benutzen, versuchte ich diesen Vorschlag gleich in die Tat umzusetzen indem ich einige Beispielprogramme aus meinem Lehrbuch dahingehend umschrieb.

    Das Original war:

    #include <stdio.h>
    #include <ctype.h>
    main()
    {
    	char eingabe ;
    	int zahl ;
    	printf ("\n Waehlen sie: (O)ktal, (H)ex oder (A)SCII > ") ;
    	eingabe=getchar();
    	printf ("\n Bitte Dezimalzahl eingeben: ") ;
    	scanf ("%i",&zahl) ;
    	switch (tolower(eingabe))
    	{
    		case 'o':
    			printf ("Dezimal %i = Oktal %o \n",zahl,zahl) ;
    		break;
    		case 'h':
    			printf ("Dezimal %i = hexadezimal %x \n",zahl,zahl) ;
    		break ;
    		case 'a':
    			if (zahl <=255)
    			printf ("ASCII-Code %i entspricht %c \n",zahl,zahl) ;
    			else
    				printf ("Diese Zahl ist zu groß!\n\a") ;
    			break;
    		}
    
    	}
    

    Meine Version:

    [...]
    char eingabe[8] ;
    	int zahl ;
    	printf ("\n Waehlen sie: (O)ktal, (H)ex oder (A)SCII > ") ;
    	fgets (eingabe, sizeof eingabe, stdin);
    	printf ("\n Bitte Dezimalzahl eingeben: ") ;
    	scanf ("%i",&zahl) ;
    	switch (tolower(eingabe))
    	{
    [...]
    

    Der compiler meldet nun folgenden Fehler:

    Warnung: Übergabe des Arguments 1 von »tolower« erzeugt Ganzzahl von Zeiger ohne Typkonvertierung

    Meine erste Frage lautet nun, wo mein Denkfehler liegt und wie fgets() korrekt zu verwenden ist.

    Meine zweite Frage:
    Sehe ich mir Programme von Usern aus diesem oder anderen Foren an treffe ich häufig auf die Anweisung return 0;

    Warum sollte dies benutzt werden?



  • fgets (eingabe, sizeof eingabe, stdin);
    

    Der erste Parameter zu man: fgets muß ein Zeiger auf char (sprich: ein String) sein. Bei dir ist es aber eine ganze Zahl.

    Meine erste Frage lautet nun, wo mein Denkfehler liegt und wie fgets() korrekt zu verwenden ist.

    Du gibst ihm einen String als erstes Argument. Da schreibt es dir die ganze Zeile vom Terminal hinein (genau wie bei man: gets -- nur mit Grenzen).

    Sehe ich mir Programme von Usern aus diesem oder anderen Foren an treffe ich häufig auf die Anweisung return 0;

    Am Ende von main()? Zumindest ein Standard verlangt das (in dem Sinn sollte main() auch explizit int sein). Also machen wir das meistens.
    Shiehe auch:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-39346.html
    http://de.wikipedia.org/wiki/Varianten_der_Programmiersprache_C#Beispiele_f.C3.BCr_den_Unterschied_zwischen_verschiedenen_Fassungen_der_Sprache_C



  • Der erste Parameter zu fgets muß ein Zeiger auf char (sprich: ein String) sein. Bei dir ist es aber eine ganze Zahl.

    Das war Blödsinn. Zur Entschuldigung: bin verkatert.

    Es dreht sich natürlich um man: tolower. Daran muß man ein Zeichen übergeben, du übergibst aber einen Zeiger auf ein Zeichen (sprich: einen String).

    Also: Zeile 2.8 ändern auf:

    switch (tolower(eingabe[0]))
    // oder
    switch (tolower(*eingabe))
    


  • ^^mit scanf einen 'int' reinzuholen, ist doch harmlos, oder nicht?
    nur bei strings bzw. arrays kann'n 'nen bufferüberlauf geben.
    🙂



  • ^^mit scanf einen 'int' reinzuholen, ist doch harmlos, oder nicht?

    Natürlich, das sehe ich genauso (einen String könnte man mit %32s begrenzen, oder?). Ich sage aber immer wieder, daß mir die Format-Syntax von scanf() eher suspekt ist. Vielleicht ist sie aber auch elegant und ich hab's nur nie ganz durchschaut.

    scanf() sieht auf den ersten Blick aus wie das Gegenteil zu printf(), ist aber auf den zweiten Blick durchaus komplizierter. Siehe zB was ich hier am Ende gesagt habe:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-249219-and-postdays-is-0-and-postorder-is-asc-and-start-is-10.html



  • Da mir gesagt wurde scanf() und gets() seien zu vermeiden und stattdessen lieber fgets() zu benutzen

    Ich frag mal frei von der Seele: wer sagt das eigentlich, und was war die Begründung? (Was nicht heißen soll, daß da nichts wahres dran ist.)



  • Die Begründung ist doch offensichtlich, weil 'scanf("%s", buffer)' und 'gets(buffer)' immer einen buffer-overflow produzieren können, während 'fgets(buffer, max, f)' höchstens max Zeichen einliest.

    Alternativ kann man auch

    char buffer[32];
    scanf("%32s", buffer);
    
    // bzw. noch besser
    scanf("%*s", max, buffer);
    

    verwenden.

    Jedoch liest scanf("%s") nur bis zum nächsten Whitespace, deshalb s.a.
    http://www.c-plusplus.net/forum/viewtopic-var-p-is-1773265.html#1773265


Anmelden zum Antworten