Copyright (C) IOI日本委員会 1994. All rights reserved.
数式を記述する際、演算子(+,-,*,/ など:operator)をオペランド(演算の対象と なるもの:operand)の後ろに書く記法を逆ポーランド記法という。例えば、
(1) a+b は ab+ (2) a*b+c は ab*c+ (3) a+b*c は abc*+ (4) (a+b)/(c-d) は ab+cd-/ (5) a*(b-c) は abc-* (6) (a+b)+c は ab+c+ (7) a+(b+c) は abc++ (8) a+b+c は ab+c+と書く。
[(1)] 次の数式を逆ポーランド記法で書け。 [各1点]
(i) (a-b)*c (ii) a*(b+c/d+e)/f-g
[(2)] 以下の3つの異なる言語で書かれたプログラムはどれも 普通の記法で書かれた数式を逆ポーランド記法の数式に変換するものである。 演算子としては四則演算(+,-,*,/)しか考えず、単項演算子としての+と-(すなわち、 -aとか+bのように使われる場合)も考えないことにする。また、 変数名としては、英小文字(a〜z)1文字だけのものを考えることにし、 定数は含まない。
選択した言語について、空欄を埋めよ。 空欄には2つの演算子の強さを比較する条件式(論理式)が入る。 ただし、演算子 x の強さは下記のどのプログラム中でも order(x) により定められている(値が大きいほど強い)。また、文字コードはASCIIとする。 [2点]
#include <stdio.h> #include <ctype.h> #include <string.h> #define STKMAX 128 #define STRLEN 256 #define OPERAND 0 #define OPERATOR 1 #define LPAREN 2 #define RPAREN 3 #define OTHERS 4 int syurui(char); int order(char); main() { char stack[STKMAX],data[STRLEN]; int n, stkPtr = 0; printf("数式を入力しなさい。\n"); gets(data); printf("%s → ", data); for (n=0; n<strlen(data); n++) { switch (syurui(data[n])) { case OPERAND : putchar(data[n]); break; case OPERATOR : while (stkPtr>0 && syurui(stack[stkPtr-1])==OPERATOR && -------------------------------- | 空欄箇所 | ) -------------------------------- putchar(stack[--stkPtr]); stack[stkPtr++] = data[n]; break; case LPAREN : stack[stkPtr++] = '('; break; case RPAREN : while (stack[stkPtr-1] != '(') putchar(stack[--stkPtr]); --stkPtr; break; case OTHERS : printf("データエラー\n"); exit(1); } } do { putchar(stack[--stkPtr]); } while (stkPtr>0); } int syurui(char x) { switch (x) { case '+' : case '-' : case '*' : case '/' : return OPERATOR; case '(' : return LPAREN; case ')' : return RPAREN; default : return (isalpha(x) ? OPERAND : OTHERS); } } int order(char x) { switch (x) { case '+' : case '-' : return 1; case '*' : case '/' : return 2; } }
DEFINT A-z DECLARE FUNCTION syurui(x) DECLARE FUNCTION order(x) DIM SHARED stack(128) AS INTEGER DIM SHARED stkPtr AS INTEGER CONST operand=0, operator=1, lparen=2, rparen=3, others=4 stkPtr=0 PRINT "数式を入力しなさい。" LINE INPUT data$ PRINT USING "@ → "; data$; FOR n=1 TO LEN(data$) d$=MID$(data$,n,1) SELECT CASE syurui(ASC(d$)) CASE operand PRINT d$; CASE operator DO IF stkPtr<=0 THEN GOTO POS1 IF syurui(stack(stkPtr))<>operator THEN GOTO POS1 ------------------------------- IF | 空欄箇所 | THEN GOTO POS1 ------------------------------- PRINT CHR$(stack(stkPtr)); stkPtr=stkPtr-1 LOOP POS1: stkPtr=stkPtr+1: stack(stkPtr)=ASC(d$) CASE lparen stkPtr=stkPtr+1: stack(stkPtr)=ASC("(") CASE rparen WHILE stack(stkPtr)<>ASC("(") PRINT CHR$(stack(stkPtr)); stkPtr=stkPtr-1 WEND stkPtr=stkPtr-1 CASE others PRINT "データエラー": STOP END SELECT NEXT n PRINT CHR$(stack(stkPtr)); stkPtr=stkPtr-1 WEND END FUNCTION syurui(CodeOfX) x$=CHR$(CodeOfX) SELECT CASE x$ CASE "+" : syurui=operator CASE "-" : syurui=operator CASE "*" : syurui=operator CASE "/" : syurui=operator CASE "(" : syurui=lparen CASE ")" : syurui=rparen CASE ELSE IF ("a"<=x$)AND(x$<="z") THEN syurui=operand ELSE syurui=others END SELECT END FUNCTION FUNCTION order(CodeOfX) x$=CHR$(CodeOfX) SELECT CASE x$ CASE "+" : order=1 CASE "-" : order=1 CASE "*" : order=2 CASE "/" : order=2 END SELECT END FUNCTION
PROGRAM test6; CONST stkmax = 128; strlen = 255; operand = 0; operator= 1; lparen = 2; rparen = 3; others = 4; VAR stack : ARRAY[1..stkmax] OF char; n,stkPtr : integer; data : string[strlen]; FUNCTION syurui(x:char): integer; BEGIN CASE x OF '+','-','*','/' : syurui:=operator; '(' : syurui:=lparen; ')' : syurui:=rparen; ELSE IF ('a'<=x) AND (x<='z') THEN syurui:=operand ELSE syurui:=others; END END; FUNCTION order(x:char): integer; BEGIN CASE x OF '+','-' : order:=1; '*','/' : order:=2; END END; BEGIN stkPtr:=0; writeln('数式を入力しなさい。'); readln(data); write(data, ' → '); FOR n:=1 TO length(data) DO BEGIN CASE syurui(data[n]) OF operand : write(data[n]); operator : BEGIN WHILE (stkPtr>0) AND (syurui(stack[stkPtr])=operator) AND ----------------------------------- ( | 空欄箇所 | ) DO ----------------------------------- BEGIN write(stack[stkPtr]); stkPtr:=stkPtr-1 END; stkPtr:=stkPtr+1; stack[stkPtr]:=data[n] END; lparen : BEGIN stkPtr:=stkPtr+1; stack[stkPtr]:='(' END; rparen : BEGIN WHILE stack[stkPtr]<>'(' DO BEGIN write(stack[stkPtr]); stkPtr:=stkPtr-1 END; stkPtr:=stkPtr-1 END; others : BEGIN writeln('データエラー'); exit END; END END; WHILE stkPtr>0 DO BEGIN write(stack[stkPtr]); stkPtr:=stkPtr-1 END END.
JOI'94へ戻る
JOIホームページへ戻る