「みんな教えて! 選手権!!」開催のお知らせ

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define BUFFERSIZE 1024
char Buffer[BUFFERSIZE];
int Index;
int ParseError;

int getE(void);

void parseError(FILE *out, char msg[]) {
ParseError = 1;
fprintf(out, "%s\n", msg);
fprintf(out, "%s\n", Buffer);
for (int i = 0; i < Index; i++) fprintf(out, " ");
fprintf(out, "^\n");
}

void removeWhite(void) {
int j = 0, c;
for (int i = 0; (c = Buffer[i]) != '\0'; i++) {
if (c == ' ' || c == '\t' || c == '\n') continue;
Buffer[j++] = c;
}
Buffer[j] = '\0';
}

int getD(void) {
int value = 0;
while (isdigit(Buffer[Index])) {
value = 10*value + Buffer[Index] - '0';
Index++;
}
return value;
}

int getF(void) {
int value;
if (isdigit(Buffer[Index])) { // 数値表現
value = getD(); if (ParseError) return 0;
} else if (Buffer[Index] == '(') { // ( E )
++Index;
value = getE(); if (ParseError) return 0;
if (Buffer[Index] == ')') {
++Index;
} else {
parseError(stderr, "閉じ括弧')'がありません."); return 0;
}
} else {
parseError(stderr, "数字または開き括弧'('がありません."); return 0;
}
return value;
}

int getT(void) {
int v, value;
value = getF(); if (ParseError) return 0;
while (Buffer[Index] == '*' || Buffer[Index] == '/') {
char op = Buffer[Index++];
v = getF(); if (ParseError) return 0;
if (op == '*') value *= v; else value /= v;
}
return value;
}

int getE(void) {
int v, value;
if (Buffer[Index] == '-') {
++Index;
v = getT(); if (ParseError) return 0;
value = -v;
} else {
value = getT(); if (ParseError) return 0;
}
while (Buffer[Index] == '+' || Buffer[Index] == '-') {
char op = Buffer[Index++];
v = getT(); if (ParseError) return 0;
if (op == '+') value += v; else value -= v;
}
return value;
}

int getExpression(void) {
int value;
value = getE(); if (ParseError) return 0;
if (Buffer[Index] != '\0') {
parseError(stderr, "余分な表現があります.");
}
return value;
}

int mygets(char *s, int n) {
fgets(s, n, stdin);
int lg = strlen(s);
if (lg > 0 && s[lg-1] == '\n') s[--lg] = '\0';
return lg;
}

int main(void) {
int value;
while (1) {
ParseError = 0;
fprintf(stderr, "\n算術式:=");
if (mygets(Buffer, BUFFERSIZE) <= 0) break;
removeWhite();
Index = 0;
value = getExpression();
if (ParseError) {
fprintf(stderr, "正しくない算術式です.\n");
} else {
fprintf(stderr, "正しい算術式です. 値は%dです.\n", value);
}
}
return 0;
}

この構文解析プログラムを実行すると
邂苓。灘シ・=(1+2+3)*3
豁」縺励>邂苓。灘シ上〒縺・ 蛟、縺ッ18縺ァ縺・
のように文字化けしてしまうのですがなぜでしょうか?

A 回答 (2件)

[1] (0) → 0


[2] (1) → 1
[3] ¬0 → 1
[4] ¬1 → 0
[5] 0∧0 → 0
[6] 0∧1 → 0
[7] 1∧0 → 0
[8] 1∧1 → 1
[9] 0∨0 → 0
[10] 0∨1 → 1
[11] 1∨0 → 1
[12] 1∨1 → 1
という書き換えを一度に一つだけ、[1]〜[12]の順番で適用する。(つまり[1]が適用できない場合にのみ[2]をチェックするという風にして、以下同様。)この書き換えを繰り返すと、書き換えるたびに文の長さは減少し、(文が文法に従っていれば)長さ1の文、つまり0か1になって終わる。
 要するに「→の左と一致する部分文字列を見つけて、その部分を→の右の文字列に差し替える」というだけだから、書き換え規則を(if文なんか使わずに)表(配列)にしておけば、ごく短く簡明に書ける。

 しかし、形式文法理論を学ぶ一環としての演習問題なら:この文脈自由文法に従う文を左から順に1文字ずつ処理して受理するpush down automatonを構成する(値の評価はツイデにできちゃう)ために、まずは文法を、例えばGreibach標準形(どの規則も
  P → xQ (x∈Σ)
という格好になってる形)で表しておく。
    • good
    • 0

文字コードを変更。


VSCode右「UTF-8」「エンコード付きで保存」「Shift-JIS」

(parseErroは?)
    • good
    • 0
この回答へのお礼

ありがとうございます。それにしたら解決できました。
ちなみになんですが、
Σ ={0, 1, (, ), ⋀, ⋁,¬}とする.
以下の生成規則をもつ拡張文脈自由文法により
開始記号 E から導出される Σ 上の記号列を論理式とよぶ.
論理式の定義
B → 0 | 1
F → {¬} B | {¬}(E)
T → F { ⋀ F }
E → T { ⋁ T
この定義において、論理式の値の評価を行うプログラムを作りたいのですが上のプログラムをどう改良すればいいでしょうか?
記号「⋀」「⋁」「¬」は,それぞれ,「&」「+」「!」で代用したいです。
もしよければ返信お願いします。

お礼日時:2021/12/08 17:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報