有时它像 2+2*2 = 6 一样工作但是当 5*5*5=only 25 这里的代码真的不知道错误在哪里,如果有人可以帮助因为我只是一个初学者我正在使用 2 个列表来存储数字和操作

namespace kalkulator
{
    public partial class Form1 : Form
    {
        List<double> vnos = new List<double>();
        List<char> operacije = new List<char>();

        public Form1()
        {
            InitializeComponent();
            reset();
        }

        private void button_Click(object sender, EventArgs e)
        {
            Button vnos = (Button)sender;
            if (textBox1.Text == "0" && textBox1.Text != null)
                textBox1.Text = vnos.Text;
            else
                textBox1.Text += vnos.Text;
        }

        private void operacija_Click(object sender, EventArgs e)
        {
            try
            {
                vnos.Add(Convert.ToDouble(textBox1.Text));
                vse.Text = vse.Text + textBox1.Text;
                textBox1.Text = "";
                Button button = (Button)sender;
                char gumb = Convert.ToChar(button.Text);
                switch (gumb)
                {
                    case '+':
                        operacije.Add('+');
                        vse.Text = vse.Text + '+';
                        break;
                    case '-':
                        operacije.Add('-');
                        vse.Text = vse.Text + '-';
                        break;
                    case '*':
                        operacije.Add('*');
                        vse.Text = vse.Text + '*';
                        break;
                    case '/':
                        operacije.Add('/');
                        vse.Text = vse.Text + '/';
                        break;
                }
            }
            catch(FormatException)
            {
                MessageBox.Show("Napačni format");
            }
            catch (OverflowException)
            {
                MessageBox.Show("Preveliko število");
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void clear_Click(object sender, EventArgs e)
        {
            reset();
        }

        private void reset()
        {
            vse.Text = "";
            textBox1.Text = "";
            vnos.Clear();
            operacije.Clear();
        }

        private void enter_Click(object sender, EventArgs e)
        {
            try
            {
                vnos.Add(Convert.ToDouble(textBox1.Text));
                vse.Text = vse.Text + textBox1.Text;
                textBox1.Text = "";
                vnos.Add(0);
                operacije.Add('.');
                for (int i = 0; i < vnos.Count - 1; i++)
                {
                    if (operacije[i] == '*')
                    {
                        vnos[i] = vnos[i] * vnos[i + 1];
                        vnos.RemoveAt(i + 1);
                        operacije.RemoveAt(i);
                    }
                    else if (operacije[i] == '/')
                    {
                        vnos[i] = vnos[i] / vnos[i + 1];
                        vnos.RemoveAt(i + 1);
                        operacije.RemoveAt(i);
                    }
                }
                for (int i = 0; i < vnos.Count - 1; i++)
                {
                    if (operacije[i] == '+')
                    {
                        vnos[i] = vnos[i] + vnos[i + 1];
                        vnos.RemoveAt(i + 1);
                        operacije.RemoveAt(i);
                    }
                    else if (operacije[i] == '-')
                    {
                        vnos[i] = vnos[i] - vnos[i + 1];
                        vnos.RemoveAt(i + 1);
                        operacije.RemoveAt(i);
                    }
                }
                textBox1.Text = Convert.ToString(vnos[0]);
            }
            catch (FormatException)
            {
                MessageBox.Show("Napačni format");
            }
            catch (OverflowException)
            {
                MessageBox.Show("Preveliko število");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void button10_Click(object sender, EventArgs e)
        {
            textBox1.Text = textBox1.Text + ',';
        }
    }
}

最佳答案

尽管我同意这可能不是实现计算器的最佳方式,但我想我找到了为什么您的代码无法使用您目前拥有的计算正确结果的原因。

在这种特定情况下,问题与您处理运算符和操作数的方式有关。由于这是我们在处理循环和集合时最常犯的错误之一,我会回答这样您就可以继续编写代码并希望在此过程中学到一些东西。 :-)

看看从你的 enter_Click(object sender, EventArgs e) 事件处理程序复制的这个片段:

for (int i = 0; i < vnos.Count - 1; i++)
{
    if (operacije[i] == '*')
    {
        vnos[i] = vnos[i] * vnos[i + 1];
        vnos.RemoveAt(i + 1);
        operacije.RemoveAt(i);
    }
    else if (operacije[i] == '/')
    {
        vnos[i] = vnos[i] / vnos[i + 1];
        vnos.RemoveAt(i + 1);
        operacije.RemoveAt(i);
    }
}

此代码的问题在于您正在使用操作和操作数数组中的第一个标记,然后将它们从数组中删除。但问题是,当您这样做时,循环控制变量 (i) 会被 for 循环 (i++) 递增,因此您实际上会丢失一个要消耗的元素。

让我看看我是否可以说明这一点:

假设您在 UI 中按该顺序单击了以下按钮 5 * 5 * 5 =。此时你有:
vnos = [5,5,5,0]
operacije = ['*', '*', '.']

然后开始循环计算结果。我已经删除了所有的代码,只留下了相关的部分,并在下面一步一步地写了你的变量发生了什么:
for (int i = 0; i < vnos.Count - 1; i++)
{
    if (operacije[i] == '*')
    {
        vnos[i] = vnos[i] * vnos[i + 1];
        vnos.RemoveAt(i + 1);
        operacije.RemoveAt(i);
    }
}
  • 初始化 for 循环。 i 设置为 0
  • 循环条件被评估为 0 < 4 -> true 为 vnos.Count = 4 。进入循环块
  • 条件 if (operacije[i] == '*') 被评估为真,因为第一个操作是 '*'
  • 输入如果阻止
  • 第一个操作数被替换为它自己和数组中下一个的乘积 -> vnos = [25,5,5,0]
  • vnos 数组中移除下一个操作数 -> vnos = [25,5,0]
  • 当前操作从 operacije 数组中移除 -> operacije = ['*', '.']
  • 退出条件块。
  • 执行循环增量块 (i++) -> i = 1。程序流程转到步骤 #2。但我会在这里一步一步地继续。
  • 循环条件得到评估 1 < 3 -> true as vnos.Count = 3. 进入循环块
  • 问题从这里开始 : Condition if (operacije[i] == '*') 被评估为 false 因为 i = 1 并且该索引中的操作不是 '*' 而是您的最终分隔符(点 '.' )字符。
  • 条件块不再按原样执行,计算结束。

  • 这实际上是我们最常犯的错误之一,最佳实践是在循环遍历集合时不要修改它(或者如果这样做要非常小心)。事实上 foreach 和迭代器甚至不允许这样做。

    其实解决方案并没有那么复杂。从集合中删除元素后,您只需要递减循环控制变量。因此,您在欺骗循环,因为当执行增量步骤时,变量这次将指向正确的索引,因为您之前手动减少了。

    因此,对于您的情况,请注意,只需在从列表中删除操作的行添加递减运算符就足够了。更改在 operacije.RemoveAt(i--); 行中。
    for (int i = 0; i < vnos.Count - 1; i++)
    {
        if (operacije[i] == '*')
        {
            vnos[i] = vnos[i] * vnos[i + 1];
            vnos.RemoveAt(i + 1);
            operacije.RemoveAt(i--); //<----- i-- instead of i.
        }
    }
    

    请注意,您必须在所有块中进行此更改。那是在您从操作列表中删除的所有地方。

    希望这可以帮助!

    关于c# - 在我的代码中找不到错误,它是一个使用列表来存储操作和数字的计算器?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53119937/

    10-17 01:59