加入
2月8日,2021年
消息
14
编程经验
Beginner
你好,

我在过去的6天里一直在努力让这个BMI计算器致力于我的要求,而是没有成功。我甚至不能从中得到一个值。我不知道在哪里开始寻找问题,因为我一直在看几个小时,一直看出不同的指南,但我不接近获得这个工作。这个论坛是我的最后一个手段,因为它已经与以前的项目一起。

正如我不知道在哪里发布的谎言发布我的代码和一些图像希望你们中的一个可以帮助我弄清楚问题所在的位置。我不希望你把一个工作代码发给我作为响应,但帮助我弄清楚问题的位置以及我应该使用什么方法来解决它。

form1.cs [设计]
1614906428176.png.

Form1.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Assignment_3_New
{
    public partial class Form1 : Form
    {
        private BMICalculator bmiCalc = new BMICalculator();
        public Form1()
        {
            InitializeComponent();
            InitializeGUI();

        }
        private void InitializeGUI()
        {
            this.Text = "The Body Mass Calculator by [Name]";

            //input
            radbtnMetric.Checked = true;
            lblHeight.Text = "Height (cm)";
            lblWeight.Text = "Weight (kg)";

            //output
            txtHeight.Text = string.Empty;
            txtWeight.Text = string.Empty;
        }

        private void DisplayResults()
        {
            lblBMICalculated.Text = bmiCalc.CalculateBMI().ToString("f2");
            lblWeightCatCalculated.Text = bmiCalc.BMIWeightCategory().ToString();
            grpResult.Text = "Results for " + bmiCalc.GetName();
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }
        //********************************************* Read Weight *********************************************
        #region Read Weight
        private bool ReadWeight()
        {
            double outValue = 0;
            bool ok = double.TryParse(txtWeight.Text, out outValue);

            if (ok)
            {
                if (outValue > 0)
                {
                    bmiCalc.SetWeight(outValue);
                }
                else
                    ok = false;
            }
            if (!ok)           
                MessageBox.Show("Invalid weight value!", "Error");

            return ok;
            
        }
        #endregion
        private void textBox3_TextChanged(object sender, EventArgs e)   //Weight
        {

        }

        private void textBox1_TextChanged(object sender, EventArgs e)   //Name
        {
            bmiCalc.SetName(txtName.Text);
        }

        //********************************************* Read Height *********************************************
        #region Read Height
        private bool ReadHeight()
        {
            double outValue = 0;
            bool ok = double.TryParse(txtHeight.Text, out outValue);

            if (ok)
            {
                if (outValue > 0)
                {
                    if (bmiCalc.GetUnit() == UnitTypes.American)
                    {
                        bmiCalc.SetHeight(outValue * 12.00);
                    }
                    else
                    {
                        bmiCalc.SetHeight(outValue / 100.0);
                    }
                }
                else
                    ok = false;
            }
            if (!ok)
                MessageBox.Show("Invalid height value!", "Error");

            return ok;
        }

        #endregion
        private void textBox2_TextChanged(object sender, EventArgs e)   //Height
        {

        }

        private void textBox5_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBox4_TextChanged(object sender, EventArgs e)
        {

        }

        private void lblWeightCat_Click(object sender, EventArgs e)
        {

        }

        private void lblBMI_Click(object sender, EventArgs e)
        {

        }

        private void grpResult_Enter(object sender, EventArgs e)
        {

        }
        //********************************************* Read Input BMI *********************************************
        #region Read Input BMI
        /*private bool ReadInputBMI()
        {
            bool CalculateClicked = false;

            btnCalculate.Click
        }*/
        #endregion
        private void btnCalculate_Click(object sender, EventArgs e)
        {
            /*bool ok = ReadInputBMI();

            if (ok)
            {
                DisplayResults();
            }*/
            DisplayResults();

        }

        private void grpUnit_Enter(object sender, EventArgs e)
        {

        }

        private void radbtnUs_CheckedChanged(object sender, EventArgs e)
        {
            if (radbtnUs.Checked)
            {
                lblHeight.Text = "Height (inch)";
                lblWeight.Text = "Weight (lbs)";
                bmiCalc.SetUnit(UnitTypes.American);
            }
        }

        private void radbtnMetric_CheckedChanged(object sender, EventArgs e)
        {
            if (radbtnMetric.Checked)
            {
                lblHeight.Text = "Height (cm)";
                lblWeight.Text = "Weight (kg)";
                bmiCalc.SetUnit(UnitTypes.Metric);
            }
        }

        private void WeightCat_Click(object sender, EventArgs e)
        {

        }

        private void lblBMICalculated_Click(object sender, EventArgs e)
        {

        }
    }
}
BMICalculator.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Assignment_3_New
{
    class BMICalculator
    {
        private string name = "No name";
        private double height = 0;
        private double weight = 0;
        private UnitTypes unit;

        // ********************************************* Getters *********************************************
        #region Getters
        public string GetName()
        {
            return name;
        }

        public double GetHeight()
        {
            return height;
        }

        public double GetWeight()
        {
            return weight;
        }

        public UnitTypes GetUnit()
        {
            return unit;
        }
        #endregion
        // ********************************************* Setters *********************************************
        #region Setters
        public void SetName(string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                name = value;
            }
        }

        public void SetHeight(double value)
        {
            if(value >= 0)
            {
                height = value;
            }
        }

        public void SetWeight(double value)
        {
            if(value >= 0)
            {
                weight = value;
            }
        }

        public void SetUnit(UnitTypes value)
        {
            unit = value;
        }
        #endregion
        //********************************************* Calculate BMI *********************************************
        #region Calculate BMI
        public double CalculateBMI()
        {
            double bmi = 0.00;
            if(unit == UnitTypes.American)
            {
                 bmi = 703 * weight / (height * height);
            }
            else if(unit == UnitTypes.Metric)
            {
                 bmi = weight / (height * height);
            }
            return bmi;
        }
        #endregion
        //********************************************* BMI Weight Category *********************************************
        #region BMI Weight Category
        public string BMIWeightCategory()
        {
            double bmi = CalculateBMI();
            string stringout = string.Empty;
            if (bmi >= 30)
                stringout = "Obesity";
            else if (bmi < 30)
                stringout = "Overweight";
            else if (bmi < 25 && bmi >= 18.5)
                stringout = "Normal Weight";
            else
                stringout = "Underweight";

            return stringout;
        }
        #endregion
      
    }
}
UnitTypes.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Assignment_3_New
{
    enum UnitTypes
    {
        Metric,
        American
    }
}

