  
  
C#を利用してコンソールに数値、演算子を入力してその結果を表示したいです。

例

[code]

    入力⇒ 2+10×3+2 ...①
    結果⇒ 38
    
[/code]

・四則演算の優先順位は考えず、左から計算して結果を算出  
・入力者は①のような入力を一度で行い、その後Enterを押すと直ぐに結果を表示する（四則演算を別で入力させない）

※以下の方法は使用しない

[code]

    コンソール出力例
    ⇒数値を入力してください＞5
     もうひとつの数値を入力してください＞5
     演算子を入力してください＞+
     結果 10
    
[/code]

開発環境はVisual Studioです。

自身の考え方としては以下です。  
String型で読みとった文字列①をfor文で回し、1つずつ取り出します。  
取り出した文字をint.TryParse()で判定。  
（ここからどうすれば良いか分かりません）  
数値だった場合変数に格納？  
四則演算子であった場合if文で計算？

forループで取り出した文字を判定するまではコードをかけるのですが、その後の作成方法がよく分かりません。

よろしくお願いします。


CC BY-SA 4.0
2023-11-01T12:35:19.383
96646
2023-11-02T23:09:37.587
2023-11-02T09:09:00.110
3060
60288
question
c#
C# で入力された数式をもとに四則演算を行いたい


> String型で読みとった文字列①をfor文で回し、1つずつ取り出します。  
>  取り出した文字をint.TryParse()で判定。

考え方は合ってます。

> 数値だった場合変数に格納？

格納しましょう。  
変数に格納しないとプログラムは値を保持できません。  
ただし **連続して数字を評価するロジック** に注意が必要です。

例えば"123"という文字を1つずつ取り出すとしましょう。  
変数`int j`をfor文の前に宣言し、"1"を評価した時に`j=1;`と代入したとします。  
次に"2"を評価した時、`j=j+2;`とすると`j+1+2;`の計算が行われて`j`の値は3になってしまいます。  
連続して数字を評価する場合はstring型の"123"をint型の123に変換しなければなりません。

これを実現する方法はいくつかありますので考えてみてください。

> 四則演算子であった場合if文で計算？

最終的にif文で計算しますが、ご提案のロジックではすぐに計算できません。

例えば"1+23-4"という文字を1つずつ取り出すとしましょう。  
変数`int j`に1を代入した後に`+`を評価した時、まだ`j`に足す値が確定できていません。  
足し算をしようとしても23が変数に入っていないため、`j+???`という状態になっています。

なので四則演算子であった場合および文字列の最後であった場合には、 **1つ前の四則演算子** をif文で計算するロジックが考えられます。  
つまり"1+23-4"を計算するロジックは下記の疑似コードの流れで計算できます。

[code]

    string siki = "1+23-4";
    int result = 1;         // 1文字目を評価して変数化
    string operator = "+";  // 2文字目が四則演算子なので、演算子を一時的に保存(まだ23を評価していない)
    int j = 23;             // 3,4文字目の連続した数値を変数化
    if(operator == "+") {   // 5文字目で次の四則演算子が出た時、1つ前の四則演算子で変数resultと変数jを加減乗除する
        result += j;        // if文で計算
    }
    operator = "-";         // 5文字目が四則演算子なので、演算子を一時的に保存(まだ4を評価していない)
    int j = 4;              // 6文字目を変数化
    if(operator == "-") {   // 最後に1つ前の四則演算子で変数resultと変数jを加減乗除する
        result -= j;        // if文で計算
    }
    
[/code]

これらの考え方を理解してfor文に書き換えることで目的の計算を実現できます。  
for文を1回ループするごとに、評価する文字は何か、変数には何が入っているのかを考えて整理することがポイントです。  
がんばってください。


CC BY-SA 4.0
2023-11-02T00:51:03.233
96648
2023-11-02T00:51:03.233
9820
96646
answer


整数だけを扱う、負の値はない、演算子は +, -, x, /
だけ、質問に書いてあったように「四則演算の優先順位は考えず、左から計算する」、不正な入力は考えないということでよければ・・・

(1) 入力の文字列から String.Split メソッドを使って整数部分の配列を取得。

(2) 計算結果を保持する変数を定義し、(1) で得た最初の数字を代入。例えば、`int result = integers[0];` とする。

(3) 入力の文字列を for ループを使って最初から一文字ずつ演算子 (+, -, x, /) か否か調べていき、演算子であれば前後する数字を +=,
-=, *=, /= を使って result に反映する。

* * *

**【追記】**

上に書いたことがコードがないと分からないようなので追記しておきます。

[code]

    using System;
    using System.Collections.Generic;
    
    namespace ConsoleApp7
    {
        internal class Program
        {
            static void Main(string[] args)
            {
                // Console.ReadLine とかは省略
                // 「入力者は①のような入力を一度で行い、その後Enterを押すと直ぐ
                // に結果を表示する（四則演算を別で入力させない）」・・・という
                // ことなので入力完了の結果から話を始めます
                var input = "2+10x3+2";
    
                // (1) 入力の文字列から String.Split メソッドを使って整数部分
                // の配列を取得
                var integers = new List<int>();
                foreach (var s in input.Split(new char[] { '+', '-', 'x', '/' }))
                {
                    integers.Add(int.Parse(s));
                }
    
                // integers の中の対象とする要素を指すインデックス
                int index = 0;
    
                // (2) 計算結果を保持する変数を定義し、(1) で得た最初の数字を代入
                var result = integers[index];
    
                // (3) 入力の文字列を for ループを使って最初から一文字ずつ演算
                // 子 (+, -, x, /) か否か調べていき、演算子であれば前後する数字
                // を +=, -=, *=, /= を使って result に反映する
                for (int i = 0; i < input.Length; i++)
                {
                    if (input[i] == '+')
                    {
                        index++;
                        result += integers[index];
                    }
                    else if (input[i] == '-')
                    {
                        index++;
                        result -= integers[index];
                    }
                    else if (input[i] == 'x')
                    {
                        index++;
                        result *= integers[index];
                    }
                    else if (input[i] == '/')
                    {
                        index++;
                        result /= integers[index];
                    }
                    else
                    {
                        continue;
                    }
                }
    
                Console.WriteLine(result);
            }
        }
    }
    
