[C] Unerwünschter Nebeneffekt bei Ausgabe

Atomique

Ensign
Registriert
März 2010
Beiträge
135
Guten Abend CB :)
ich hoffe ihr könnt mir weiterhelfen mit meinem Problem :) und ich hoffe, dass ich mein Problem in die richtige Kategorie gepostet hab ;)

Nun zu meinem Problem:

Ich habe heute Abend begonnen ein C-Programm zu schreiben um etwas zu üben. Wollte ein Programm schreiben in dem Alles irgendwie vorkommt. Das Programm hat ein Menü in welchem ausgewählt werden kann welche Funktion man benutzen möchte (Die Funktionen sind noch nicht geschrieben, habe den Aufruf erstmal mit Printf ausgefüllt ^^). Wenn man 0 eingibt soll in diesem Menü auf erneute Bestätigung das Programm beendet werden. Nun das Problem: Wenn ich 'n' eingebe kommt zwar das Programm wie ich es vor hatte, jedoch kommt "Falscheingabe" aus der int main dazu :o
Ich dachte erst das liegt an dem \n, habe deswegen mal überall vor Verzweiflung ein fflush(stdin) eingebaut wie ihr sehen könnt. Ich hoffe ihr könnt mir helfen!

Ersteinmal der Code:
Code:
#include <stdio.h>

#define Version 1.00

int main();
int menue_01();
int programmende();

int main()
{	
	int me_in=0;

	do
	{
		menue_01();		
		scanf("%i",&me_in);
		fflush(stdin);
		switch(me_in)
		{
		case 1:	printf("1\n");
			break;
		case 2:	printf("2\n");
			break;
		case 3:	printf("3\n");
			break;
		case 9:	printf("9\n");
			break;
		case 0: programmende();
		default: printf("Falscheingabe\n\n"); 
		}
		
	}
	while(me_in=!0);


	return 0;
}


int menue_01()
{
	printf("Willkommen in MathematiX Version %.2lf, was wollen Sie tun?\n", Version);
	printf("<1> Rechnen (Normaler Taschenrechner)\n");
	printf("<2> Flaechenberechnung einer geom. Figur\n");
	printf("<3> Volumenbrechnung eines Objektes\n");
	printf("<9> About MathematiX Version %.2lf.\n", Version);
	printf("<0> Programm beenden. \n[Randnotiz: Es folgen weitere Funktionen ;) ]\n");
	


	return 0;
}

int programmende()
{
	char input;
	printf("Programm wird beendet. Fortfahren mit < J >, Abbrechen mit < N >.\n");
	do
	{
	input=getchar();
	}
	while(getchar()!='\n');
	fflush(stdin);
	if(input == 'j','n')
	{
		if(input=='j')
		{
			printf("Programm beendet. Vielen Dank f\x81r das benutzen von MathematiX Version %.2lf\n", Version);
			exit(0);
		}
		else
		{
			printf("Programm wird fortgesetzt.\n\n");
			return 0;
		}

	}
	else
	{
		printf("Falscheingabe, Bitte wiederholen:\n");
		programmende();
	}
	return 0;
}

fehler.JPG


Vielen Dank für eure Hilfe im vorraus schon einmal :) Wenn ihr irgendwelche Vorschläge habt meinen Programmierstil zu verbessern, nur raus damit, ich möchte versuchen so sauber wie möglich zu programmieren! :)

Gruß Atomique
 
case 0: programmende();
break;
default: printf("Falscheingabe\n\n");


???
 
Ich finde zudem "Fehler 2 error C3861: "exit": Bezeichner wurde nicht gefunden." in Zeile 69, die Funktion fehlt wohl noch

da fehlt doch nur nen include
#include <stdlib.h>

nun zum Fehler:
1. das break
noch was anderes
2.scanf("%i",&me_in);
%i gibts doch garnicht oder, %d für ne dezimal zahl

