PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Orda will Programmieren lernen - schon erste Probleme mit C (Mehrfachauswahl im Menü)


orda
2005-10-18, 11:29:33
Moin!

Da ich mich jetzt endlich mal durchgerungen habe, ein bisschen C zu leren, habe ich mir vorgenommen einen ganz einfachen Taschenrechner zu programmieren (+;-;*;/).

Doch leider scheitere ich schon an der ersten Hürde, das Auswahlmenü. Eine einfache if Abfrage bekomme ich ja noch hin, aber nicht mit mehreren möglichen Antwortmöglichkeiten. Hoffe ihr versteht was ich meine.

CODE:

#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <stdlib.h>
void main(void) // Beginn der Hautfunktion
{
int i,t;
//Variablen
//===================================================================

float x,y,z;

//US
printf("::::::Rechner von D.Goebel 2005::::::==");
gotoxy(30,12);
cprintf("LADE HAUPTMENUE",1);
sleep(2);
clrscr();

///////////////////MENUE///////////////////////

gotoxy(1,2);
cprintf("HAUPTMENUE",1);
gotoxy(10,4);
cprintf("1. Addition,",1);
gotoxy(10,5);
cprintf("2. Subtraktion,",1);
gotoxy(10,6);
cprintf("3. Multiplikation",1);
gotoxy(10,7);
cprintf("4. Division",1);
gotoxy(10,8);
cprintf("5. Beenden",1);

gotoxy(10,10);
printf("\nWas moechten sie tun? (1-5): ");

///////////////////MENUE///////////////////////

t=getch();

//====================1. ADDITION===========================
//==========================================================

if(t==49)
{
printf("1");
}
//====================2. SUBTRAKTION===========================
//=============================================================

if(t==50)
{
printf("2");
}
//====================3. MULTIPLIKATION===========================
//================================================================
if(t==51)
{
printf("3");
}
//====================4. DIVISION=================================
//================================================================
if(t==52)
{
printf("4");
}
//====================5. EXIT=====================================
//================================================================
if(t==53)
{
printf("5");
}
//===================EINGABE?=====================================
//================================================================
else
{
printf("Konnte Eingabe nicht erkennen, nur Zahlen von 1-5");
}

sleep(33);
}


In die if "Klammern" sollen dann natürlich später mal die richtigen Rechenoperationen rein, momentan soll er nur eine einfache Textausgabe machen, damit man sieht ob das Menü funktioniert.
Was mache ich nur falsch? Muss ich die weiteren if Abfragen in die else "Klammer" schreiben?

Senior Sanchez
2005-10-18, 11:38:15
Moin!

Da ich mich jetzt endlich mal durchgerungen habe, ein bisschen C zu leren, habe ich mir vorgenommen einen ganz einfachen Taschenrechner zu programmieren (+;-;*;/).

Doch leider scheitere ich schon an der ersten Hürde, das Auswahlmenü. Eine einfache if Abfrage bekomme ich ja noch hin, aber nicht mit mehreren möglichen Antwortmöglichkeiten. Hoffe ihr versteht was ich meine.

CODE:

#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <stdlib.h>
void main(void) // Beginn der Hautfunktion
{
int i,t;
//Variablen
//===================================================================

float x,y,z;

//US
printf("::::::Rechner von D.Goebel 2005::::::==");
gotoxy(30,12);
cprintf("LADE HAUPTMENUE",1);
sleep(2);
clrscr();

///////////////////MENUE///////////////////////

gotoxy(1,2);
cprintf("HAUPTMENUE",1);
gotoxy(10,4);
cprintf("1. Addition,",1);
gotoxy(10,5);
cprintf("2. Subtraktion,",1);
gotoxy(10,6);
cprintf("3. Multiplikation",1);
gotoxy(10,7);
cprintf("4. Division",1);
gotoxy(10,8);
cprintf("5. Beenden",1);

gotoxy(10,10);
printf("\nWas moechten sie tun? (1-5): ");

///////////////////MENUE///////////////////////

t=getch();

//====================1. ADDITION===========================
//==========================================================

if(t==49)
{
printf("1");
}
//====================2. SUBTRAKTION===========================
//=============================================================

if(t==50)
{
printf("2");
}
//====================3. MULTIPLIKATION===========================
//================================================================
if(t==51)
{
printf("3");
}
//====================4. DIVISION=================================
//================================================================
if(t==52)
{
printf("4");
}
//====================5. EXIT=====================================
//================================================================
if(t==53)
{
printf("5");
}
//===================EINGABE?=====================================
//================================================================
else
{
printf("Konnte Eingabe nicht erkennen, nur Zahlen von 1-5");
}

sleep(33);
}


