C言語-インタプリタminiCASL
前へ 目次へ 次へ 

 9. 命令も英大文字・小文字のどちらでも使えるようにする

 変数は、関数toupper()で英大文字に変換して、大文字・小文字が区別されないようにした。同じように、命令も大文字でも小文字でも使用できるようにする。
 関数toupperは、1文字分のデータしか大文字に変換することができない。文字列中の英小文字だけを大文字に、または、その逆に変換するの標準関数にはない。ここでは、文字列中の英小文字だけを大文字に変換するユーザ関数str_upperを作成する。

 1行読み込んだ直後に、ユーザ関数str_upperを使用して英小文字を大文字に変換する。変数名も含めてすべて英大文字に変換されるので、関数toupperで変数名を大文字に変換する必要はなくなる。

[mc10.c] (修正部分は赤色太字で示す。)
 1:
 2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "gettoken.h"

#define STRMAX 80       /* 文字列配列の大きさ */
/* グローバル変数 */
double hensuu[26];      /* mc言語の変数用 */

void main(int argc, char *argv[])
{
    char    *str_upper(char *); /* 文字列大文字変換関数 */
    int     get_valnum(void);   /* 変数番号取得関数 */
    double  get_para(void);     /* 引数取得関数 */
    FILE    *fp;                /* ファイル操作用 */
    char    inbuff[STRMAX];     /* 入力データ用 */
    int     val;                /* 変数番号用 */

    if(argc != 2){      /* パラメータのチェック */
        printf("使い方:MC filename\n");
        exit(1);
    }
    if((fp = fopen(argv[1], "r")) == NULL){     /* ファイルのオープン */
        printf("ファイルがオープンできませんでした。\n");
        exit(1);
    }
    while(fgets(gt_line, STRMAX, fp)){     /* データの読み込み */
        str_upper(gt_line);
        get_token();
        if(!strcmp(token, "ADD")){    /* 命令判定 */
            get_token();
            val = get_valnum();
            get_token();
            hensuu[val] = hensuu[val] + get_para();
        }else if(!strcmp(token, "SUB")){
            get_token();
            val = get_valnum();
            get_token();
            hensuu[val] = hensuu[val] - get_para();
        }else if(!strcmp(token, "MUL")){
            get_token();
            val = get_valnum();
            get_token();
            hensuu[val] = hensuu[val] * get_para();
        }else if(!strcmp(token, "DIV")){
            get_token();
            val = get_valnum();
            get_token();
            hensuu[val] = hensuu[val] / get_para();
        }else if(!strcmp(token, "END")){
            break;
        }else if(!strcmp(token, "IN")){
            get_token();
            val = get_valnum();
            printf("in=");
            gets(inbuff);
            hensuu[val] = atof(inbuff);
        }else if(!strcmp(token, "OUT")){
            get_token();
            val = get_valnum();
            printf("%f\n", hensuu[val]);
        }else{
            printf("Error : コマンドエラー\n");
            continue;
        }
    }
    fclose(fp);         /* ファイルのクローズ */
}
char *str_upper(char *str)
{
    char    *top = str;

    while(*str){
        if(*str >= 'a' && *str <= 'z')
            *str = *str - 0x20;
        ++str;
    }
    return(top);
}
int get_valnum(void){
    if(isalpha(*token)){
        return(*token - 'A');       /* 変数番号 */
    }else{
        printf("変数を指定してください。\n");
        exit(1);
    }
}
double get_para(void){
    if(isalpha(*token)){
        return(hensuu[*token - 'A']);   /* 変数値 */
    }else if(isdigit(*token) || *token == '+' || *token == '-'){
        return(atof(token));            /* 数値 */
    }else{
        printf("変数または数値を指定してください。\n");
        exit(1);
    }
}
実行結果
D:\Data\src>cc mc10.c gettoken.obj
lld @link.i
D:\Data\src>mc10 reidai04.mc
in=12.345
in=11.111
23.456000
12.345000
123.450000
-12.345000

 変数gt_lineはgettoken.hで宣言されているグローバル変数なので、関数str_upper()の引数として渡す必要はない。しかし、言語処理プログラムでは文字列全体を大文字に変換するケースがあるので、どのようなケースでも使えるように引数として変換したい文字列を指定するようにしている。
 これでmc言語の一応の完成である。



【課題】
 CASL風の言語を作成してきたので、さらに次のような機能の拡張を各自で研究して追加してみよう。
 機能の追加は、どれから行っても問題はないと思うので、実現しやすそうなものから取りかかってみよう。

 等々


前へ 目次へ 次へ 
Copyright © 2001 Hiroshi Masuda 

 

 

inserted by FC2 system