我意识到这是一个大问,但我觉得我已经用尽了我所有的其他选择,因为我必须看看帮助imo不是非常好的,并且我一直试图用帮助解决这个问题过去6天无济于事。

运行程序时的结果
1614906689529.png.

无论在身高或重量上输入"Weight Category"总是“体重不足”"BMI"总是符号是什么。即使我尝试使用Double.trymars以制作MessageBox弹出窗口,当高度和重量无效(非数字)时,度量标准和帝国(美国)单位的结果是相同的。

要结束这个长篇帖子,id就是真的感谢那些已经读过的人这一切都是对我来说至少这是一个很多代码,因为我说这是我最后的手段,我对此的任何意见都非常胜利。我不是在寻找讲义merley帮助在哪里开始,因为当我用我的眼睛看代码时,我觉得它应该工作,但那么再次是新的,结果表明它不起作用所以你......

此致
 
Solution
当前问题是,只要我输入无效号码(无需按下按钮),我就会提示使用MessageBox,我不想要此。我想要只能提示我输入了无效值和"calculate button" has been pressed.
That is pretty much exactly backwards and the code I provided will prompt the user when they try to leave a control that contains invalid data. As I said, it is better UX to not even allow the user to click the Button if it can't possibly do anything useful.

That said, if you really want to do it backwards, i.e. not prompt the user unless they click the Button, then why are you executing code...

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,731
地点
悉尼,澳大利亚
编程经验
10+
有路,waaaaaaaayyyyyyyyyyyyyyyyyyyyyyyy在那里。您已抛弃每一位代码的事实表明您没有合理的努力隔离问题。您的整个应用程序不是一个问题。将整个过程中的整个过程分成较小的零件,并在隔离中处理每个部分。至少,您可以将其分解为获取用户输入,执行计算和显示输出。那些是三个完全独立的操作,可以如此治疗。您可以编写代码以使用Canded数据执行计算,并查看是否有效。如果它确实,计算不是问题,并且基本上与我们无关紧要。如果它不起作用,那么输入和输出部件是无关紧要的,您需要在计算中工作,将其打入较小的部分并调试代码以确定其行为的行为不符合您的期望。这就是软件开发是什么,这就是你需要在这里做的事情。一旦您隔离了问题的方式和方式,您只能向我们提供与此相关的信息,这甚至可能涉及将相关代码复制到完全单独的测试程序。这基本上是解决问题的101(划分和征服),并不具体对编程,但对编程至关重要。尝试一下,当你缩小一点(实际上很多)时,请回复我们。
 
