Cで計算機を作る(足し算、引き算)
―準備中―
C言語で計算機を作ってみます。まずは足し算、引き算だけの基本形から。
プログラムはVB.netで作ったプログラムをC用に改変したものなので、
プログラムの説明は「VB.netで計算機を作る(足し算、引き算)」をご参照下さい。
ここでは、VB.netからC用に改変したコードの部分のみ説明を書きます。
列挙型、構造体の宣言の書き方
VB.netとCでは若干違う。違いはコードを見てください。
Cでは、関数のプロトタイプ宣言が必要。
関数get_token
Cではreturnで構造体変数そのものをを返り値にできないので、
構造体tokenの変数tokをグローバル変数として宣言し、tokを関数の引数として呼び出して、
その引数(構造体変数tok)を変更することにより、変更した値を渡している。
VB.net版ではreturnで構造体の変数そのものを返り値にしている。
ほとんどのコードはほぼ似たようなものですが、異なっているのは以下の2か所
文字列を整数型に変換するところは
VB.netでは、 tok(pos).v = Integer.Parse(tok(pos).str)
Cでは、tok[pos].v = atoi(tok[pos].str)
読み込んだ文字を文字列に連結していくところは
VB.netでは、tok(pos).str = tok(pos).str + statement.Chars(i)
Cでは strcpy(tok[pos].str,st)
calc0.0a.c Borland C++用
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> typedef enum{ number, dot, add_op, sub_op, mul_op, div_op, lparen, rparen, space, bad, line_end, } type; typedef struct { type type; char str[20]; int v; } token; type checktype(char); double expression(void); double primary_expression(void); void get_token(token *t); void unget_token(void); token tok[30]; int main(void) { /* token tok[30]; */ /* Declare as a local variable in the main function */ int i,pos,isnum,len; double value; type r; char exp[50], st[2]; gets(exp); len = strlen(exp); for (i=0; i < len; i++) { printf("%d : %c\n", i, exp[i]); } printf("token:%d\n",len); pos=0; isnum=0; for(i=0; i < len; i++) { r=checktype(exp[i]); /* printf("%d :%c : %d \n",i,exp[i],r); */ st[0]=exp[i]; st[1]='\0'; if (r == space) continue; if (r == bad) break; if (isnum == 1 && r == number) { strcat(tok[pos].str,st); tok[pos].v = atoi(tok[pos].str); continue;} if (isnum == 1 && r == rparen) { pos = pos + 1 ; strcpy(tok[pos].str,st); tok[pos].type = r; continue;} if (isnum == 1 && (r == add_op || r == sub_op || r == mul_op || r == div_op)) { pos = pos + 1; strcpy(tok[pos].str,st); tok[pos].type = r ; pos = pos + 1; isnum = 0; continue;} if (isnum == 0 && r == lparen) { strcpy(tok[pos].str,st); tok[pos].type = r; pos = pos + 1; continue; } if (isnum == 0 && r == number) { strcpy(tok[pos].str,st); tok[pos].type = r; tok[pos].v = atoi(tok[pos].str); isnum = 1;} if (isnum == 0 && r == sub_op) { strcpy(tok[pos].str,st); tok[pos].type = number; isnum = 1;} } tok[pos+1].type=line_end; for( i = 0; i <= pos+1; i++) { printf("%d : %s; %d\n",i,tok[i].str,tok[i].type); } if (r == bad) printf("Wrong expression\n"); printf("calculate\n"); value=expression(); printf("value=%lf",value); return 0; } type checktype(char t) { type r; r=bad; if (isdigit(t) != 0 ) r=number; /* isdigit return ascii code, if augument is numeric */ if (t == '+') r=add_op; if (t == '-') r=sub_op; if (t == '*') r=mul_op; if (t == '/') r=div_op; if (t == '(') r=lparen; if (t == ')') r=rparen; if (t == ' ') r=space; /* printf("%c : %d \n",t,r); */ return (r); } double expression() { double v1, v2; token t; v1=primary_expression(); printf("expession v1:%lf\n",v1); while (1){ get_token(&t); printf("expression %s: %d : %d\n", t.str, t.type, t.v); if (t.type != add_op && t.type != sub_op) { unget_token(); break;} v2 = primary_expression(); printf("expression v2:%lf\n", v2); if (t.type == add_op) v1 = v1 + v2; if (t.type == sub_op) v1 = v1 - v2; printf("expression calculated v1:%lf\n", v1); } return (v1); } double primary_expression() { token t; get_token(&t); printf("primary_expression %s: %d : %d \n", t.str, t.type, t.v); if (t.type == number) return (t.v); else return (0); } void get_token(token *t) { static int i = 0; printf("get_token %d: %s : %d : %d \n", i, tok[i].str, tok[i].type, tok[i].v); /* Assign the structure *t=toku[i] */ *t=tok[i]; i++; } void unget_token() { }
次回は、乗算・除算もできるようにします。ー>「Cで計算機を作る(乗算・除算)」