scanf Prob in c

CaptainPsycho

Keine Panik!
Registriert
14. August 2002
Reaktionspunkte
22
Ort
L.E.
hallo ich hab dieses code

#include "stdio.h"

int main ()
{
int izahl;
char chtaste, o, a, h, O, A , H;

printf ("\nnatuerliche Zahl zwischen 1 und 255 eingeben\n"); /*Eingabe der zu konvertierenden Zahl*/
scanf("%d", &izahl);

if ((izahl >= 1) && (izahl <= 255)) /*Auswahl des Ausgabeformates*/
{
printf ("< O > eingeben für oktale ausgabe\n");
printf ("< A > eingeben für ascii ausgabe\n");
printf ("< H > eingeben für hex ausgabe\n");
chtaste = getchar();

switch (chtaste)
{
case 'o': printf ("ausgabe in oktal: "); break;
case 'O': printf ("ausgabe in oktal: "); break;
case 'a': printf ("ausgabe in ascii: "); break;
case 'A': printf ("ausgabe in ascii: "); break;
case 'h': printf ("ausgabe in hex: "); break;
case 'H': printf ("ausgabe in hex: "); break;
default: printf ("ungueltige Ausgabe gewaehlt \a\a\a\n");
}
}
else printf("ungueltige Zahl eingegeben\n");
return(0);
}

ohne das scanf("%d", &izahl);

geht es wunderbar nur wenn ich das mit reinschreibe überspringt er die charactereingabe. Warum?

Gruss Joachim der zu doof ist und jemand anders auch. :D
 
Ist allgemein eine schlechte Idee scanf und getchar abwechselnd bzw. aufeinanderfolgend zu benutzen. Das Problem ist meist das seltsame Fehlerhandling von scanf.

Der Effekt den Du siehst liegt IMO daran, dass scanf die Zeichen im Input Stream laesst, die nicht zu der angeforderten Konversion passen. Sprich, Du gibst "<Zahl><Enter>" ein, die Zahl wird wie gewuenscht in einen %d konvertiert, und das Enter bleibt im Input Stream, und wird nachfolgend von getchar gelesen.
 
gage_ schrieb:
Ist allgemein eine schlechte Idee scanf und getchar abwechselnd bzw. aufeinanderfolgend zu benutzen. Das Problem ist meist das seltsame Fehlerhandling von scanf.

Der Effekt den Du siehst liegt IMO daran, dass scanf die Zeichen im Input Stream laesst, die nicht zu der angeforderten Konversion passen. Sprich, Du gibst "<Zahl><Enter>" ein, die Zahl wird wie gewuenscht in einen %d konvertiert, und das Enter bleibt im Input Stream, und wird nachfolgend von getchar gelesen.

Besten Dank genau das wollt ich wissen. Hab bei meinen anderen Proggies nie scnaf und getchar zusammen verwendet. Deshalb kannte ich das Prob noch nicht. Aber jetzt bin ich schlauer.

Gruss Joachim
 
ups, hier war doch grad noch ein Beitrag von gage???

Egal, eine zugegebenermaßen etwas kaputte Lösung wäre vielleicht noch, als Format-String "%d%*1[\n]" zu verwenden -- liest nach der Zahl genau ein \n weg. Um mit fehlerhaften Eingaben umgehen zu können, vielleicht besser (wie von gage angedeutet) eine Zeile einlesen und die mit sscanf analysieren. Wenn das Einlesen unbedingt mit stdio-Mitteln sein muss, würd ich sowas wie

char line[256];
scanf("%255[^\n]%*1[\n]", line);

nehmen. Naja, genug gesenft...
 
carmin ... ich wollte dann doch keine Mittel promoten, die auf unsicheres String-Handling basieren .. wobei das bei so einer Anwendung wohl recht egal ist ;)
 
Naja hab's dann anders gelöst, zwar umständlicher aber was solls.
So konnt man wenigstens gleich nochmal alte Sachen wiederverwerten.

Gruss Joachim
MAKEFILE:

##########################################################################
#Aufgabe: Zahlenkonverter #
# #
#Modulbeschreibung: Makefile #
# #
##########################################################################

CC = gcc
CFLAGS = -Wall -O -ansi

