質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

3回答

765閲覧

出力した逆ポーランド法の式を計算して結果を返す方法

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2017/05/29 10:49

C# ```###前提・実現したいこと 出力した逆ポーランド記法の式の演算結果を出力したい ###該当のソースコード ```C# using System; using System.Collections; using System.Collections.Generic; // char型要素の配列のスタックのクラス class Stack_char :IEnumerable { char[] data; // データを格納する配列 int max; // 要素の最大格納数 int top=-1; // topの初期値 public Stack_char(int n) { // 最大要素数 n を指定して作成 data = new char[n]; // 要素数 n の配列を作成 max = n; // max を設定 } public bool Push(char c) { if (top==max-1) return false; // 既に最大数格納されていれば false top += 1; data[top] = c; return true; // Pushに成功すれば true } public char Pop() { top -= 1; return data[top+1]; } public char Top() { return data[top]; } public bool isEmpty() { return (top==-1); } public bool isFull() { return (top==max-1); } public int Count() { return (top+1); } public IEnumerator GetEnumerator() { // リストの最初の要素から順に要素を取り出して返す int i=top; while (i >= 0) { yield return data[i]; i -= 1; } } public void List() { foreach (char k in this) Console.Write("{0} ", k); Console.WriteLine(); } }; class Hoge { static void Main(string[] args) { List<char> output = new List<char>(); // 出力される文字列を格納するchar型動的配列 Stack_char oprs = new Stack_char(100); // (char型要素の)スタックを作成(要素無し) 演算子用 char opr = ' '; Console.Write("B型単純式を入力 : "); string exp = Console.ReadLine(); foreach (char c in exp) { switch (c) { case '+': case '-': case '*': case '/': opr = c; break; case '(': if (opr!=' ') oprs.Push(opr); opr = ' '; break; case ')': if (!oprs.isEmpty()) { char temp = oprs.Pop(); Console.Write("{0} ", temp); output.Add(temp); output.Add(' '); } break; case ' ': break; default: if ('0'<=c && c<='9') { Console.Write("{0} ", c); output.Add(c); output.Add(' '); if (opr!=' ') { Console.Write("{0} ", opr); output.Add(opr); output.Add(' '); opr = ' '; } } break; } if (c!=' ') { Console.Write("c="+c+" oprs = "+opr +" "); oprs.List();} } while (!oprs.isEmpty()) { char c = oprs.Pop(); Console.Write("{0} ", c); output.Add(c); output.Add(' '); } Console.WriteLine(); foreach (char c in output) Console.Write(c); Console.WriteLine(); } }

###試したこと
foreach文を最後に挿入し、cの出力結果を参考に計算するものを実装(ただ普通の式では無いので検索や発想も虚しく終了...)

###補足情報(言語/FW/ツール等のバージョンなど)
B型単純式は講義内で聞いたところ、演算子による演算の優先度を無視するそうです。(1+2*3は7ではなく、9です)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2017/05/29 12:14

全部書き直したいくらいです。もうちょっと練れるはずですが、とりあえずコードを少なくするためにスタックは既存の物を使って書き直してください。バグの入る可能性が減ります。
退会済みユーザー

退会済みユーザー

2017/05/29 12:20

既存のもの・・・ですか???
Zuishin

2017/05/29 12:42

System.Collections.Generic.Stack<char> です。スタッククラスにもバグが入っていますが、そのデバッグが不要になります。
guest

回答3

0

逆ポーと言えばスタックなのでスタックつこてみた