In die if "Klammern" sollen dann natürlich später mal die richtigen Rechenoperationen rein, momentan soll er nur eine einfache Textausgabe machen, damit man sieht ob das Menü funktioniert.
Was mache ich nur falsch? Muss ich die weiteren if Abfragen in die else "Klammer" schreiben?

Er gibt immer aus, egal was gedrückt wird, das er die Eingabe nicht erkennen konnte, stimmts?

Das problem ist, das wenn eine Addition z.B. durchlaufen wurde, das Programm weiterläuft und da die Auswahl ungleich 53 ist, wird auch immer ausgegeben, dass die Eingabewerte falsch sind.

Du hast im Grunde zwei Möglichkeiten. Die dirrrrty Variante ist, nach der Auswahl und Abarbeitung einer Rechenmethode aus der Funktion herauszusprungen. return sollte dir da helfen können ;)

Die bessere Variante ist, das ganze nicht über if-Anweisungen sondern über eine Mehrfachselektion, wie z.B. switch zu machen.
Dort kannst du jeden Fall hinterlegen der auftreten kann, plus ein default-Fall der Eintritt, wenn kein passender Fall gefunden wurde. So umgehst du elegant das Problem.
Um Switch aber übersichtlich zu halten, sollteste die einzelnen Rechenarten in externe Methoden auslagern.

Monger
2005-10-18, 12:05:18
Wenn ich jetzt nicht völlig auf dem Holzweg bin, sollten switch/case Anweisungen auch immer über break bzw return abgebrochen werden, weil sie sonst weiterlaufen. Ist auf jeden Fall in Java so, und afaik in C/C++ ebenso.

Also

switch(zahl){

case 1: doSth(); break;
case 2: doSthElse(); break;

}

Und so weiter.

Btw, ein Taschenrechner nimmt man immer wieder gerne, ist aber alles andere als trivial. Spätestens wenn man verkettete Ausdrücke (1+4+3 usw) machen will, wird es ziemlich böse. Nicht unbedingt das beste Einsteigerprojekt...

Senior Sanchez
2005-10-18, 12:17:14
Wenn ich jetzt nicht völlig auf dem Holzweg bin, sollten switch/case Anweisungen auch immer über break bzw return abgebrochen werden, weil sie sonst weiterlaufen. Ist auf jeden Fall in Java so, und afaik in C/C++ ebenso.

Also

switch(zahl){

case 1: doSth(); break;
case 2: doSthElse(); break;

}

Und so weiter.

Btw, ein Taschenrechner nimmt man immer wieder gerne, ist aber alles andere als trivial. Spätestens wenn man verkettete Ausdrücke (1+4+3 usw) machen will, wird es ziemlich böse. Nicht unbedingt das beste Einsteigerprojekt...

Also in Java ist es auf jeden Fall so, man sagt dann das die Switch-Anweisung Durchfall hat :D

Hmm, naja, es reicht ja, wenn der Taschenrechner erstmal mit zwei Operanden arbeiten kann.

MadMan2k
2005-10-18, 12:25:48
Btw, ein Taschenrechner nimmt man immer wieder gerne, ist aber alles andere als trivial. Spätestens wenn man verkettete Ausdrücke (1+4+3 usw) machen will, wird es ziemlich böse. Nicht unbedingt das beste Einsteigerprojekt...
der highlevel assembler ist auch nicht die optimale einstiegssprache - also passt doch :)