Wenn ihr irgendwelche Vorschläge habt meinen Programmierstil zu verbessern, nur raus damit
gewöhn dir an zu kommentieren ;) Bei so nem kleinen Progrämmchen gehts ja noch, haste aber mal 50 ineinanderverschatelte if / elses wirds langsam unübersichtlich ;)

z.B.:

//Falscheingabe abfangen...
else
{
printf("Falscheingabe, Bitte wiederholen:\n");
programmende();
}


und
lass das:
fflush(stdin);
macht keinen Sinn (nie), fflush ist für output streams...

gruß
 
Zuletzt bearbeitet:
xD Danke Danke Danke :D Ich mach wohl lieber Morgen weiter :D Wenn ich nur sehe "hm sieht komisch aus aber ich lass es mal" und net mal blick, dass da nen break; fehlt :D
- DrToxic kannst du mir das mit dem exit erklären? Habe diesen Fehler gar nicht bei mir untem im Log stehen (Visual Studio 2005)

Gruß Atomique
Ergänzung ()

Okay, ja :) Du hast Recht :) Manchmal vergess' ich es einfach komplett ^^ Bei meinem letzten habe ich es gemacht..
Ansonsten nichts zu beanstanden? Ich habe vorhin gelesen, dass man statt scanf(); lieber fgets(); nehmen soll und diese Eingabe dann mit sscanf konvertieren. Was denkst du / ihr ? Und VS05 hat mir vorhin auch eine Warnung ausgegeben ich solle lieber "s_scanf" benutzen statt scanf, wegen der Sicherheit.. -> Funktioniert das dann auch mit anderen Compilern? Oder sollte ich lieber bei Scanf bleiben?

Gruß Atomique
 
soyd schrieb:
da fehlt doch nur nen include
#include <stdlib.h>

Sorry, ich wusste nicht, dass es für exit Bibliotheklen gibt. Hab ich persönlich nie genutzt, ich dachte, das wäre eine vom TE selbst ausgedachte Funktion :)

Ich muss allerdings sagen, dass ich an manchen Stellen fflush brauchte, um später keine doppelten Ausgaben zu bekommen.

Sowohl ich als auch meine Professorin sind nicht 100%ig dahinter gestiegen, wieso manchmal dann Sachen zweimal ausgegeben wurden, wenn man in der Abfrage vorher eine ungültige Eingabe hatte.

z.B. bei Abfrage einer Zahl "2a" oder "2 " eingegeben, hat bei der nächsten Abfrage dazu geführt, dass dass printf zweimal ausgeführt wurde.

Die Vermutung war, dass das "a" oder " " noch in dem inputstream hing und deswegen das erste mal der nächsten Abfrage nicht akzeptiert wurde.

Das erklärt jedoch trotzdem nicht, wieso dann nochmal abgefragt wird, eigentlich hätte das Programm dann da weiter machen müssen.

Nur mal so, als kleine Anekdote zum fflush :)
 
noch zum fflush:

7.19.5.2 The fflush function
Synopsis

#include <stdio.h>
int fflush(FILE *stream);
Description

If stream points to an output stream or an update stream in which the most recent
operation was not input, the fflush function causes any unwritten data for that stream
to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.

If stream is a null pointer, the fflush function performs this flushing action on all
streams for which the behavior is defined above.
Returns

The fflush function sets the error indicator for the stream and returns EOF if a write
error occurs, otherwise it returns zero.

vielleicht was mit dem type modifier? %...

scanf: formattierte Eingabe
fgets: unformattierte Eingabe
Ich habe vorhin gelesen, dass man statt scanf(); lieber fgets(); nehmen soll und diese Eingabe dann mit sscanf konvertieren
kommt drauf an was du machen willst...
liest du bei scanf mit %d ein wird nen 123\n zu 123
fgets -> 123\n

ob fgets/scanf ist schnuppe würd ich sagen...
scanf_s secure Function, meistens nicht nötig, schützt vor Buffer Overflows... scanf schützt den Buffer nicht, wird der zu groß .... die bösen Hacker/Cracker ;)