加入
2月8日,2021年
消息
14
编程经验
Beginner
编辑:如果有人在我编辑解决方案之前有人有足够的时间阅读这一点,我很抱歉,请更新
如果您在编辑之前看到了这篇文章,请忽略
 
Last edited:

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,903
地点
切萨皮克,va.
编程经验
10+
我可能需要仔细看看上面的代码在更大的屏幕上,但只需扫描手机上的代码,它看起来不是实际上从文本框中拉出值并将它们传递到计算器中。它看起来像计算器刚才要求直接计算它目前的任何值。

That would explain why the results never change, but I don't know why you would get the strange square boxes for the computed BMI. Calling ToSting("f2") on any number should still result in a string that has printable glyphs. Those square boxes usually indicate glyphs that are not present in the selected font for the TextBox.
 
加入
2月8日,2021年
消息
14
编程经验
Beginner
我做了一些工作并设法让它打印正确的值,就像你所说的那样,我从来没有提取我现在已经修复的价值,而是在修复我现在有另一个问题我无法修复,因为我无法修复。 m使用trypars方法只能解析数字,如果没有显示一个消息框,只要我输入一个数字字符串,它会弹出错误框,我只想"calculate"不是每当我偶然放入数字以外的东西时按下按钮。例如,当我尝试擦除我输入的高度并且我来到最后一个(175和我删除5和7)所以当我来"1"然后按BackSpace错误消息提示与任何None Numer编号(ABCDEFG ...)提示相同,我只希望它在按下计算按钮时提示错误框,并且TRYPARSS失败。所以我创建了一个bool来检查按钮是否被按下:

ReadCalculate:
        private bool ReadInputBMI = false;

        private void btnCalculate_Click(object sender, EventArgs e)
        {
            ReadInputBMI = true;

            DisplayResults();
            ReadInputBMI = false;


        }

然后我尝试在try.parse方法之前实现它,但每当我尝试并这样做,它会突破我的代码,我的输入永远不会被设置。
如果要检查按钮,请按下:
         private void ReadWeight()
                {
                    if(ReadInputBMI == true)
                    {
                        double outValue = 0;
                        bool ok = double.TryParse(txtWeight.Text, out outValue);

                        if (ok)
                        {
                            if (outValue > 0)
                            {
                                bmiCalc.SetWeight(outValue);
                            }
                            else
                                ok = false;
                        }
                        if (!ok)
                            MessageBox.Show("Invalid weight value!", "Error");
                    }


                }
        private void textBox3_TextChanged(object sender, EventArgs e)   //Weight
        {
            ReadWeight();
        }