[/code]

結果:

[![画像の説明をここに入力](https://i.stack.imgur.com/xOXk2.jpg)](https://i.stack.imgur.com/xOXk2.jpg)


CC BY-SA 4.0
2023-11-02T02:13:06.450
96649
2023-11-02T07:22:11.723
2023-11-02T07:22:11.723
51338
51338
96646
answer


様々な事柄をとりあえず考慮せずに，最も単純かと思うレベルにすると以下のような感じでしょうか？

  * 先頭から１文字ずつ見ていって，｛数字だったら→こうする，そうじゃなかったら→こうする｝みたいなのを愚直に書いた．
  * サポートする演算子は { `+`, `-`, `*` } のみ．
  * 入力は数字と↑の３種の演算子のみで構成されているという前提．スペースすら許されない．（他の文字があると `Calc()` メソッドから容赦なく例外送出されます）
  * 先頭が `-` や `+` から始まる入力も扱えない．
  * `int.Parse()` を使用している（→失敗する場合には例外で強制終了）

[code]

    class Program
    {
        //２項演算処理
        static int Calc( int lhs, char Operator, int rhs )
        {
            switch( Operator )
            {
            case '+':   return lhs+rhs;
            case '-':   return lhs-rhs;
            case '*':   return lhs*rhs;
            default:    throw new ArgumentException( "Unknown Operator " + Operator );
            }
        }
    
        //Main
        static void Main(string[] args)
        {
            //数式を１行で入力する
            string Input = Console.ReadLine();
    
            //
            int CurrCalcResult = 0; //計算経過値
            string ValStr = ""; //数字が連続しているうちはここに連結していく
            char Operator = '+';    //最後に見つけた演算子
    
            foreach( char c in Input ) //１文字ずつ見ていく
            {
                if( char.IsNumber(c) )
                {//数字なら ValStr に繋げる
                    ValStr += c;
                }
                else
                {//※数字じゃないやつは演算子なのだと想定
                    if( ValStr.Length > 0 )
                    {//途中計算を実施
                        CurrCalcResult = Calc( CurrCalcResult, Operator, int.Parse(ValStr) );
                        ValStr = "";
                    }
                    else
                    {//入力の先頭が数字じゃないとか，演算子が連続で並んでいるとかいう場合
                        Console.WriteLine( "Format Error" );
                        return;
                    }
                    //演算子を記録
                    Operator = c;
                }
            }
            //最後の計算を実施
            if( ValStr.Length > 0 )
            {   CurrCalcResult = Calc( CurrCalcResult, Operator, int.Parse(ValStr) );   }
            else
            {   Console.WriteLine( "(The last operand is missing...?)" );   }
            
            //結果を表示
            Console.WriteLine( "Result : " + CurrCalcResult.ToString() );
        }
    }
    
[/code]


CC BY-SA 4.0
2023-11-02T04:36:55.873
96650
2023-11-02T04:43:47.367
2023-11-02T04:43:47.367
52236
52236
96646
answer


ご参考までに

[code]

    using System;
    using System.Linq;
    using System.Collections.Generic;
    
    class Program
    {
        // OPE 定義
        delegate int OPE(int lhs, int rhs);
    
        static void Main(string[] args) {
            // 演算を定義
            OPE Plus = (int lhs, int rhs) => lhs + rhs;
            OPE Minus = (int lhs, int rhs) => lhs - rhs;
            OPE Mul = (int lhs, int rhs) => lhs * rhs;
            OPE Div = (int lhs, int rhs) => lhs / rhs;
            // KEY:演算記号 VALUE:演算 の辞書を定義
            var dic = new Dictionary<char, OPE>() {
                {'+', Plus},{'-', Minus},{'x', Mul},{'*', Mul},{'/', Div},
            };
            // 数式入力
            var formula = Console.ReadLine();
            // オペランド抽出
            var terms = formula.Split(dic.Keys.ToArray());
            // idx:formula のインデックス（演算記号位置用）
            int idx = 0;
            // val:計算結果格納用変数（最初のオペランド値で初期化）
            int val = int.Parse(terms[0]);
            // 数式を最初から演算記号毎に演算していく
            for (int i = 0; i + 1 < terms.Length; i++) {
                idx += terms[i].Length;  // 演算記号位置設定
                val = dic[formula[idx++]](val, int.Parse(terms[i + 1])); // 演算実行
            }
            Console.WriteLine(val);  // 計算結果出力
            Console.ReadKey();
        }
    }
    
[/code]


CC BY-SA 4.0
2023-11-02T23:09:37.587
96656
2023-11-02T23:09:37.587
41756
96646
answer