Zahlenkonverter: Zahlenkonverter.c io.c io.h
$(CC) $(CFLAGS) Zahlenkonverter.c io.c -o Zahlenkonverter -g

ZAHLENKONVERTER.C:
/*****************************************************************************/
/*Programm zur Konvertierung von Zahlen in verschiedene Formate. */
/*****************************************************************************/

#include "io.h"
/*#include <stdio.h>*/ /*kann weggelassen werden, da stdio.h schon in io.h included wird*/

int main ()
{
int izahl, Menuewahl, endlos, endlos1; /*izahl ist die zu kopnvertierende Zahl*/
/*Menuewahl ist eine Hilfsvariable zur Menuewahl*/
char Eingabeaufforderung[256]; /*In das Feld kommt die Eingabeausforderung (max. 256 Zeichen) die der Inteingabe in der io.h uebergeben wird.*/

do /*Schleife die solange geht, bis eine korrekte Menuewahl erfolgte*/
{
/*Schreiben der Eingabeaufforderung in den String (Feld von Charaktern) der der Eingabefunktion uebergeben wird.*/
sprintf ( Eingabeaufforderung, "\nBitte geben sie eine natuerliche Zahl zwischen 1 und 255 ein.\n i = ");
izahl = inteingabe( Eingabeaufforderung);

if ((izahl >= 1) && (izahl <= 255)) /*Auswahl des Ausgabeformates*/
{
endlos1 = 0;

endlos = 1; /*Variable wird auf 1 gesetzt, damit die Schleife durchlaufen wird.*/
do /*Schleife die solange geht, bis eine korrekte Menuewahl erfolgte*/
{
/*Schreiben der Eingabeaufforderung in den String (Feld von Charaktern) der der Eingabefunktion uebergeben wird.*/
sprintf( Eingabeaufforderung, "\n< 1 > oktale Ausgabe\n< 2 > ascii Ausgabe\n< 3 > hex Ausgabe\n");
Menuewahl = inteingabe( Eingabeaufforderung);

switch (Menuewahl)
{
case 1: { printf ("ausgabe in oktal: "); endlos = 0; break; }
case 2: { printf ("ausgabe in ascii: "); endlos = 0; break; }
case 3: { printf ("ausgabe in hex: "); endlos = 0; break; }
default: printf ("ungueltige Ausgabe gewaehlt \a\a\a\n");
}
} while( endlos);


}
else { printf("ungueltige Zahl eingegeben\n"); endlos1 = 1; }
} while( endlos1);
return(0);
}

IO.H:
/************************************************************************/
/*Aufgabe: 1.5 Rangieren */
/* */
/*Modulbeschreibung: io.h Headerfile für io.c */
/* */
/************************************************************************/

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

/************************************************************************/
/* Eingabe einer natuerlichen Zahl und deren Rückgabe */
/* char *Eingabeaufforderung /Text der als Eingabeaufforderung angezeigt*/
/* werden soll. */
/* Rueckgabewert: eine Zahl im Format int */
/************************************************************************/

extern int inteingabe (char *);

IO.C:
/************************************************************************/
/*Aufgabe: 1.5 Rangieren */
/* */
/*Modulbeschreibung: Eingabe einer nat. Zahl */
/* */
/************************************************************************/

# include "io.h"

# define ERROR "\nBitte überprüfen sie ihre Eingabe und wiederholen sie diese.\n"

int inteingabe(char *Eingabeaufforderung)
{
char string[256];
int stringlaenge, i, j=1;

while(j) /*J bleibt solange auf bis der String entweder zu Ende ist oder*/
{ /*er enthält keine Integergrößen*/
printf( Eingabeaufforderung); /*Eingabeaufforderung wird ausgegeben*/
scanf("%255s", string);
stringlaenge = strlen(string); /*strlen Fkt aus stblib.h zur Berechnung von Stringlängen*/
for ( i=0; i < stringlaenge; i++) /*String wird überprüft, ob nur Zahlen enthalten sind*/
{
if(isdigit((int )string)) j = 0; /*isdigit überprüft den gegebenen String auf Integerwerte*/
else
{
printf("\n %s \n", ERROR); /*Bei falscher Eingabe Fehlermeldung und erneute Eingabe*/
j = 1;
break;
}
}
}
j = atoi(string); /*String wird zu int umgewandelt und in j gespeichert*/

return j; /*int Zahl wird als j zurückgegeben*/
}
 