svenska
2005-10-18, 15:22:20
über case/switch anweisung lösen und
die jeweiligen funktionen, wie schon gesagt wurde auslagern.
das sieht besser/übersichtlicher aus und macht die erweiterung deines rechners besser. :up:

noid
2005-10-18, 16:19:05
der highlevel assembler ist auch nicht die optimale einstiegssprache - also passt doch :)

ich denke, dass die obige variante zum lernen von c eh nicht ideal ist. hier werden sehr viele fkt verwendet, die ich noch nie gesehen habe X-D
mir dünkt, dass diese zu sehr MS-spezifisch sind.

Crushinator
2005-10-18, 16:34:13
(...) mir dünkt, dass diese zu sehr MS-spezifisch sind.
Ist aber Borland. ;) (für DOS)

noid
2005-10-18, 16:44:19
Ist aber Borland. ;) (für DOS)

trotzdem schrecklich. X-D
ist zB getch() nicht auch unsicher?

weiterhin würde ich grundlegende dinge lernen (zB void ist nicht der rückgabetyp von main, da sollte jeder gute compiler meckern). ich weiss nicht ob das projekt in dieser ausführung viel bringt.

sicherlich schön, aber um c zu verstehen würde ich mir was anderes suchen (fällt mich gerade nichts ein). hier kommt ja nichtmal nen einfachzeiger vor.

Gnafoo
2005-10-18, 17:47:11
Oder auch mit else-if anstatt switch, obwohl das nicht so schön ist, aber ich will das nur der Vollständigkeit halber erwähnen:


if(t==...)
{
// bla
}
else if(t==...)
{
// bla2
}
else if(t==...)
{
// bla3
}
else
{
// bla4
}

orda
2005-10-18, 18:06:29
Oder auch mit else-if anstatt switch, obwohl das nicht so schön ist, aber ich will das nur der Vollständigkeit halber erwähnen:


if(t==...)
{
// bla
}
else if(t==...)
{
// bla2
}
else if(t==...)
{
// bla3
}
else
{
// bla4
}


Danke, so werde ich es machen, weil es für einen Anfänger aus meienr Sicht am einfachsten zu verstehen ist. Melde mich dann beim nächsten Problem wieder bei euch.... :biggrin:

Senior Sanchez
2005-10-18, 18:09:29
Danke, so werde ich es machen, weil es für einen Anfänger aus meienr Sicht am einfachsten zu verstehen ist. Melde mich dann beim nächsten Problem wieder bei euch.... :biggrin:

das würde ich so nicht machen, weil die übersichtlichkeit ist echt banane.
nimm lieber switch, früher oder später wirste das eh kennenlernen.

orda
2005-10-18, 20:45:57
das würde ich so nicht machen, weil die übersichtlichkeit ist echt banane.
nimm lieber switch, früher oder später wirste das eh kennenlernen.

Ich mache es erstmal soweit, das alles mit den if else Algorithmen funktioniert und dann versuche ich das Ganze zu vereinfachen (switch). Bin jetzt momentan mit dem Menü fertig und implementiere die Rechenoperationen, versuche es zumindestens.

Vordergründig geht es mir darum, die Denkweise zu verstehen und zu lernen (20 Ebige EBNF und Syntaxdiagramme und solche Späße eben)

orda
2005-10-18, 22:11:48
So, Rechner funktioniert im Groben.

Nur wie kann ich bsw. am Ende nochmal das ganze Programm in einer Schleife sich wiederholen lassen, wenn der User noch eine Rechenoperation durchführen will?

mit goto? Wie muss dazu der (die?) Syntax aussehen?

Trap
2005-10-18, 22:38:50
Ich würde folgendes machen:
bool done=false;
while(!done){
// Menü
}
und dann beim Beenden-Befehl done=true setzen.

Trabi
2005-10-18, 22:40:29
Du kannst es mit goto machen, aber ich würde an deiner Stelle do - while verwenden.