我已经调试了,我可以确认我的号码我输入永远不会被设置,但我看不到为什么或我将如何进行,做另一种方法来检查按钮是否已按下然后运行一次,然后设置一次按钮再次单击为false
 
Last edited:

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,731
地点
悉尼,澳大利亚
编程经验
10+
Your explanation is barely coherent so I'm going to ignore what you're doing and explain how I think it should be done. A BMI calculation is based on height and weight so it doesn't make sense to allow the user to even try to calculate a BMI if they haven't entered a height and a weight. In that case, the Button should be disabled unless valid data has been entered. The proper way to validate in WinForms is to handle the Validating event of a control and set e.Cancel to true if the data fails validation. That way, the control will refuse to lose focus as long as it contains invalid data. You can also handle the Validated event to execute code only when control passes validation. In this case, I would do something like this:
C#:
private void textBoxes_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
    // Get the TextBox that raised the event.
    var tb = (TextBox)sender;

    // Check whether the control contains text and that that text is a valid representation of a number.
    if (tb.TextLength > 0 && !double.TryParse(tb.Text, out _))
    {
        // Validation has failed.

        // Highlight the input.
        tb.HideSelection = false;
        tb.SelectAll();

        // Prompt the user with specific information from the TextBox being validated.
        MessageBox.Show($"Please enter a valid {tb.Tag}");

        // Remove highlight without focus.
        tb.HideSelection = true;

        // Don't allow the control to lose focus.
        e.Cancel = true;
    }
}

private void textBoxes_Validated(object sender, EventArgs e)
{
    // We know that the current TextBox is valid. Enable the button if and only if both are valid.
    // This assumes that there are no other [ICODE]TextBoxes[/ICODE] on the form. If there are, use some other method to isolate them, e.g. a [ICODE]Panel[/ICODE] or an explicit list.
    button1.Enabled = Controls.OfType<TextBox>().All(tb => tb.TextLength > 0);
}

private void button1_Click(object sender, EventArgs e)
{
    // The Button must be enabled so we know that the data is valid.
    var height = double.Parse(textBox1.Text);
    var weight = double.Parse(textBox2.Text);

    // Use data here.
}
Note that one method is used to handle an event for both TextBoxes because the code is the same in each case. For the prompt displayed when validation fails, the name of the value being entered in stored in the control itself and retrieved from there. Each TextBox will refuse to lose focus if it contains invalid data. They will lose focus if they are blank but the Button will not be enabled in that case. The Button is enabled if and only if both TextBoxes contain valid data so, when it is clicked, you can assume that the data is valid. Note that validation only occurs when the user tries to navigate away from a TextBox, so the user can enter and delete whatever text they like before that. Note that the Button should be disabled by default, because both TextBoxes do not contain valida data by default.

我还应该指出这里发生的事情:
C#:
if (tb.TextLength > 0 && !double.TryParse(tb.Text, out _))
下划线字符有什么被称为丢弃物。它基本上是一个你永远不会使用的变量。你可以这样做:
C#:
if (tb.TextLength > 0 && !double.TryParse(tb.Text, out var value))
或这个:
C#:
double value;

if (tb.TextLength > 0 && !double.TryParse(tb.Text, out value))
but that makes your code more verbose for no reason. Anyone looking at that will see you set that value variable and may wonder whether you forgot to use it. By using a discard, you are implicitly stating that you specifically intend not to use the value it receives. Discards are a fairly recent addition to C# syntax.
 
Last edited:
加入
2月8日,2021年
消息
14
编程经验
Beginner
谢谢jmcilhinney,这对我来说都是新的,经过代码,试着了解它,谢谢你的意见和解释。它与我认为它可以工作的方式非常不同。我之前只在Arduino中完成了C ++编码。对不起,如果我的解释是不可理解的,因为在我自己的脑海里,我几乎无法理解我想要解释的东西。但我会尽力给它另一个拍摄,因为我认为这对我来说有点过于高级,我觉得它仍然应该与我所遇到的东西一样。