gruß
 
Zuletzt bearbeitet:
Wende ich das fflush(stdin) dann nach jedem scanf an? Und habt ihr meine Ergänzung gesehen? :>
 
Also, ich hatte damit die o.g. Probleme behoben - aber wenn du kein Problem hast, lass es mit dem fflush :)

Zu fscanf() kann ich leider nichts sagen. Ich hatte nur ein Semester Grundlagen in C, da war Sicherheit bei der Eingabe nicht so das Thema ;)

Achja, und willkommen im Forum :)
 
Ich hoffe es wurde noch nicht angesprochen, hab die anderen Beiträge nur überflogen:

Dein Problem scheint zwar gelöst, aber warum sind denn deine Funktionen nicht vom Typ void? Du brauchst ja gar keinen return-Wert, also kannste ihn auch gleich weglassen...
 
Dankeschön :) Also fürs helfen und fürs Willkommen heißen :) Echt Topp wie hier einem geholfen wird :) Und vorallem die Geschwindigkeit :D

Eine Frage habe ich noch, wenn ich darf:

Ihr habt ja den Quellcode gelesen. Und ihr kennt das ja wenn man Sonderzeichen eingeben will, wie zum Beispiel Ä Ö Ü und so weiter. Wie gewohnt habe ich dann bei:

Code:
int menue_01()
{
	printf("Willkommen in MathematiX Version %.2lf, was wollen Sie tun?\n", Version);
	printf("<1> Rechnen (Normaler Taschenrechner)\n");
	printf("<2> Flaechenberechnung einer geom. Figur\n");
	printf("<3> Volumenbrechnung eines Objektes\n");
	printf("<9> About MathematiX Version %.2lf.\n", Version);
	printf("<0> Programm beenden. \n[Randnotiz: Es folgen weitere Funktionen ;) ]\n");
	


	return 0;
}

"Flaechenberechnung" \x84 eingegeben, statt dem ae und es kam eine Fehlermeldung, die das Programm nichteinmal starten lies:


1>c:\users\atomique\documents\visual studio 2005\projects\mathematix\mathematix\main.c(47) : error C2022: '2124' : too big for character

Bei
printf("Programm beendet. Vielen Dank f\x81r das benutzen von MathematiX Version %.2lf\n", Version);
klappte aber alles hervorragend oO


Und die Warnung zum scanf (um nochmal drauf zu zu kommen weil es wieder auftauchte)

1>c:\users\atomique\documents\visual studio 2005\projects\mathematix\mathematix\main.c(17) : warning C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.


Gruß Atomique
Ergänzung ()

Ich dachte, void ist veraltet und man nimmt immer int + return 0 stattdessen?

Ich habe es auch nur so gelernt. Hm
 
Achso, nur so als Anmerkung: fscanf steht ja für FILEscanf, wäre also hier der falsche Befehl, da es aus einer Quelldatei liest.

Mit gets() solltest du keine Probleme haben, aber bestehen in deinem Progg die Benutzereingaben nicht aus einem Buchstaben / einer Zahl? Da wäre ein String ja überflüssig.
Ergänzung ()

DrToxic schrieb:
Ich dachte, void ist veraltet und man nimmt immer int + return 0 stattdessen?

Ich lerne C im Moment im zweiten Semester und bei uns ist das Gang und Gebe, kann das also nicht bestätigen.

Edit: In der mainfunktion habe ich aber einen Rückgabewert, da mir GCC (Compiler) sonst ne Warnmeldung ausspuckt (funzt aber auch mit void!).
 
Zuletzt bearbeitet:
Also mache ich jetzt überall das int weg, schreibe das void dazu und bastel das int / den Datentyp nur davor wenn ich nen Rückgabewert benutze? Mache ich das dann auch bei der int main()?
 
Die Main-Funktion gehört auch als int { return 0; } angegeben.
Bei den restlichen Funktionen ist das egal - die kannst du auch als void nutzen.