bei goto würde das in etwa so aussehen:

// irgendwo im Programm
Hierhin:
// tue was

// Springe zurück zu Hierhin
goto Hierhin;


Das finde ich aber etwas unschön, deshalb lieber etwas mit while. While kennst du? Jedenfalls wiederholt diese Funktion die Klammer solange die Bedingung von while wahr ist.

do führt die "Klammer" (fällt mir grad kein andres Wort dafür ein, sorry) immer min. einmal aus.

bool wiederholen = false;
do
{
// ich werde min. 1 mal ausgeführt
// tue was
}
while(wiederholen);


Wenn es noch einmal wiederholt werden soll, dann setzt du wiederholen auf true und schon wird es noch einmal ausgeführt. Wenn du es nicht wiederholen willst auf false. (irgendwie logisch, aber kann ja sein, dass du es nicht weisst ;))

Oh da war schon jemand schneller...

Senior Sanchez
2005-10-18, 22:40:51
So, Rechner funktioniert im Groben.

Nur wie kann ich bsw. am Ende nochmal das ganze Programm in einer Schleife sich wiederholen lassen, wenn der User noch eine Rechenoperation durchführen will?

mit goto? Wie muss dazu der (die?) Syntax aussehen?

goto ist böse, ganz ganz böse ;) Das sollte man sich nicht angewöhnen. Erst wenn man weiß was man tut, kann man das mal testweise nutzen.

Halt das ganze inne Schleife packen und solange ne bestimmte Eingabe kommt, wieder von vorne.
Ne do-while()-Schleife würde sich anbieten.

MadMan2k
2005-10-18, 22:42:38
Tipp: fang mit Java bzw. etwas harmlosen an, was dir nen ordentlichen Stil aufzwingt

svenska
2005-10-18, 23:33:21
goto ist böse, ganz ganz böse ;) Das sollte man sich nicht angewöhnen. Erst wenn man weiß was man tut, kann man das mal testweise nutzen.

Halt das ganze inne Schleife packen und solange ne bestimmte Eingabe kommt, wieder von vorne.
Ne do-while()-Schleife würde sich anbieten.


ich will mich nicht streiten, goto sieht vll. nicht toll aus im quelltext aber im compilierten code ist es egal. denn es bleibt ja beim sprung befehl, auch bei einer if,else bedingung bzw. do<>while ect. wenn man nur einmal springt, gehts noch. allerdings sollte man sich mit "goto" nicht den quelltext versauen, auch nicht massiv nutzen und über lange distanzen hin und herspringen.

Senior Sanchez
2005-10-18, 23:58:08
ich will mich nicht streiten, goto sieht vll. nicht toll aus im quelltext aber im compilierten code ist es egal. denn es bleibt ja beim sprung befehl, auch bei einer if,else bedingung bzw. do<>while ect. wenn man nur einmal springt, gehts noch. allerdings sollte man sich mit "goto" nicht den quelltext versauen, auch nicht massiv nutzen und über lange distanzen hin und herspringen.

Naja, eben, solange man es nicht übertreibt, geht es noch. Aber aus meiner Sicht zeugt das Verwenden von goto von schlechtem Design.

svenska
2005-10-19, 00:12:29
Naja, eben, solange man es nicht übertreibt, geht es noch. Aber aus meiner Sicht zeugt das Verwenden von goto von schlechtem Design.


hmm naja. von meinem standpunkt aus isses ok, da ich bei meiner c und assemblerprogrammierung bzw. das dissassemblieren gesehen habe, dass einige dinge wie sprungbefehle oder bedingungen ähnlich compiliert werden. es stimmt aber, dass es im normalen c quellcode doof aussieht.

Coda
2005-10-19, 00:39:45
Naja, eben, solange man es nicht übertreibt, geht es noch. Aber aus meiner Sicht zeugt das Verwenden von goto von schlechtem Design.Das ist eine Legende. Im Linux Kernel hats im Moment genau 32678 gotos und die blicken auch durch ;)

