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で計算機を作る(乗算・除算)」