当前问题是,只要我输入无效号码(无需按下按钮),我就会提示使用MessageBox,我不想要此。我想要只能提示我输入了无效值和"calculate button"已被按下。我提示有一个无效的数字,我需要更改它,然后我可以再次尝试按下计算,如果所有数字都有效(它们通过try.parse)然后显示BMI。

我明白这可能是一个"worse"与您在上面写的验证相比,编写代码的方法,但它只是在我的脑海中有意义,我只是无法进入代码。此外,我应该提到我正在参加C#的课程,但是在我的课程中使用Covid继续拥有超过350名学生的课程,教师非常有限,因此我正在使用这个论坛来帮助我。我以前指出的是我不是在寻找讲义,因为我实际上正在努力学习和理解代码,而是说我需要满足某些要求,我觉得并使用我们尚未覆盖的验证等一些要求不会是我的最佳行动方案。如果可以在我所描述的情况下可以创建代码,我希望您能理解,可以愿意回复我。对不起,如果我的写作技巧复杂的东西是早上6点,我还没有睡觉。 ZZZZ.
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,731
地点
悉尼,澳大利亚
编程经验
10+
当前问题是,只要我输入无效号码(无需按下按钮),我就会提示使用MessageBox,我不想要此。我想要只能提示我输入了无效值和"calculate button" has been pressed.
That is pretty much exactly backwards and the code I provided will prompt the user when they try to leave a control that contains invalid data. As I said, it is better UX to not even allow the user to click the Button if it can't possibly do anything useful.

That said, if you really want to do it backwards, i.e. not prompt the user unless they click the Button, then why are you executing code that will prompt the user any time other than when the user clicks the Button? If the only time you want to validate the input and perform the calculation is when the user clicks the Button then the only place you should be executing code that validates the input and performs the calculation is in the Click event handler of the Button. Why are you executing any code at all on the TextChanged event of a TextBox?

这是为什么你不尝试从头到来的想法到代码的一个例子。在写任何代码之前,您应该首先锻炼逻辑。如果这需要你用笔和纸张写下东西,然后是它。一旦您认为您有声音逻辑,那么您就会编写代码以具体地实现该逻辑。您始终有用于将代码进行比较。如果某些代码不起作用,那么您可以始终指向特定的逻辑,即该代码应该实施,我们可以告诉您为什么没有。如果您只有随机代码无缘无故地解释,我们应该如何告诉您应该是什么样子?必须有一个特定的目的是要查看代码的正确方法。
 
解决方案

约翰

C#论坛主持人
工作人员
加入
2011年4月23日
消息
1,160
地点
挪威
编程经验
10+
您的要求是否允许您使用适当的输入来输入? NumericUpdown控件就像一个文本框,但如果使用您可以跳过手动验证和输入的转换,则只能使用数字输入。
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,731
地点
悉尼,澳大利亚
编程经验
10+
您的要求是否允许您使用适当的输入来输入? NumericUpdown控件就像一个文本框,但如果使用您可以跳过手动验证和输入的转换,则只能使用数字输入。
One additional advantage of using a NumericUpDown is that you get to specify a range of allowed values. That means that you can easily exclude negative values, which are obviously meaningless for such data. You might also set the minimum a bit above zero, e.g. do BMI calculations really make sense for someone shorter than 50 cm?
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,731
地点
悉尼,澳大利亚
编程经验
10+
对不起,如果我在这次谈话中使自己听起来很愚蠢,但我会看看你发给我的验证代码,因为我了解如何更逻辑和有效地做那样的事情。
没有必要道歉。只是从你的错误中吸取教训。当他们开始外出时,大多数人往往是非常不合逻辑的和不系统的,因为结果让自己变得更加困难。我们都希望写代码,因为这是性感的部分,但如果我们不知道它应该做什么,我们写的代码往往朝着垃圾,很少有人真正花时间开始锻炼。你越早了解那课,对你来说更好。
 
最佳 底部