Computerhilfen.de Logo
Forum
Tipps
News
Frage stellen

Taschenrechner mit C programmieren.

Hallo,

ich möchte einen Taschenrechner mit C programmieren.

Also Ich hab jetzt noch nicht angefangen.
Mein Plan ist es einen String einzulesen. Und dann...ja  ;D

Irgendwie erst die Zahlen berechnen, die multipliziert bzw. dividiert werden sollen. Und dann die überigen Zahlen adiieren und subrtahieren. Aber wie kann man sowas realisieren?


Antworten zu Taschenrechner mit C programmieren.:

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button
3 Leser haben sich bedankt

Also hab sowas mit c++ schon mal gemacht,
aber die ganze Rechnung als String einzulesen halte ich für unklug, wie willst du da zwischen Operanten und Operatoren unterscheiden?
Hab damals zuerst eine Zahl als Double eingelesen, danach das Rechenzeichen als String eingelesen, dann noch 2.Zahl als Double wieder.
Danach über case-Fallunterscheidung (+,-,*,/) die entsprechende Rechnung ausgeführt.

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button
1 Leser hat sich bedankt

Was mache ich bei längeren Rechnugnen?

3+6*6-8/2

Wie bei deiner Methode würdest du ja einfach von links nach rechts arbeiten, und somit nicht Punkt-vor-Strich-rechnung machen.

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button
1 Leser hat sich bedankt

Das is ja auch nur die einfache Variante eines Rechners,
wie du dir das vorstellst wird schon komplizierter, da du am Anfang die Anzahl und was eingegeben wird nicht festlegen kannst.
Wieviel erfahrung hast du schon mit c denn fürn Anfang find ich is das schon recht schwer!

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Weiß ja nicht, ob du Wert aufs selberprogrammieren legst, aber sonst kannst du mal das hier versuchen:
http://www.gammon.com.au/files/utils/parser.tgz
Und dann einfach benutzen  ;)

#include <stdio.h>
#include <stdlib.h>
#include "parser.h"

int main(int argc, char *argv[]) {
    Parser p( "3 + 6 * 6 - 8 / 2" );
    double d = p.Evaluate();
    printf( "Ergebnis: %f\n", d );
    system( "PAUSE" );
    return 0;
}

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Also ich hatte schon vor, selber zu programmieren. Aber vielleicht sollte ich mir den Parser mal anschauen. ::)
Vielleicht gebe ich mich dann ja doch mit der Art von FuX84 zufrieden ;D