Bei der MAIN-Funktion ist es für das ausführende Betriebssystem ganz nützlich, einen return-Wert zu bekommen (ob das Programm korrekt ausgeführt wurde oder ob ein Fehler aufgetreten ist).

Für die Eingabefunktion hätte ich eine andere Idee - die dürfte dir (zumindest bei deinem Beispiel) einiges an Arbeit abnehmen:
Code:
int me_in=0;

do
{
        System("cls");
	menue_01();		
	scanf("%i", &me_in);
	fflush(stdin);
}
while(me_in != 9 && (me_in > 3 && me_in < 0));

switch(me_in)
{
case 1:	printf("1\n");
	break;
case 2:	printf("2\n");
	break;
case 3:	printf("3\n");
	break;
case 9:	printf("9\n");
	break;
default:    programmende(); 
}

Ich nehme mal an, dass in die Case-Blöcke noch alternative Funktionsaufrufe kommen - ansonsten kann man die auch wegrationalisieren und direkt in der while-Schleife ausgeben.
Dadurch, dass du direkt bei der Eingabe prüfst
 
also in C ist void f(...) nicht "veraltet"
wenn dann gehts doch um sowas wie
int f(void)
bei C wäre das eine int Funktion ohne Übergabeparameter
int f()
ist eine int Funktion mit beliebig vielen Parametern

in C++ siehts anders aus:
int f(void) veraltet
int f() neu, da hier Funktion ohne Parameter...

=)

@Tapion3388
fscanf würde auch gehen, als eingabe stdin ;) ist auch nur nen filestream


"Flaechenberechnung" \x84 eingegeben,
was soll das sein? x84? hexa 84
scanf immer noch mit %i ??? probiers mit %c ;)

hast du was am Quelltext verändert ? falls ja stell ihn doch nochmal rein.

und mich würd echt interessieren warum scanf(%i,...)
%i ist doch kein type specifier... %... würd ich mir ja noch gefallen lassen ;)

@voodoo44

da wärs aber nach der 1.ten Eingabe vorbei das Programm..

gruß
 
Zuletzt bearbeitet:
Zuletzt bearbeitet:
In der mainfunktion habe ich aber einen Rückgabewert, da mir GCC (Compiler) sonst ne Warnmeldung ausspuckt (funzt aber auch mit void!).

er hat doch einen drin... gutes gcc ;)

funzt aber auch mit void
böses gcc

Ist fürs System wichtig, ob das Proggy nun fertig ist oder nicht... sonst kannste "Leichen" im Speicher haben

Also mache ich jetzt überall das int weg, schreibe das void dazu und bastel das int / den Datentyp nur davor wenn ich nen Rückgabewert benutze? Mache ich das dann auch bei der int main()?

wo du keine Rückgabeparameter brauchst mach void, zum Fehler abfangen ist nen Rückgabewert oft nicht blöd (C), durch unnötige Rückgabewerte wird dein Progrämmchen größer, macht vielleicht bei nem PC nichts aus, bei nem µC mit "wenig" Speicher reißens die paar Byte manchmal raus ;)

main ist immer vom typ int mit Rückgabe

gruß
 
Zuletzt bearbeitet:
asdfman schrieb:

Ja klar, vor nem Buffer Overflow wärste hier nicht geschützt, da hast du natürlich recht. :freaky:

Zu den Links: Aus diesem Grund hat die main (bei mir) ja nen Rückgabewert, im ersten Semester haben wir aber bis zu einer bestimmten Stelle noch mit void main() gearbeitet, da wir von Funktionen ja nocht nichts wussten.
Ergänzung ()

soyd schrieb:
@Tapion3388
fscanf würde auch gehen, als eingabe stdin ;) ist auch nur nen filestream

Hehe stimmt, aber warum einfach wenns auch kompliziert geht ;)
 

Ähnliche Themen

Zurück
Oben