プログラミングで数式の値を求める高機能プログラム

このQ&Aのポイント
  • プログラムを発展させ、整数の数式の値を求める高機能なプログラムを作成しました。
  • プログラムは、入力された数式を計算し、その値を表示します。
  • 新たな機能として、乗算と除算の演算子を追加しました。
回答を見る
  • ベストアンサー

プログラミングに自信のある方是非解答をお願いします

問題は以下です。 以下のプログラムは、整数の数式を入力して、式の値を求めて表示するプログラムである。このプログラムを発展させて、さらに高機能にせよ。(何をする機能を加えたかについての解説もお願いします。) #include <stdio.h> #include <stdlib.h> #include <ctype.h> static int ch; void error(char *s) { fprintf(stderr, "%s\n", s); exit(EXIT_FAILURE); } void nextch() { do { if ((ch = getchar()) == EOF) return; }while (ch == ' ' || ch == '\t'); } double number() { double x, a; int sign = '+'; if (ch == '+' || ch == '-') { sign = ch; nextch(); } if (! isdigit(ch)) error("Not a number or '(' is required."); x = ch - '0'; nextch(); while (isdigit(ch)) { x = 10 * x + ch - '0'; nextch(); } if (ch == '.') { a = 1; nextch(); while (isdigit(ch)) { x += (a /= 10) * (ch - '0'); nextch(); } } return sign == '-' ? -x : x; } double expression(); double factor() { double x; if (ch != '(') return number(); nextch(); x = expression(); if (ch != ')') error("')' is required,"); nextch(); return x; } double term() { double x, y; x = factor(); while (1) { if (ch == '*') { nextch(); x *= factor(); } else if (ch == '/') { nextch(); y = factor(); if (y == 0) error("Zero division"); x /= y; } else break; } return x; } double expression() { double x; x = term(); while (1) { if (ch == '+') { nextch(); x += term(); } else if (ch == '-') { nextch(); x -= term(); } else break; } return x; } int main() { double x; nextch(); x = expression(); if (ch != '\n') error("Syntax error"); printf("%g\n", x); return EXIT_SUCCESS; }

  • wfak
  • お礼率78% (11/14)

質問者が選んだベストアンサー

  • ベストアンサー
noname#242220
noname#242220
回答No.2

まず。 プログラム自体が長過ぎる(スパゲッティコード) start data cls // main keyinput if keyin=""then rtn else sub cmpdata ; キー入力待ち if keying="e" then sub printout else end;ここでeが押されるまで処理を繰り返す。 end  //cmpdata ;比較用データアレイと処理 data アレイ 1.a 2.b . end ---------- printout ;結果表示 --===== endReturn

wfak
質問者

お礼

ありがとうございます。

その他の回答 (3)

回答No.4

他人の作ったプログラムを改変する自信があるわけではありませんが、 処理を整数の数式に限定するために、 すべてのdoubleをintに置き換える %gを%dに置き換える 入力文字が'.'のときの処理を削除する これで、環境によっては、処理が高速になります。

  • black2005
  • ベストアンサー率32% (1968/6046)
回答No.3

宿題だろ、これ? 丸投げすんな・・・

  • kamikami30
  • ベストアンサー率24% (812/3335)
回答No.1

自信なくてもできると思うから、本当に自信のある人は回答しないと思うし、基本的に丸投げの人って、自分では何も努力しない他人任せな人という印象が強いから、助けてあげようという気持ちになるひとは少ないと思います。