Zu meinen Programmierkenntnissen in C....
naja...es reicht für if, while, for, switch, und do-while. Und noch einige Funktionen die Strings bearbeiten.  :-[

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Kennst du Rekursion? Ansonsten wirst du es nicht verstehen...
Ich hab es mal in C übersetzt und etwas vereinfacht:

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

#define bool int
#define true 1
#define false 0

typedef enum {
    NONE,
    NUMBER,
    END,
    PLUS,
    MINUS,
    MULTIPLY,
    DIVIDE
} TokenType;

char program[100];
char word[100];
TokenType type;
const char * pWord;
const char * pWordStart;
double value;

TokenType getToken( const bool ignoreSign ) {
    word[0] = 0;
    // skip spaces
    while( *pWord && isspace( *pWord ) ) ++pWord;

    pWordStart = pWord; // remember where word starts *now*
 
    if( *pWord == 0 && type == END ) {
        printf( "Unexpected end of expression." );
        exit -1;
    }

    unsigned char cFirstCharacter = *pWord;
 
    if( cFirstCharacter == 0 ) {
        strcpy( word, "<end of expression>" );
        word[19] = 0;
        return type = END;
    }
   
    unsigned char cNextCharacter  = *( pWord + 1 );
   
    // count word length
    int count = 0;
   
    // look for number
    if ( ( !ignoreSign &&
         ( cFirstCharacter == '+' || cFirstCharacter == '-' ) &&
           isdigit( cNextCharacter )
         ) || isdigit( cFirstCharacter ) ) {
       
        // skip sign
        if( ( cFirstCharacter == '+' || cFirstCharacter == '-' ) ){
            pWord++;
            count++;
        }
        while( isdigit( *pWord ) || *pWord == '.' ){
            pWord++;
            count++;
        }
   
        strncpy( word, pWordStart, pWord - pWordStart );
        word[count] = 0;
       
        sscanf( word, "%lf", &value );
        //printf( "Number: %s, Value: %f\n", word, value );
   
        return type = NUMBER;
    }
   
    type = NONE;
    switch( cFirstCharacter ) {
        case '+': type = PLUS; break;
        case '-': type = MINUS; break;
        case '*': type = MULTIPLY; break;
        case '/': type = DIVIDE; break;
    }
   
    if( type != NONE ){
         strncpy( word, pWordStart, 1 );
         word[1] = 0;
         ++pWord;
         return type;
    }
 
    printf( "Unexpected character: %c", cFirstCharacter );
    exit -1;
}

double primary( const bool get ){

    double v;
   
    if( get ) getToken( false );    // one-token lookahead 
       
    switch( type ) {
        case NUMBER: v = value;
                     getToken( true );  // get next one (one-token lookahead)
                     return v;
         
        //case MINUS:  return - Primary (true);  // <- not sure what this one does...
        default:     printf( "Unexpected token: %s", word );
                     exit -1;
    }
 
}

double term( const bool get ) {
     
    double left = primary( get );
    double d;
 
    while( true ) {
        switch( type ){
            case MULTIPLY: left *= primary( true ); break;
            case DIVIDE:   d = primary( true );
                           if( d == 0.0 ){
                               printf( "Divide by zero" );
                               exit -1;
                           }
                           left /= d;
                           break;
            default: return left;
        }
    }
}

double addSubtract( const bool get ) {

    double left = term( get );
    while( true ) {
        switch( type ) {
            case PLUS:  left += term( true ); break;
            case MINUS: left -= term( true ); break;
            default:    return left;
        }
    }
}

double evaluate() {
   
    pWord = program;
    type = NONE;
     
    double v = addSubtract( true );
    if( type != END ) {
        printf( "Unexpected text at end of expression: %s", pWordStart );
        exit -1;
    }
    return v; 
}

int main(int argc, char *argv[]) {
   
    //value = 0.0;
    strcpy( program, "-3" );
    program[9] = 0;
    double d = evaluate();
    printf( "Ergebnis: %f\n", d );
    system("PAUSE");
    return 0;
}

// Based on:
/*

 Parser - an expression parser

 Author:  Nick Gammon
          http://www.gammon.com.au/

(C) Copyright Nick Gammon 2004. Permission to copy, use, modify, sell and
distribute this software is granted provided this copyright notice appears
in all copies. This software is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.
 
Modified 24 October 2005 by Nick Gammon.

  1. Changed use of "abs" to "fabs"
  2. Changed inclues from math.h and time.h to fmath and ftime
  3. Rewrote DoMin and DoMax to inline the computation because of some problems with some libraries.
  4. Removed "using namespace std;" and put "std::" in front of std namespace names where appropriate
  5. Removed MAKE_STRING macro and inlined the functionality where required.
  6. Changed Evaluate function to take its argument by reference.

Thanks to various posters on my forum for suggestions. The relevant post is currently at:

  http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=4649

*/

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Ich habe mal was von Rekursion gelesen und auch schon davon gehört...ehrlich gesagt, verstandne hab ich es nicht wirklich.

Aber macht nichts vielleicht komm ich da noch hinter.
Dauert bei mir meistens länger, weil ich nicht der beste Freund von MAthematik bin. ;D

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button
#include <stdio.h>
#include <stdlib.h>

int fak(int x)
{
  int  ergebnis;
  if(x=0)
  ergebnis=1;
  else
  ergebnis=(x*fak(x-1));
  return ergebnis;
}

int main(int argc, char *argv[])
{
  int zahl, fakul;
  scanf("%i",&zahl);
  fakul=fak(zahl);
  printf("%i",fakul); 
  system("PAUSE");
  return 0;
}

Irgendwo habe ich gelesen, dass Funktionen in C sich slebst aufrufen können. Gut...das Beispiel war für Pascal, aber soll auch für C gehen. Naja. Ich hab's versucht umzuschrieben.

Dev-C++ sagt mir einefach nur "Projekt ist nicht compiliert".

Geht das jetzt doch nicht?

Edit: Ich hab da noch ne Frage ;D
Wenn das rekursiv geht, kann man das doch auch iterativ realisieren, oder?
« Letzte Änderung: 22.08.08, 11:15:33 von Andre S. »

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Doch das geht (so ziemlich in jeder Programmiersprache gibt es Rekursion). Ist ein kleiner Fehler drin. if( x = 0 ) ist eine Zuweisung, du möchtest aber einen Vergleich an der Stelle...
Iterativ könnte es etwa so aussehen:

int fak( int x ) {
    int result = 1;
    for( int i = 2; i <= x; i++ ) {
        result *= i;     
    }
    return result;   
}

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Also liese sich auch ein Parser iterativ programmieren?

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Ja, das geht auch. In diesem Fall müsstest du wahrscheinlich den String zerlegen, dann nach den Token '*' und '/' suchen und die dann mit dem reweils rechten und linken Token auswerten. Das Ergebnis dann wieder an der Stelle einfügen (statt der bisher ausgewerteten Token). Danach dann '+' und '-' auswerten. Also irgendwie eine Liste machen und immer ändern, z.B.:
3, +, 6, *, 6, -, 8, /, 2
3, +, 36, -, 8, /, 2
3, +, 36, -, 4
39, -, 4
35

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Okay...ich glaube rekursiv geht es einfacher.
Ich habe es, glaube ich zumindest, verstanden.


Aber ich hab da mal eine Frage, was mache ich, wenn bei dem Programm "Fakultät". jemand 33 eingibt?
Dann kommt da ja eine negative Zahl bei raus. Warum das so ist weiß ich. Aber gibt es eine Möglichkeit das zu umgehen?

Der Windows-Taschenrechner bekommt das ja auch hin, mit Zhalen zu rechnen, die größer als 2147483647 sind.

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Du kannst natürlich einen Datentyp nehmen, der größer ist. Also z.B. unsigned int, long, unsigned long, long long, unsigned long long. Welcher Typ da jetzt wie definiert ist, hängt auch vom System/Compiler ab.
Als Anhaltspunkt (jeweils die Mindestlänge): http://home.att.net/~jackklein/c/inttypes.html#limits
Bei mir (DevC++) hab ich aber lediglich 4294967295 hingekriegt (unsigned int), die anderen waren nicht größer...

EDIT: Normalerweise sollte es ab 13 mit nem normalen int nicht mehr gehen, irgendwo ab 20! ist dann auch der unsigned long long int voll...

Hier mal mit Typ unsigned long long int unter MS Visual Studio:

Fakultät( 2 ): 2
Fakultät( 3 ): 6
Fakultät( 4 ): 24
Fakultät( 5 ): 120
Fakultät( 6 ): 720
Fakultät( 7 ): 5040
Fakultät( 8 ): 40320
Fakultät( 9 ): 362880
Fakultät( 10 ): 3628800
Fakultät( 11 ): 39916800
Fakultät( 12 ): 479001600
Fakultät( 13 ): 6227020800
Fakultät( 14 ): 87178291200
Fakultät( 15 ): 1307674368000
Fakultät( 16 ): 20922789888000
Fakultät( 17 ): 355687428096000
Fakultät( 18 ): 6402373705728000
Fakultät( 19 ): 121645100408832000
Fakultät( 20 ): 2432902008176640000
Fakultät( 21 ): 14197454024290336768
Fakultät( 22 ): 17196083355034583040
Fakultät( 23 ): 8128291617894825984
Fakultät( 24 ): 10611558092380307456
Fakultät( 25 ): 7034535277573963776
« Letzte Änderung: 26.08.08, 11:56:14 von Lisaa »

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Mir dem DevC++ arbeite ich auch.
naja...müsste ich ne Abfrage basteln, die dann einfach eine Ausgabe "ERROR" macht.

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Wird halt sehr schnell sehr groß... siehe mein Edit in meinem letzten Beitrag...

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Ich habe da noch eine Frage.
Ich hab eeinen Matheparser gefunden.

www.c-programmieren.com

aber da steht
dann

while(1)
{
//Programmcode
}

Was macht diese Anweisung denn?

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Das ist eine Endlosschleife. Du könntest auch schreiben while(true). Ist wahrscheinlich der iterative Ansatz für so einen Parser; beendet wird die Schleife dann (hoffentlich  ;)) ausschließlich manuell durch ein break oder return.

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Gut dann lag ich mit meiner Vermutung ja richtig. ;D

