C言語での実装例とは? わかりやすく解説

Weblio 辞書 > 辞書・百科事典 > ウィキペディア小見出し辞書 > C言語での実装例の意味・解説 

C言語での実装例

出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2020/02/20 09:34 UTC 版)

操車場アルゴリズム」の記事における「C言語での実装例」の解説

#include #include #include // 演算子// 優先順位 : 演算子 : 結合性// 4 : ! : 右結合性// 3 : * / % : 左結合性// 2 : + - : 左結合性// 1 : = : 右結合性int op_preced(const char c){ switch (c) { case '!': return 4; case '*': case '/': case '%': return 3; case '+': case '-': return 2; case '=': return 1; } return 0;} bool op_left_assoc(const char c){ switch (c) { // 左結合性 case '*': case '/': case '%': case '+': case '-': return true; // 右結合性 case '=': case '!': return false; } return false;} unsigned int op_arg_count(const char c){ switch (c) { case '*': case '/': case '%': case '+': case '-': case '=': return 2; case '!': return 1; default: // 関数場合、A()引数は0個、B()引数は1個、C()引数は2個... と定義 return c - 'A'; } return 0;} #define is_operator(c) (c == '+' || c == '-' || c == '/' || c == '*' || c == '!' || c == '%' || c == '=')#define is_function(c) (c >= 'A' && c <= 'Z')#define is_ident(c) ((c>= '0' && c <= '9') || (c>= 'a' && c <= 'z')) bool shunting_yard(const char *input, char *output){ const char *strpos = input, *strend = input + strlen(input); char c, *outpos = output; char stack[32]; // 演算子スタック unsigned int sl = 0; // スタック長(深さchar sc; // スタック要素記録while (strpos < strend) { // 入力ストリームからトークンを1つ読み込む c=*strpos++; if (c == ' ') { continue; } else if (is_ident(c)) { // トークンが数値(識別子)なら、出力キューに追加する *outpos++ = c; } else if (is_function(c)) { // トークンが関数なら、スタックにプッシュする。 stack[sl++] = c; } else if (c == ',') { // トークンが関数の引数のセパレータ(例えばカンマ)の場合 bool pe=false; while (sl> 0) { sc = stack[sl - 1]; if (sc == '(') { pe = true; break; } else { // スタックトップトークンが左括弧になるまで // スタック上の演算子出力キューポップ続ける *outpos++ = sc; sl--; } } // 左括弧出てこなかった場合、すなわちセパレータ位置が変だった場合 // あるいは括弧正しく対応してない場合 if (!pe) { printf("エラーセパレータ括弧不一致\n"); return false; } } else if (is_operator(c)) { // トークン演算子 op1 の場合 while (sl > 0) { sc = stack[sl - 1]; // op1 が左結合性優先順位が op2 と等しいか低い場合 // あるいは op1 の優先順位が op2 より低い場合 // 演算子トークン op2 がスタックトップにある間ループする。 // 1^2+3 のような式を正しく 12^3+ に変換するため // "+" と "^" は右結合性とする。 // 演算子の優先順位違いからポップするかプッシュするかを判断する。 // 2つ演算子の優先順位等しいなら、結合性から判断する。 if (is_operator(sc) && ((op_left_assoc(c) && (op_preced(c) <= op_preced(sc))) || (op_preced(c) < op_preced(sc)))) { // Pop op2 off the stack, onto the output queue; *outpos++ = sc; sl--; } else { break; } } // op1 をスタックにプッシュ stack[sl++] = c; } else if (c == '(') { // トークンが左括弧なら、スタックにプッシュ stack[sl++] = c; } else if (c == ')') { // トークンが右括弧の場合 bool pe=false; // スタックのトップにあるトークンが左括弧になるまで // スタックから出力キューに演算子をポップし続ける while (sl> 0) { sc = stack[--sl]; if (sc == '(') { // スタックから左括弧ポップするが、出力キューには置かない pe = true; break; } else { *outpos++ = sc; } } // スタック全部見ても左括弧到達しなかった場合左右括弧不一致があることになる if (!pe) { printf("エラー括弧不一致\n"); return false; } // スタックトップにあるトークン関数トークンなら、それを出力キューポップする if (sl > 0) { sc = stack[sl - 1]; if (is_function(sc)) { *outpos++ = sc; sl--; } } } else { printf("不明なトークン:%c\n", c); return false; // 不明なトークン } } // 読み込むべきトークン尽きた際 // スタック上に演算子トークン残っていたら、それらを出力する while (sl > 0) { sc = stack[--sl]; if (sc == '(' || sc == ')') { printf("エラー括弧不一致\n"); return false; } *outpos++ = sc; } *outpos = 0; // ヌルターミネート return true;} bool execution_order(const char *input){ const char *strpos = input, *strend = input + strlen(input); char c, res[4]; unsigned int sl = 0, sc, stack[32], rn = 0; printf("【実行順序\n"); // 入力トークンがある間ループする while (strpos < strend) { // 入力から次のトークン読み込む c = *strpos++; if (is_ident(c)) { // トークンが値か識別子場合 // それをスタックプッシュする。 stack[sl++] = c; } else if (is_operator(c) || is_function(c)) { // さもなくばトークン演算子である(ここでは関数演算子含める) sprintf(res, "$%d", rn++); printf("%s = ", res); // 演算子が n 個の引数をとることは事前にわかっている。 unsigned int nargs = op_arg_count(c); if (sl < nargs) { // スタックに n 個未満の値しかない場合 // ユーザーの入力した式に値(引数)が足りないのでエラーを返す return false; } // そうでない場合、スタックから n 個の値をポップする // それらの値を引数として、演算子を評価する if (is_function(c)) { printf("%c(", c); while (nargs> 0) { sc = stack[sl - nargs]; // 逆順引数削除 if (nargs > 1) { printf("%s, ", (char*) &sc); } else { printf("%s);\n", (char*) &sc); } --nargs; } sl -= op_arg_count(c); } else { if (nargs == 1) { sc = stack[--sl]; printf("%c %s;\n", c, (char*) &sc); } else { sc = stack[sl - 2]; printf("%s %c ", (char*) &sc, c); sc = stack[sl - 1]; sl -= 2; printf("%s;\n", (char*) &sc); } } // 返ってきた結果がもしあれば、スタックプッシュ stack[sl++] = *(unsigned int*) res; } } // スタック1つ値しない場合、 // その値が計算結果である。 if (sl == 1) { sc = stack[--sl]; printf("実行結果は %s\n", (char*) &sc); return true; } // スタックにさらに値がある場合 // ユーザ入力に値が多すぎるので、エラーとする。 return false;} int main(){ // 関数: A() B(a) C(a, b), D(a, b, c) ... // 識別子: 0 1 2 3 ... および a b c d e ... // 演算子: = - + / * % ! const char *input = "a = D(f - b * c + d, !e, g)"; char output[128]; printf("【入力\n%s\n\n", input); if (shunting_yard(input, output)) { printf("【出力\n%s\n\n", output); if (!execution_order(output)) { printf("\n不正な入力\n"); } } return 0;} このコード次のような結果出力する。 【入力a = D(f - b * c + d, !e, g)【出力afbc*-d+e!gD=【実行順序】$0 = b * c;$1 = f - $0;$2 = $1 + d;$3 = ! e;$4 = D($2, $3, g);$5 = a = $4;実行結果は $5

※この「C言語での実装例」の解説は、「操車場アルゴリズム」の解説の一部です。
「C言語での実装例」を含む「操車場アルゴリズム」の記事については、「操車場アルゴリズム」の概要を参照ください。

ウィキペディア小見出し辞書の「C言語での実装例」の項目はプログラムで機械的に意味や本文を生成しているため、不適切な項目が含まれていることもあります。ご了承くださいませ。 お問い合わせ



英和和英テキスト翻訳>> Weblio翻訳
英語⇒日本語日本語⇒英語
  

辞書ショートカット

すべての辞書の索引

「C言語での実装例」の関連用語

C言語での実装例のお隣キーワード
検索ランキング

   

英語⇒日本語
日本語⇒英語
   



C言語での実装例のページの著作権
Weblio 辞書 情報提供元は 参加元一覧 にて確認できます。

   
ウィキペディアウィキペディア
Text is available under GNU Free Documentation License (GFDL).
Weblio辞書に掲載されている「ウィキペディア小見出し辞書」の記事は、Wikipediaの操車場アルゴリズム (改訂履歴)の記事を複製、再配布したものにあたり、GNU Free Documentation Licenseというライセンスの下で提供されています。

©2024 GRAS Group, Inc.RSS