関連するQ&A

  • 構文図についての問題です。

    全然分からなく困っています。どうか解答、解説をよろしくお願いします。問題は、以下です。 以下のプログラムは、整数の数式を入力して、式の値を求めて表示するプログラムである。このプログラムが対象とする数式の構文を、BNFか構文図で書け。 #include <stdio.h> #include <stdlib.h> #include <ctype.h> static int ch; void error(char *s) { fprintf(stderr, "%s\n", s); exit(EXIT_FAILURE); } void nextch() { do { if ((ch = getchar()) == EOF) return; }while (ch == ' ' || ch == '\t'); } double number() { double x, a; int sign = '+'; if (ch == '+' || ch == '-') { sign = ch; nextch(); } if (! isdigit(ch)) error("Not a number or '(' is required."); x = ch - '0'; nextch(); while (isdigit(ch)) { x = 10 * x + ch - '0'; nextch(); } if (ch == '.') { a = 1; nextch(); while (isdigit(ch)) { x += (a /= 10) * (ch - '0'); nextch(); } } return sign == '-' ? -x : x; } double expression(); double factor() { double x; if (ch != '(') return number(); nextch(); x = expression(); if (ch != ')') error("')' is required,"); nextch(); return x; } double term() { double x, y; x = factor(); while (1) { if (ch == '*') { nextch(); x *= factor(); } else if (ch == '/') { nextch(); y = factor(); if (y == 0) error("Zero division"); x /= y; } else break; } return x; } double expression() { double x; x = term(); while (1) { if (ch == '+') { nextch(); x += term(); } else if (ch == '-') { nextch(); x -= term(); } else break; } return x; } int main() { double x; nextch(); x = expression(); if (ch != '\n') error("Syntax error"); printf("%g\n", x); return EXIT_SUCCESS; }

  • 関数

    FILE *fp; char *str,buf[1000]; char xbuf[100],*xstr;   char ybuf[100],*ystr; static double bx=0; static double by=0; if ((fp = fopen("kadai.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str=='X'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') xstr=xbuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) || *str=='-' || *str=='.')*xstr++=*str++; *xstr='\0'; } if(*str=='Y'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') ystr=ybuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) |*str=='||*str=='.') *ystr++=*str++; *ystr='\0'; } else str++; } } ファイルからの一行の切り分けのプログラムなのですが if(*str=='X'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') xstr=xbuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) || *str=='-' || *str=='.')*xstr++=*str++; *xstr='\0'; } の部分と if(*str=='Y'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') ystr=ybuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) |*str=='||*str=='.') *ystr++=*str++; *ystr='\0'; } の部分は変数が違うだけでほとんど同じ文ですよね。 関数を作ってこの処理のときに呼び出せれば応用が利くと思い 考えてみたのですが中々できません。よろしければ教えて下さい。 まだ戻り値や関数の理解が今ひとつです。

  • C言語による簡易電卓の作成

    四則演算に加えてべき乗、階乗を使えるような電卓を作りたいのです。 四則演算は #include <stdio.h> #include <ctype.h> void Factor( int *x ); void MulDiv( int *x ); void AddSub( int *x ); int expression( void ); int main( void ) { printf( "%d\n", expression() ); return 0; } void Factor( int *x ) { int num = 0, flag = 1, c = 0; c = fgetc( stdin ); if( c == '-' || c == '+' ){ c = fgetc( stdin ); flag = (c == '+' ) ? 1 : -1; } if( isdigit(c) ){ int n = 0; while( isdigit(c) ){ n = n * 10 + ( c - '0' ); c = fgetc( stdin ); } num = n * flag; }else{ if( c == '(' ){ num = expression(); if( fgetc( stdin ) != ')' ){ exit(-1); } c = 0x0100; } } if( c != 0x0100 ) ungetc( c, stdin ); (*x) = num; } void MulDiv( int *x ) { int num = 0, c = 0; Factor( x ); num = (*x); c = fgetc( stdin ); while( c == '*' || c == '/' || c == '%' ){ switch( c ) { case '*': Factor( x ); num = num * (*x); break; case '/': Factor( x ); num = num / (*x); break; case '%': Factor( x ); num = num % (*x); break; } c = fgetc( stdin ); } ungetc( c, stdin ); (*x) = num; } void AddSub( int *x ) { int num = 0, c = 0; MulDiv( x ); num = (*x); c = fgetc( stdin ); while( c == '+' || c == '-' ){ switch( c ) { case '+': MulDiv( x ); num = num + (*x); break; case '-': MulDiv( x ); num = num - (*x); break; } c = fgetc( stdin ); } ungetc( c, stdin ); (*x) = num; } int expression( void ) { int x = 0; AddSub( &x ); return x; } これで正しく動くことを確認できたのですが、階乗、べき乗の書き方が全くわかりません。どなたか、詳しい方いらっしゃいましたら、ご教授願います。

  • プログラム

    { FILE *fp; char *str,buf[1000];   char subbuf[100],*s1; char buf2[100],*s2;   char buf3[100],*s3; char buf4[100],*s4; static double bx=0; static double by=0; if ((fp = fopen("test.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='G'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s2=buf2; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0'&&(isdigit(*str) || *str=='-' || *str=='.')) *s2++=*str++; *s2='\0'; } if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s3=buf3; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *s3++=*str++; *s3='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s4=buf4; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *s4++=*str++; *s4='\0'; } CDC *v; v=GetDC(); if((int)atof(buf2)==92){ MoveTo((int)atof(buf3),(int)atof(buf4)); bx=(int)atof(buf3); by=(int)atof(buf4); ReleaseDC(v); } else if((int)atof(buf2)==01){ MoveTo((int)bx,(int)by); LineTo((int)atof(buf3),(int)atof(buf4)); bx=(int)atof(buf3); by=(int)atof(buf4); ReleaseDC(v); } else str++; } } fclose(fp); return 0; } という風なプログラムになっているのですが 今現在 G01X30Y30 G01X30Y120というファイルをこのプログラムにて実行すると (0,0)→(30,30)→(30,120)というような直線が引かれます。 しかしこれを G01X30Y30 Y120 とかかれたときも同様の結果がでるようにしたいです。 つまり最初のG○○が省略されているときは前回のGの値を X○○が省略されているときは前回のXの値を使うように 変更したいのですがどのように変更すればいいのかがわかりません。 教えてください。

  • プログラム

    以前ファイルからXとYの値だけ取り出し図形を作る質問をした者ですが void Ctest::OnOK() { FILE *fp; char *str,buf[1000];     char buf3[100],*s3; char buf4[100],*s4; if ((fp = fopen("test.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s3=buf3; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *s3++=*str++; *s3='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s4=buf4; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *s4++=*str++; *s4='\0'; CDC *v; GetDC(); MoveTo(0,0); LineTo(atof(buf3),atof(buf4)); ReleaseDC(v); } else str++; } } fclose(fp); return 0; } でコンパイルはできるのですが直線の作図がされません。 どこが間違ってるのでしょうか。VC+6.0のMFC使ってます

  • プログラム

    { FILE *fp; char *str,buf[1000]; char xbuf[100],*xstr;   char ybuf[100],*ystr; static double bx=0; static double by=0; if ((fp = fopen("kadai.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) xstr=xbuf; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *xstr++=*str++; *xstr='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) ystr=ybuf; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *ystr++=*str++; *ystr='\0'; } else str++; } pDC->MoveTo((int)bx,(int)by); pDC->LineTo((int)atof(xbuf),(int)atof(ybuf)); bx=(int)atof(xbuf); by=(int)atof(ybuf); } } fclose(fp); return 0; } とテキストファイルを読み込みその中のXとYに付属する値を 取り出し図形を書くというプログラムなのですが X100Y100 X200Y100というファイルなら (0,0)→(100,100)→(200,100)という2つの直線が描かれます。 実行の結果正常に動きました。 str=buf; の部分ではbufの先頭要素のアドレスをstrに設定している のはわかりました。 しかしxstr=xbufの所ではわからないことがあります。 bufでfpから読み込んだ文字列1行が入っているのはわかります。 しかしxbufにはまだ何も入ってないはずなのに xstr=xbufの所でxbufにはxの値がしっかり入っていました。 これはどうしてでしょうか xbufとかybufとかいらないような気もするのですが もしそうならばどのように書き直せばいいのでしょうか? この2点について教えてください。

  • C言語のプログラミングがうまくいきません!

    先日のプログラムを作り直しました。アドバイスのおかげでエラーは減りましたが、まだ完ぺきではないようです。恐らく、elseのところがいけないと思うのですが、どうしたらいいか分かりません。 ご指摘お願いします。 #include <stdio.h> #include <math.h> void main(void) { double x ,y ,z ,error ,menseki ; double ans; printf("x ?"); scanf("%lf", &x); printf("y ?"); scanf("%lf", &y); printf("z ?"); scanf("%lf", &z); if(x<y+z || y<x+z || z<x+y) { ans=(x+y+z)/2; menseki=sqrt(ans*(ans-x)*(ans-y)*(ans-z)); } if(x==y && y==z && z==x) { printf("正三角形です"); printf("面積は%lfです" , menseki); } else if(x==y || y==z || z==x) { printf("二等辺三角形です"); printf("面積は%lfです" , menseki); } else { printf("三角形です"); printf("面積は%lfです" , menseki); } else { printf("error"); } }

  • sqrtの計算

    ルートの値を返す関数を以下のように作ります。 double sqrt(double x){ double lower,upper,middle,y; lower = 0.0; upper = x; while(1){ middle =(lower+upper)/2.0; y=midde*middle; if(y<0.999*x){ lower=middle; }else if (y>1.001*x){ upper=middle; }else{ return middle; } } } この関数に十分に大きい引数xを関数sqrtに与えたとき、while文による繰り返しは最大何回実行されるか。おおよその回数をxの式で表し、理由を述べよ。 この問題が解ける方は教えて頂きたいです。

  • 二分法のサブ化する方法について

    こんばんは。C言語は超初心者です。以下の文は二分法の部分をサブ化したつもりの文です。がうまくいきません。修正箇所が山ほどあると思いますがよろしくお願いします。 int main (void) { double solution, x; double bisec(double x); solution=bisec(x); cout<<solution<<endl; return 0; } //bisec sub double bisec(double x) { double x, x0, x1, x2, y, y0, y1; int i=0, k=0, j=0; x=0.1; y1=f(x); for(;;) { for(;;) { x+=0.1; if(x>=10.0) { exit(0); } y=f(x); if(y*y1>0) { y1=y; } else { x1=x-0.1; x2=x; x0=x; y0=y; break; } } for(;;) { x=(x1+x2)/2.0; i++; if(fabs((x-x1)/x)>1.0e-14) { y=f(x); if(y*y1>0) { x1=x; y1=y; } else { x2=x; } } else { return x; x=x0; y1=y0; break; } } } } includeと関数f(x)の定義は省略しました。二分法のサブの部分は複数の解を得ることが出来るようになっています。次のことをご教授お願いします。 一つ目は、上の文のbisec(double x)をdouble()にするとエラーが出ないのですが根本的にその理由が分かりません。 二つ目は、解を複数表示する方法が分かりません。上の文では一回returnしちるため1つしか表示されないということは分かるのですが。。 なるべく原文を崩さないで修正お願いします。あまり変わってしまうと理解できないので。。お願いします。

  • プログラミング

    以下のC++で書かれた以下のプログラムのコンパイルができません。理由を教えてください。 #include <iostream> #include <vector> #include <algorithm> istream& read(istream&, std::vector<double>&); double median(std::vector<double>); int main(){ std::vector<double> a; read(std::cin, a); std::vector<double>::iterator itr; while(itr != a.end()){ std::cout << *itr; } std::cout << median(a) << std::endl; } istream& read(istream& is, std::vector<double>& v){ double b; if(is){ while(in >> b) v.push_back(b); } return is; } double median(std::vector<double> a){ int i; if(a.size() == 0) { return -1; } i = a.size() / 2; if(a.size()%2 == 1) return (a[i]); else return ((a[i] + a[i-1])/2); }

専門家に質問してみよう