Ja der Parser ist iterativ. dort wird jedes Zeichen einzelnd überprüft. ::)

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Um nicht nohc einen Thread aufmachen zu müssen...

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

char klammern(char rechnung[999]);

int main()
{
    char rechnung[999];
    char temp[999];
   
    printf("Rechnung eingeben: ");
    gets(rechnung);
   
    strcpy(temp,klammern(rechnung));
    puts(temp);
    return 0;
}

char klammern(char rechnung[999])
{
   
   
   
   
  int kl_auf=0,
      i=0;
  char temp[999];
  strcpy(temp,"\0");


  do
  {
  if( rechnung[i]=='(')
  {
      kl_auf++;
  }
  if(kl_auf>0)
  strncat(temp,rechnung+i,1);
 
  if(rechnung [i]==')')
  {kl_auf--;
   if(kl_auf==0)
   break;
  }
 
  i++;
  }
  while(rechnung[i]!='\0');
 
  //Kontrolle
  printf("%i\n",kl_auf);
  printf("%s",temp);
 
  return temp;
}

Beim kompilieren meckert der Compiler:
Zitat
14 [Warning] passing arg 2 of `strcpy' makes pointer from integer without a cast
54  [Warning] return makes integer from pointer without a cast

Also die main() soll nur einen String aufnehmen und am Ende ein Ergebnis ausgeben.

klammern() soll hingegen den Inhalt von Klammern in eine andere Variable kopieren.
Die Funktion alleine läuft auch. Die selbst gebaute Funktion soll irgendwann sich selbst aufrufen und dann die das letzte Klammer in eine Klammer finden (wenn vorhanden).

Aber erstmal reicht mir das was ich bisher geschrieben habe.


EDIT: Ich hab das Problem gefunden ;D
War ganz einfach musste nur angeben das die Funktion einen Pointer zurückgibt. Also

char * klammern();

und nun gehts.
« Letzte Änderung: 04.09.08, 11:08:18 von Andre S. »

Hello,
muss ebenso nen Taschenrechner progn und bin dabei auf euch gestoßen...

gute Ansätze habt ihr, nur würde ich gerne wissen welche funktionen sich hinter strcpy, strncat, puts, gets verbergen?!?

MfG Alex

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Das sind Funktionen aus den C Standardbibliotheken (z.B. cstdlib, cstdio, cstring etc.). Hier gibts ne IMHO ganz gute Referenz dazu: http://www.cplusplus.com/reference/clibrary/
ggf. dort die Suchfunktion verwenden.
 


« SQL: Platzhalter, Datensätze zusammenfassenNach Installation funktioniert Programm nicht mehr »
 

Schnelle Hilfe: Hier nach ähnlichen Fragen und passenden Tipps suchen!

Fremdwörter? Erklärungen im Lexikon!
Double Layer
Double-Layer-DVDs können fast doppelt so viele Daten (8GB) speichern wie einfach beschreibbare DVDs 84,7 GB). Das liegt daran, dass sie zwei beschreibbare Datenschic...

Quellcode
Ein Quellcode, auch als Quelltext bekannt, bezeichnet den unkompilierten Programm-Code einer Software. Quell- oder Programm-Code ist der auch für Menschen lesbare Co...

Unicode
Unicode ist ein international anerkannter Standard, der als universeller Zeichencode ("Universal Code") dient und durch das Unicode-Konsortium entwickelt und verwaltet wi...