尚、
0. スタックサイズはメモリの限り
0. 動作詳細はHP35sに準拠(完全じゃない

あたりで一つよろしく

csharp

1 2 3using System; 4using System.Collections.Generic; 5using System.Linq; 6 7namespace ConsoleApp6 8{ 9 internal class Program 10 { 11 private static readonly Stack<double> Stack = new Stack<double>(); 12 private static readonly double[] Dummy = new double[4]; 13 private static readonly string[] Tag = {"X", "Y", "Z", "T"}; 14 15 private static void Main(string[] args) 16 { 17 double x, y; 18 19 for (;;) 20 { 21 var input = Console.ReadLine().Split(' '); 22 23 foreach (var s in input) 24 if (double.TryParse(s, out var d)) 25 { 26 Stack.Push(d); 27 } 28 else if (s == "+") 29 { 30 if (Stack.Count >= 2) 31 { 32 x = Stack.Pop(); 33 y = Stack.Pop(); 34 35 Stack.Push(x + y); 36 } 37 } 38 else if (s == "-") 39 { 40 if (Stack.Count >= 2) 41 { 42 x = Stack.Pop(); 43 y = Stack.Pop(); 44 45 Stack.Push(x + y); 46 } 47 } 48 else if (s == "*") 49 { 50 if (Stack.Count >= 2) 51 { 52 x = Stack.Pop(); 53 y = Stack.Pop(); 54 55 Stack.Push(x * y); 56 } 57 } 58 else if (s == "/") 59 { 60 if (Stack.Count >= 2) 61 { 62 x = Stack.Pop(); 63 y = Stack.Pop(); 64 65 Stack.Push(x / y); 66 } 67 } 68 else if (s == "exit") 69 { 70 goto RETURN; 71 } 72 else 73 { 74 Console.WriteLine($"{s} is invalid input"); 75 } 76 77 DispStack(); 78 } 79 80 RETURN: 81 ; 82 } 83 84 85 private static void DispStack() 86 { 87 Console.ForegroundColor = ConsoleColor.Green; 88 89 foreach (var element in Stack.Concat(Dummy).Zip(Tag, (d, s) => (value:d, tag:s)).Reverse()) 90 Console.WriteLine($"\t{element.tag}:{element.value}"); 91 92 Console.ForegroundColor = ConsoleColor.Gray; 93 } 94 } 95} 96

投稿2017/05/30 07:27

Tokeiya3

総合スコア260

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text.RegularExpressions; 5 6class Program 7{ 8 static List<string> Split_Nums(string str) 9 { 10 str = str.Replace(" ", ""); 11 str = str.Replace("**", "^"); 12 str = str.Replace(",", ""); 13 14 Regex re = new Regex(@"\((?<nega>-\d+?(|.\d+?))\)"); 15 16 List<string> negative = new List<string>(); 17 18 MatchCollection mc = re.Matches(str); 19 20 foreach (Match m in mc) 21 { 22 negative.Add(m.Groups["nega"].Value); 23 } 24 25 str = re.Replace(str, "f"); 26 27 List<string> for_translate = new List<string>(); 28 List<string> tmp = new List<string>(); 29 30 for (int i = 0; i < str.Length; i++) 31 { 32 if ("+-*/%^()[]{}".Contains(str[i])) 33 { 34 if (tmp.Count > 0) 35 { 36 for_translate.Add(string.Join("", tmp)); 37 tmp.Clear(); 38 } 39 40 for_translate.Add(str[i].ToString()); 41 } 42 else 43 { 44 tmp.Add(str[i].ToString()); 45 } 46 47 if (i == str.Length - 1) 48 { 49 if (tmp.Count > 0) 50 { 51 for_translate.Add(string.Join("", tmp)); 52 } 53 } 54 } 55 56 for (int i = 0; i < for_translate.Count; i++) 57 { 58 if (for_translate[i] == "f") 59 { 60 for_translate[i] = negative[0]; 61 negative.RemoveAt(0); 62 } 63 } 64 65 return for_translate; 66 } 67 68 //かっこが正しいか数値が正しいかを判定 69 static Object Check(List<string> list) 70 { 71 bool valid_nest = true; 72 73 List<string> nest = new List<string>(); 74 75 Dictionary<string, string> p_dic = new Dictionary<string, string>() 76 { 77 { ")", "(" }, 78 { "]", "[" }, 79 { "}", "{" } 80 }; 81 82 foreach (string e in list) 83 { 84 if ("([{".Contains(e)) 85 { 86 nest.Add(e); 87 } 88 else if (")]}".Contains(e)) 89 { 90 if (nest.Count < 1) 91 { 92 valid_nest = false; 93 break; 94 } 95 96 if (nest.Last() != p_dic[e]) 97 { 98 valid_nest = false; 99 break; 100 } 101 102 nest.RemoveAt(nest.Count - 1); 103 } 104 } 105 106 if (nest.Any()) valid_nest = false; 107 108 if (valid_nest) 109 { 110 int nums = 0; 111 int symbol = 0; 112 113 foreach (string e in list) 114 { 115 if ("+-*/%^()[]{}".Contains(e) == false) 116 { 117 double d = 0; 118 119 if (double.TryParse(e, out d)) 120 { 121 nums++; 122 } 123 } 124 else if (("+-*/%^".Contains(e))) 125 { 126 symbol++; 127 } 128 } 129 130 if (nums <= symbol) return "Invalid expression"; 131 132 for (int i = 0; i < list.Count; i++) 133 { 134 if ("[{".Contains(list[i])) list[i] = "("; 135 if ("]}".Contains(list[i])) list[i] = ")"; 136 } 137 138 return list; 139 } 140 141 return "Missing end bracket"; 142 } 143 144 //逆ポーランド記法に変換 145 static List<string> Translate(List<string> list) 146 { 147 List<string> stack = new List<string>(); 148 List<string> for_calc = new List<string>(); 149 150 for (int i = 0; i < list.Count; i++) 151 { 152 if (list[i] == "(") 153 { 154 stack.Add(list[i]); 155 } 156 else if (list[i] == ")") 157 { 158 while (stack.Last() != "(") 159 { 160 for_calc.Add(stack.Last()); 161 stack.RemoveAt(stack.Count - 1); 162 } 163 164 stack.RemoveAt(stack.Count - 1); 165 } 166 else if ("+-*/%^".Contains(list[i])) 167 { 168 if (stack.Count > 0) 169 { 170 if ("+-".Contains(list[i])) 171 { 172 while ("+-*/%^".Contains(stack.Last())) 173 { 174 for_calc.Add(stack.Last()); 175 stack.RemoveAt(stack.Count - 1); 176 177 if (stack.Count < 1) break; 178 } 179 } 180 else if ("*/%".Contains(list[i])) 181 { 182 while ("*/%^".Contains(stack.Last())) 183 { 184 for_calc.Add(stack.Last()); 185 stack.RemoveAt(stack.Count - 1); 186 187 if (stack.Count < 1) break; 188 } 189 } 190 } 191 192 stack.Add(list[i]); 193 } 194 else 195 { 196 for_calc.Add(list[i]); 197 } 198 199 if (i == list.Count - 1) 200 { 201 if (stack.Count > 0) 202 { 203 stack.Reverse(); 204 205 foreach (string e in stack) 206 { 207 for_calc.Add(e); 208 } 209 } 210 } 211 } 212 213 return for_calc; 214 } 215 216 //逆ポーランド記法を解く 217 static double Calc_Porland(List<string> list) 218 { 219 List<string> stack = new List<string>(); 220 221 while (list.Any()) 222 { 223 stack.Add(list[0]); list.RemoveAt(0); 224 225 if ("+-*/%^".Contains(stack.Last())) 226 { 227 List<string> tmp = stack.GetRange(stack.Count() - 3, 3); 228 229 stack.RemoveRange(stack.Count() - 3, 3); 230 231 double a = double.Parse(tmp[0]); 232 double b = double.Parse(tmp[1]); 233 234 double d = 0.0D; 235 236 switch (tmp[2]) 237 { 238 case "+": 239 d = a + b; 240 break; 241 case "-": 242 d = a - b; 243 break; 244 case "*": 245 d = a * b; 246 break; 247 case "/": 248 d = a / b; 249 break; 250 case "%": 251 d = a % b; 252 break; 253 case "^": 254 d = Math.Pow(a, b); 255 break; 256 } 257 258 stack.Add(d.ToString()); 259 } 260 } 261 262 return double.Parse(stack[0]); 263 } 264 265 static string Calculate(string str) 266 { 267 var nums = Split_Nums(str); 268 269 var result = Check(nums); 270 271 if (result is String) return (string)result; 272 273 double ans = Calc_Porland(Translate((List<string>)result)); 274 275 return ans.ToString(); 276 } 277 278 static void Main(string[] args) 279 { 280 string input = "[{(1+2)*(3+4)}+{(5+6)*(7+8)}]*[{(9+10)*(11+12)}+{(13+14)*(15+16)}]*(-1)+0.1"; 281 Console.WriteLine(Calculate(input)); 282 Console.ReadKey(); 283 } 284}

参考にしたサイト
【Ruby】【アルゴリズム】逆ポーランド記法
逆ポーランド記法による計算式を計算する電卓
逆ポーランド記法変換ツール
rubyについて質問です。のkatoy様の回答
逆ポーランド記法への変換2
素人ですが考えてみました。
このプログラムが正確に動くかどうかは分かりません。
B型単純式についてはよくわからなかったので何もしていません。

投稿2017/05/29 13:24

編集2017/07/16 18:31
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/07/07 12:28 編集

私の画面では編集結果が反映されていないので注意書きをします。 回答の「編集 2017/06/29 01:57」を押すと編集履歴を見ることができます。 編集履歴には回答の変更が反映されています。 編集前の「編集 2017/06/29 01:57」の回答はtranslateの 部分がおかしいです。 +-と*/%の計算順序を間違えています。
guest

0

teratailの運営様に編集結果が反映されない件についてお問い合わせを
行っており、その件で改めて編集が反映されないかどうかをテストさせていただいています。

C#

1using System; 2using System.Collections.Generic; 3using System.Text.RegularExpressions; 4using System.Linq; 5namespace calc_porland 6{ 7 class Program 8 { 9 //式分解 10 static List<string> split_nums(string str) 11 { 12 str = str.Replace(" ", ""); 13 str = str.Replace("**", "^"); 14 str = str.Replace("f", ""); 15 16 Regex re = new Regex(@"\((?<nega>-\d+?(|.\d+?))\)"); 17 18 List<string> negative = new List<string>(); 19 20 MatchCollection mc = re.Matches(str); 21 22 foreach(Match m in mc) 23 { 24 negative.Add(m.Groups["nega"].Value); 25 } 26 27 str = re.Replace(str, "f"); 28 List<string> for_translate = new List<string>(); 29 List<string> tmp = new List<string>(); 30 for (int i = 0; i < str.Length; i++) 31 { 32 if ("+-*/%^()[]{}".Contains(str[i])) 33 { 34 if (tmp.Count > 0) 35 { 36 for_translate.Add(string.Join("", tmp)); 37 tmp.Clear(); 38 } 39 for_translate.Add(str[i].ToString()); 40 } 41 else 42 { 43 tmp.Add(str[i].ToString()); 44 } 45 if(i == str.Length - 1) 46 { 47 if(tmp.Count > 0) 48 { 49 for_translate.Add(string.Join("", tmp)); 50 } 51 } 52 } 53 for(int i =0;i < for_translate.Count; i++) 54 { 55 if (for_translate[i] == "f") 56 { 57 for_translate[i] = negative[0]; 58 negative.RemoveAt(0); 59 } 60 } 61 62 return for_translate; 63 } 64 //かっこが正しいか数値が正しいかを判定 65 static Object check(List<string> list) 66 { 67 bool valid_nest = true; 68 List<string> nest = new List<string>(); 69 Dictionary<string, string> p_dic = new Dictionary<string, string>() 70 { 71 { ")", "(" }, 72 { "]", "[" }, 73 { "}", "{" } 74 }; 75 foreach(string e in list) 76 { 77 if ("([{".Contains(e)) 78 { 79 nest.Add(e); 80 } 81 else if (")]}".Contains(e)) 82 { 83 if(nest.Count < 1) 84 { 85 valid_nest = false; 86 break; 87 } 88 if(nest.Last() != p_dic[e]) 89 { 90 valid_nest = false; 91 break; 92 } 93 nest.RemoveAt(nest.Count - 1); 94 } 95 } 96 if (nest.Any()) valid_nest = false; 97 if(valid_nest) 98 { 99 bool valid_number = true; 100 int nums = 0; 101 int symbol = 0; 102 foreach(string e in list) 103 { 104 if ("+-*/%^()[]{}".Contains(e) == false) 105 { 106 double d = 0; 107 if (double.TryParse(e, out d)) 108 { 109 nums++; 110 } 111 else 112 { 113 valid_number = false; 114 } 115 } 116 else if(("+-*/%^".Contains(e))) 117 { 118 symbol++; 119 } 120 } 121 if (nums <= symbol) return "式が不正です"; 122 if(valid_number) 123 { 124 for (int i = 0; i < list.Count; i++) 125 { 126 if ("[{".Contains(list[i])) list[i] = "("; 127 if ("]}".Contains(list[i])) list[i] = ")"; 128 } 129 return list; 130 } 131 else 132 { 133 return "数値が不正です"; 134 } 135 } 136 return "かっこが不正です"; 137 } 138 //逆ポーランド記法に変換 139 static List<string> translate(List<string> list) 140 { 141 List<string> stack = new List<string>(); 142 List<string> for_calc = new List<string>(); 143 for(int i = 0; i < list.Count; i++) 144 { 145 if(list[i] == "(") 146 { 147 stack.Add(list[i]); 148 } 149 else if(list[i] == ")") 150 { 151 while (stack.Last() != "(") 152 { 153 for_calc.Add(stack.Last()); 154 stack.RemoveAt(stack.Count - 1); 155 } 156 stack.RemoveAt(stack.Count - 1); 157 } 158 else if ("+-*/%^".Contains(list[i])) 159 { 160 if(stack.Count > 0) 161 { 162 if ("+-".Contains(list[i])) 163 { 164 while ("*/%^".Contains(stack.Last())) 165 { 166 for_calc.Add(stack.Last()); 167 stack.RemoveAt(stack.Count - 1); 168 if (stack.Count < 1) break; 169 } 170 } 171 else if (list[i] == "*") 172 { 173 while ("/%^".Contains(stack.Last())) 174 { 175 for_calc.Add(stack.Last()); 176 stack.RemoveAt(stack.Count - 1); 177 if (stack.Count < 1) break; 178 } 179 } 180 else if ("/%".Contains(list[i])) 181 { 182 while (stack.Last() == "^") 183 { 184 for_calc.Add(stack.Last()); 185 stack.RemoveAt(stack.Count - 1); 186 if (stack.Count < 1) break; 187 } 188 } 189 } 190 stack.Add(list[i]); 191 } 192 else 193 { 194 for_calc.Add(list[i]); 195 } 196 if(i == list.Count - 1) 197 { 198 if (stack.Count > 0) 199 { 200 stack.Reverse(); 201 foreach(string e in stack) 202 { 203 for_calc.Add(e); 204 } 205 } 206 } 207 } 208 return for_calc; 209 } 210 //逆ポーランド記法を解く 211 static double calc_porland(List<string> list) 212 { 213 List<double> stack = new List<double>(); 214 foreach(string e in list) 215 { 216 double d = 0; 217 if(double.TryParse(e, out d)) 218 { 219 stack.Add(d); 220 } 221 else 222 { 223 double a = stack.Last(); stack.RemoveAt(stack.Count - 1); 224 double b = stack.Last(); stack.RemoveAt(stack.Count - 1); 225 double acue = 0; 226 switch (e) 227 { 228 case "+": 229 acue = b + a; 230 break; 231 case "-": 232 acue = b - a; 233 break; 234 case "*": 235 acue = b * a; 236 break; 237 case "/": 238 acue = b / a; 239 break; 240 case "%": 241 acue = b % a; 242 break; 243 case "^": 244 acue = Math.Pow(b, a); 245 break; 246 } 247 stack.Add(acue); 248 } 249 } 250 return stack[0]; 251 } 252 //上のメソッドの結果を合体 253 static string porland(string str) 254 { 255 List<string> for_check = split_nums(str); 256 var result = check(for_check); 257 if (result is String) 258 { 259 return (string)result; 260 } 261 else 262 { 263 return calc_porland(translate((List<string>)result)).ToString(); 264 } 265 } 266 static void Main(string[] args) 267 { 268 //string input = "[{(1+2)*(3+4)}+{(5+6)*(7+8)}]*[{(9+10)*(11+12)}+{(13+14)*(15+16)}]"; 269 string input = "[{(1+2)*(3+4)}+{(5+6)*(7+8)}]*[{(9+10)*(11+12)}+{(13+14)*(15+16)}]*(-1)+0.1"; 270 Console.WriteLine(porland(input)); 271 Console.ReadKey(); 272 } 273 } 274}

参考にしたサイト
【Ruby】【アルゴリズム】逆ポーランド記法
逆ポーランド記法による計算式を計算する電卓
逆ポーランド記法変換ツール
rubyについて質問です。のkatoy様の回答
逆ポーランド記法への変換2
素人ですが考えてみました。
このプログラムが正確に動くかどうかは分かりません。
B型単純式についてはよくわからなかったので何もしていません。

投稿2017/07/11 12:51

編集2017/07/11 12:59
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問