Doppelte Ausgabe

sanjo

Grünschnabel
Hallo Leute,

ich habe nach Jahren wieder mit dem Programmieren angefangen und gleich wieder ein Problem.

Als Einstieg, hab ich mir ein Programm genommen, welches Kreisumfang und -fläche aus dem Durchmesser bestimmt.

Zum Schluss soll das Programm fragen, ob eine neue Rechnung durchgeführt werden soll.
"j" für Ja und "n" für nein. Alles wunderbar, es klappt.

Wird jetzt etwas anderes als "j" oder "n" eingegeben, soll er nachfragen ("Wie bitte?") und eine erneute Eingabe auffordern.

Er fragt dann aber zweimal, also:

Wie bitte?

Wie bitte?

Hier mal der Quelltext, hoffentlich sieht jemand den Fehler. Habe anstatt goto auch scho do-while verwendet und das ganze umstruckturiert, aber ich denke es liegt an der if-else verschachtelung.

Danke für eure Hilfe....

PHP:
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <iostream>

int main (void) 
{
  
  char weiter;
  float d;
  float r;
  float u;
  float a;
  
  anfang:
          
  printf("Durchmesser d in m angeben!\n\n\n");
  scanf("%g",&d);
  
  r=d/2;
  u=2*r*M_PI;
  a=pow(r,2)*M_PI;
  
  printf("Umfang u=%g m\n\a",u);
  printf("Flaeche a=%g m2\n\a",a);
  scanf("%c",&weiter);
  printf("Noch eine Zahl eingeben?\n\n\n");
 
  wiederholen:
 
  scanf("%c",&weiter);
 
  if(weiter=='j')
                 {
                 goto anfang;
                 }
  if (weiter=='n')
                 {
                 exit(0);
                 }
  else
                 {
                 printf("\nWie bitte?\n");
                 goto wiederholen;     
                 }
      
  
   return 0;
  }
 
Das liegt vermutlich daran, dass nach dem Rücksprung bei einer falschen Eingabe immer noch das Zeilenumbruchzeichen \n im Eingabepuffer steckt, welches dann sofort ohne weitere Eingabe von scanf eingelesen und verarbeitet wird. Lösen kann man dieses Problem beispielsweise dadurch, dass man vor dem Aufruf von scanf den Eingabepuffer mit fflush(stdin); leert. Alternativ könnte man auch getch verwenden (siehe unten).

Zu deinem Programmierstil sind zwei Sachen anzumerken:
  • Buchstabenvariablen sollten eigentlich nur in Ausnahmefällen (z.B. als Zählvariable) verwendet werden. Wenn dann sollte ihre Funktion dokumentiert sein (mittels Kommentaren bei der Deklaration)
  • goto ist in fast allen Programmiersprachen verpönt, da es dazu führt, unstrukturiert zu programmieren. Jedes Programm kann und sollte ohne goto geschrieben werden.

Mein Verbesserungsvorschlag:
C:
#include <stdio.h>
#include <conio.h>
#include <math.h>

int main (void) 
{
	char cWeiter;
	float fDurchmesser;
	float fRadius;
	float fUmfang;
	float fFlaeche;
	char bGueltigeEingabe;
	
	do {
		printf("Durchmesser d in m angeben!\n\n\n");
		scanf("%g", &fDurchmesser);
	
		fRadius = fDurchmesser / 2;
		fUmfang = 2 * fRadius * M_PI;
		fFlaeche = fRadius * fRadius * M_PI;
		
		printf("Umfang u=%g m\n\a", fUmfang);
		printf("Flaeche a=%g m2\n\a", fFlaeche);
		getch();
		printf("Noch eine Zahl eingeben (j/n)? ");
		
		do {
			cWeiter = getch();
			bGueltigeEingabe = (cWeiter == 'j' || cWeiter == 'n');
			if (!bGueltigeEingabe) {
				printf("\nWie bitte? ");
			}
		} while (!bGueltigeEingabe);
		
		printf("\n");
		
	} while (cWeiter == 'j');
	
	return 0;
}
 
Vielen Dank für deine schnelle Antwort, hat mir sehr geholfen. Habe auch schon gehört/gelesen, dass goto sehr verpönt ist. Ist halt als Sprungersatz nehmen?
 
Eigentlich dämlich, dass Sprünge so verpönt sind: Auf Assemblerebene (wohin ein Programm nunmal übersetzt wird) gibt es nur Schleifen mit 1 Anweisung. Sonst alles Sprünge. Weil, if gibts nicht, gibt nur cmp und test (Zahlenvergleich und "ist Bit gesetzt?"). Eine Zählschleife mit mehr als einer Anweisung oder eine andere Schleife gibbet nur mit Rücksprung:
Code:
mov cx,20
loop1:
  ; code bla bla
  dec cx ; cx dekrementieren
  jnz loop1 ; wenn cx <> 0 machs noch einmal, Joe
Warum sind Sprünge verpönt? Weil manche Sachen nicht geklärt sind. Z.B. Sprung in eine Schleife rein. Ist doch glasklar. Z.B. Zählschleife: Wenn in cx äh.. was interressantes steht, kommt das Programm halt nicht vom Fleck, ist dann aber die Schuld des Programmieres. Außerdem ist für den Prozessor -127 - 1 = 0. Ist wie Programm wird nicht beendet. Oder String zur Ausgabe endet nicht auf $. Dann siehst du den gesamten Inhalt des RAMs... nicht dass ich den sehen wollte.So simpel, und die ganze Programmiererschaft der Welt krigst nicht auf die Reihe, mal sowas zu klären. Wie gesagt, in Assembler biste nur am Springen, da kann man das auch in Hochsprachen machen.
Tschö,
nullplan
 
Zurück