Ne im ernst, aber für early-exit bedingungen oder break-out-of-nested-loops gibt's nichts besseres.

Senior Sanchez
2005-10-19, 01:10:29
Das ist eine Legende. Im Linux Kernel hats im Moment genau 32678 gotos und die blicken auch durch ;)

Ne im ernst, aber für early-exit bedingungen oder break-out-of-nested-loops gibt's nichts besseres.

Nur weil es funktioniert, muss es nicht richtig sein.

32678 gotos hat für mich auch einen leicht mystischen charakter, schau dir die zahl mal genau an ;)

Aus meiner Sicht ist es aber schlechtes Design, weil es den Code beim ersten Einlesen schwer verständlich macht. Wenn man Tag & Nacht drüber hockt, ist einem das irgendwann egal, da kennt man den auswendig ;)

hmmm, naja, um aus inneren schleifen auszubrechen, dafür ist es ne variante, aber ich sagte ja, dass man sparsam damit sein soll.

Coda
2005-10-19, 01:37:17
32678 gotos hat für mich auch einen leicht mystischen charakter, schau dir die zahl mal genau an ;)32768 ist 2^15 - knapp daneben.

Aus meiner Sicht ist es aber schlechtes Design, weil es den Code beim ersten Einlesen schwer verständlich macht. Wenn man Tag & Nacht drüber hockt, ist einem das irgendwann egal, da kennt man den auswendig ;)Ich hab keine Probleme damit, auch wenn ich selber sehr selten gotos verwende.

svenska
2005-10-19, 01:40:12
Nur weil es funktioniert, muss es nicht richtig sein.

32678 gotos hat für mich auch einen leicht mystischen charakter, schau dir die zahl mal genau an ;)

Aus meiner Sicht ist es aber schlechtes Design, weil es den Code beim ersten Einlesen schwer verständlich macht. Wenn man Tag & Nacht drüber hockt, ist einem das irgendwann egal, da kennt man den auswendig ;)

hmmm, naja, um aus inneren schleifen auszubrechen, dafür ist es ne variante, aber ich sagte ja, dass man sparsam damit sein soll.


ja, das is natürlich richtig. wenn ein anderer den code dann bearbeiten soll und es sind dort so einige branches die sonstwohin gehen, dann wird es schwierig.

Senior Sanchez
2005-10-19, 01:51:23
32768 ist 2^15 - knapp daneben.

Ich hab keine Probleme damit, auch wenn ich selber sehr selten gotos verwende.

arg, genau verguggt *ggg*
Das ist bestimmt ein Zeichen.

Naja, es geht halt wie gesagt schon, nur ohne gotos/labels gehts eben besser ;)

noid
2005-10-19, 08:49:11
goto?
das einzige was ich vllt noch akzeptieren würde wäre ein continue oder break. aber goto hat in c nichts verloren. das kommt sicherlich alles von den bösen basic-tippern.

außerdem hatten wir die diskussion schon, und schlussendlich kann man sagen, dass es keine(!) fälle gibt, die man "schöner" mit goto lösen kann. (zumal goto sich in meinen augen schlecht debuggen lässt. auch in der ide schlecht zu finden, wenn man über definitionen und referenzen sucht.)

Trap
2005-10-19, 10:43:40
Oh nein, schon wieder eine goto-Diskussion...

Je unwichtiger die Sache, desto ausführlicher wird drüber diskutiert. Das ist ja fast so wie begin-end vs. {} vs. () oder ";" als statement terminator vs. statement seperator.

Man nimmt einfach die spezifischste Kontrollstruktur die passt. goto als unspezifischste ist halt die letzte Möglichkeit...

orda
2005-10-23, 14:00:50
Danke Leute, Tachenrechner funktioniert super, mit allen mögliche Sprüngen usw.
Habe leider ertsmal goto verwendet und gleich feststellen müssen, dass der Befehl wirklich gefährlich sein kann, besonders wenn es dann komplexer wird.

Werde jetzt den Quelltext versuchen zu vereinfachen und andere Möglichkeiten ausprobieren.