sollte mit[ code] [ /code] kein problem sein... ;)
mal davon abgesehn, da blick ich net wirklich durch :confused:


Der Effekt den Du siehst liegt IMO daran, dass scanf die Zeichen im Input Stream laesst, die nicht zu der angeforderten Konversion passen. Sprich, Du gibst "<Zahl><Enter>" ein, die Zahl wird wie gewuenscht in einen %d konvertiert, und das Enter bleibt im Input Stream, und wird nachfolgend von getchar gelesen.
@ gage_
könntest du das prob nochmal versuchen für jemanden zu erklären, der erst am anfang seines programmierlebens steht... :)
 
derschotte ... die Funktionen getchar() und scanf() lesen beide Zeichen aus einem "Input Stream", also ein "Strom" von aufeinanderfolgenden Eingaben. Der Stream, von dem hier gelesen wird heisst auch "Standard Input"; wenn man das Programm manuell startet, sind das die Tastatureingaben.

getchar() liest das erste Zeichen aus diesem Stream, und entfernt es daraus. scanf() liest die Zeichen, die zu der angeforderten Formattierung passen (in der urspruenglichen Frage "%d", d.h. einen Integerwert) und laesst den Rest der Zeichen im Stream. Folgt nun ein getchar() auf einen scanf(), der nicht zuverlaessig alle Zeichen aus dem Stream entfernt hat, wird nicht eine neue Tastatureingabe gelesen, sondern Reste von der alten.
 
kann mir mal einer von euch superhirnen verraten, warum, egal welche zahl ich eingebe, immer 34603536 als dezimalzahl ausgegeben bekomme? das oben beschriebene prob mit getch und scanf löste sich nach einbinden der conio.h :)
hab jetzt die überprüfung gemacht mit do()while und jetzt bekomme ich immer diese megazahl, egal in welchem format ausgegeben.. :(

und es ist absicht, das ich es als php darstelle, schaut doch netter aus :)

PHP:
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
 
void main ()
{
 int izahl = 0;
 int ifehlerbit = 1;
 char chtaste;

 printf ("zahl eingeben zwischen 1 und 255\n");
  scanf("%d", &izahl);

 if ((izahl > 0) && (izahl <256))
 {
  do
  {
   printf ("< O > eingeben für oktale ausgabe\n");
   printf ("< A > eingeben für ascii ausgabe\n");
   printf ("< H > eingeben für hex ausgabe\n");
   printf ("< D > eingeben für dezimal ausgabe\n");
	chtaste = getch();
	
   switch (chtaste)
   {
	case 'o': 
	case 'O': printf ("ausgabe in oktal: %o \n"), izahl; ifehlerbit = 1; break;
	case 'a':
	case 'A': printf ("ausgabe in ascii: %c \n"), izahl; ifehlerbit = 1; break;
	case 'h':
	case 'H': printf ("ausgabe in hex: %x \n"), izahl; ifehlerbit = 1; break;
	case 'd':
	case 'D': printf ("ausgabe in dezimal: %d \n"), izahl; ifehlerbit = 1; break;
	default:  printf ("ungueltige Ausgabe gewaehlt \a\a\a\n"), ifehlerbit = 0;
   }
  }while (ifehlerbit != 1);
 }
 else printf ("ungültige Zahl eingegeben\n");
}
 
Deine printf's sind kaputt ...

Code:
printf ("ausgabe in dezimal: %d \n"), izahl;

muss lauten:

Code:
printf ("ausgabe in dezimal: %d \n", izahl);
 
... wenn Du (wie Joachim) für den gcc die Option -Wall benutzt, kommen _solche_ Fehler wenigstens nicht mehr vor:

schotte.c:31: warning: too few arguments for format
 
derschotte schrieb:
ähm... fang damit nulll an :D

Also wnn du deinen sch...... M$ Vikualdingens endlich wegwirfst und die einfach nen editor nimmst und den gcc (gnu c compiler) nimmst und den -Walll flag benutzt, dann bekommst solche warnungen ausgegeben.

Gruss Joachim
 
eclipsee_Victoria.gif



http://www.world-of-smilies.de/html/images/smilies/sonstige/eclipsee_Victoria.gif
 
Zurück