danydodson
danydodson

Reputation: 21

class constructor that calculates input using C#

Hello and thanks for checking my post. New to C# and Oop in general. Learning has been smooth so far but I'm running into issues when I try to create (and call) a constructor that calculates data input by user.

If possible: I would like to create 3 classes.

MainDisplay class that displays information and gets user input.

BMIBlueprint class that "only" does the calculation for bmi.

BFPBlueprint class that calculates bfp (needs to use bmi total).

I've accomplished this task using one class, But I'd really like to know/comprehend how to do this using multiple classes. I've watched/read/studied every source I could find over the past 2 weeks before posing this but I haven't been able to make sense of creating a constructor that does a calculation, then calling it in main to use user input data for the variables..

The very bottom code is how I've done it in one class (but not quite finished). You can disregard all of that though, I just don't want to come off like I'm completely hopeless or trying to cheat.

This is what I have so far. The first is my BMIBlueprint class that I created just to use as a calculator for bmi based on input from the user, which I plan to call on in my MainClass. also, this is about my 200th different version while trying to make it work and It's probably very far from what it could/should actually look like...

class BMIBlueprint {

    public double bmiBefore;
    public double bmiAFter;

    public BMIBlueprint() { }

    public BMIBlueprint(double height, double weight) {

        bmiBefore = (height * height) * weight;
    }

    public BMIBlueprint(double bmiConst) {

        bmiAFter = bmiBefore * 703;

    }
}

How do I "use" the above class constructor to calculate what the user inputs in my main class ? or am I way off track with it ? My main class is below where I ask for user input then place those values in my constructor.

static void Main() {

    Write("Enter weight: ");
    double weight = double.Parse(ReadLine());

    Write("Enter height: ");
    double height = double.Parse(ReadLine());

    BMIBlueprint calcBmi = new BMIBlueprint(newBmiOne, newBmiTwo);

    //then display after calculated
    WriteLine("The finished cal should be shown here: {0:N2}", calcBmi);

I've tried this many many different ways but this is where I'm at right now; If anyone has the time or kindness to post what the code should be with a couple notes so I could study it, would be absolutely great, but also probably asking for too much. If not any kind of help/advice/metaphors/analogies would be greatly appreciated.

The code below is where I did it all in one class -almost done, but is not part of the question and should be ignored.

static void Main() {

    EntranceBlueprint entrance = new EntranceBlueprint();

    WriteLine(entrance);

    BMIBlueprint bmiCalculator = new BMIBlueprint();

    Write("First, enter your weight in lbs: ");
    double newWeight = double.Parse(bmiCalculator.weight = ReadLine());

    Write("\nGreat, now enter your height in inches: ");
    double newHeight = double.Parse(bmiCalculator.height = ReadLine());

    bmiCalculator.bmiVar = 703;
    double totalBmi = ((newWeight * bmiCalculator.bmiVar) / 
                      (newHeight * newHeight));

    WriteLine("\nPerfect! Your bmi is: {0:N2}. With just a few more 
              inputs we'll have your bfp. ", +totalBmi);

    Write("\npress any key to continue");
        ReadKey();

    BFPBlueprint bfpCalculator = new BFPBlueprint();              

    Write("According to _ your bfp is more accurate because it takes     
    into account your age and gender. So enter your age first: ");

    double newAge = double.Parse(bfpCalculator.age = ReadLine());
    Write("\nGreat, now enter your sex, like this (male or female): ");

    string newSex = ReadLine();

        if (newAge >= 13 && newSex.ToLower() == "male") {
            double totalAdultMale = 
                (1.20 * totalBmi) - (0.23 * newAge) - (10.8 * 1) - 5.4;
                Write("\nYour bfp is: {0:N2} ", totalAdultMale);
                    if (totalAdultMale > 1 && totalAdultMale < 13)
                    Catagories(); }

        else if (newAge <= 12 && newSex.ToLower() == "male") {
            double totalYouthMaleBfp = 
            (1.51 * totalBmi) - (0.70 *newAge) - (3.6 * 1) + 1.4;
            Write("Perfect! Your bfp is: {0:N2}",

        else if (newAge >= 13 && newSex.ToLower() == "female") {
            double totalAdultFemaleBfp = 
            (1.20 * totalBmi) - (0.23 * newAge) - (10.8 * 0) - 5.4;
            Write("Perfect! Your bfp is: {0:N2} ",totalAdultFemaleBfp); }


        else if (newAge <= 12 && newSex.ToLower() == "female") {
            double totalYouthFemaleBfp = 
            (1.51 * totalBmi) - (0.70 * newAge) - (3.6 * 0) + 1.4;
            Write("Perfect! Your bfp is {0:N2} ", totalYouthFemaleBfp); }

        else { Write("\nYou must have typed something wrong, Try 
               again"); }

        ReadKey();

Upvotes: 1

Views: 5846

Answers (4)

C. McCoy IV
C. McCoy IV

Reputation: 897

Here's a more advanced example of an OOP approach, complete with input validation. Note, you may need to modify Person based on the exact functionality you want to have. The calculators/history tracking may be objects themselves. I simply showed how the excerpt you posted could be written in a C#/OOP fashion.

using System;
using System.Linq;

namespace BMI_StackOverflow
{
    class Program
    {
        static void Main(string[] args)
        {
            PersonValidator inputValidator = new PersonValidator();
            Person person = new Person();
            person.Weight = CollectUserInput<double>("First, enter your weight in lbs: ",
                inputValidator.IsValidWeight, "Please enter a positive number: ");
            person.Height = CollectUserInput<double>("\nGreat, now enter your height in inches: ",
                inputValidator.IsValidHeight, "Please enter a positive number: ");

            double bmi = person.GetBmi();
            Console.WriteLine("\nPerfect! Your bmi is: {0:N2}. With just a few more inputs we'll have your bfp. ", +bmi);
            Console.Write("\nPress any key to continue");
            Console.ReadKey();

            person.Age = CollectUserInput<int>("According to _ your bfp is more accurate because it takes into account your age and gender. So enter your age first: ",
                inputValidator.IsValidAge, "Please enter a positive, non-decimal number.");
            string sex = CollectUserInput<string>("\nGreat, now enter your sex, like this (male or female): ",
                inputValidator.IsValidSex, $"That sex is not recognized. Please input one of: {string.Join(", ", Enum.GetNames(typeof(Person.BiologicalSex)).Select(x => x.ToLower()))}");
            person.Sex = inputValidator.ParseSex(sex).Value;

            double bfp = person.GetBfp();
            Console.WriteLine("Perfect! Your bfp is {0:N2} ", +bfp);
            Console.ReadKey();
        }

        /// <summary>
        /// Prompts user for console input; reprompts untils correct type recieved. Returns input as specified type.
        /// </summary>
        /// <param name="message">Display message to prompt user for input.</param>
        private static T CollectUserInput<T>(string message = null)
        {
            if (message != null)
            {
                Console.WriteLine(message);
            }
            while (true)
            {
                string rawInput = Console.ReadLine();
                try
                {
                    return (T)Convert.ChangeType(rawInput, typeof(T));
                }
                catch
                {
                    Console.WriteLine($"Please input a response of type: {typeof(T).ToString()}");
                }
            }
        }

        /// <summary>
        /// Prompts user for console input; reprompts untils correct type recieved. Returns input as specified type.
        /// </summary>
        /// <param name="message">Display message to prompt user for input.</param>
        /// <param name="validate">Prompt user to reenter input until it passes this validation function.</param>
        /// <param name="validationFailureMessage">Message displayed to user after each validation failure.</param>
        private static T CollectUserInput<T>(string message, Func<T, bool> validate, string validationFailureMessage = null)
        {
            var input = CollectUserInput<T>(message);
            bool isValid = validate(input);
            while (!isValid)
            {
                Console.WriteLine(validationFailureMessage);
                input = CollectUserInput<T>();
                isValid = validate(input);
            }
            return input;
        }
    }

    public class Person
    {
        public double Weight { get; set; }
        public double Height { get; set; }
        public int Age { get; set; }
        public BiologicalSex Sex { get; set; }

        private const int bmiVar = 703;

        public double GetBmi()
        {
            return ((Weight * bmiVar) /
                   (Math.Pow(Height, 2)));
        }

        public double GetBfp()
        {
            double bmi = GetBmi();
            switch (Sex)
            {
                case BiologicalSex.MALE:
                    if (Age >= 13)
                    {
                        return (1.20 * bmi) - (0.23 * Age) - (10.8 * 1) - 5.4;
                    }
                    return (1.51 * bmi) - (0.70 * Age) - (3.6 * 1) + 1.4;
                case BiologicalSex.FEMALE:
                    if (Age >= 13)
                    {
                        return (1.20 * bmi) - (0.23 * Age) - (10.8 * 0) - 5.4;
                    }
                    return (1.51 * bmi) - (0.70 * Age) - (3.6 * 0) + 1.4;
                default:
                    throw new Exception($"No BFP calculation rule for sex: {Sex}");
            }
        }

        public enum BiologicalSex
        {
            MALE,
            FEMALE
        }
    }

    public class PersonValidator
    {
        public bool IsValidWeight(double weight)
        {
            return weight >= 0;
        }

        public bool IsValidHeight(double height)
        {
            return height >= 0;
        }

        public bool IsValidAge(int age)
        {
            return age >= 0;
        }

        public bool IsValidSex(string sex)
        {
            return ParseSex(sex) != null;
        }

        /// <summary>
        /// Attempts to parse sex from string. Returns null on failure.
        /// </summary>
        public Person.BiologicalSex? ParseSex(string sex)
        {
            int temp;
            bool isNumber = int.TryParse(sex, out temp);
            if (isNumber)
            {
                return null;
            }
            try
            {
                return (Person.BiologicalSex)Enum.Parse(typeof(Person.BiologicalSex), sex, ignoreCase: true);
            }
            catch (ArgumentException ex)
            {
                return null;
            }
        }
    }
}

Upvotes: 0

Jeff_Liu
Jeff_Liu

Reputation: 1

your problem is this code:

WriteLine("The finished cal should be shown here: {0:N2}", calcBmi);

The WriteLine function will not take calcBmi, which is a BMIBlueprint, as a parameter. Also {0:N2} is a wrong syntax. You could do this however:

WriteLine("The finished cal.bmiBefore should be shown here: {0}", calcBmi.bmiBefore);
WriteLine("The finished cal.bmiBefore should be shown here: {0}", calcBmi.bmiBefore);

Upvotes: 0

Chris Hatfield
Chris Hatfield

Reputation: 26

You can go about this a number of ways, but from a pure OOP standpoint, using a class is a good idea.

Build your object using the constructor by initializing the members of your class through your construction parameters:

    public class BMIBlueprint {

    private const double BMI_CONST = 703;

    public double Height {get; private set;} 
    public double Weight {get; private set;}


    public BMIBlueprint(double height, double weight) {

        this.Height = height;
        this.Weight = weight;
    //instead of passing in variables to perform a function in your constructor
    //use them to initialize your member variables
    //bmiBefore = (height * height) * weight; 
    }

    public double GetBMIBefore(){

        double bmiBefore = (this.Height * this.Height) * this.Weight;
        return bmiBefore;
    }

    public double GetBMIAfter() {

        double bmiBefore = this.GetBMIBefore();
        double bmiAfter = bmiBefore * BMI_CONST;
        return bmiAfter;
    }

Then call the method(s) contained in this class to do your calculation(s) from the object:

static void Main() {
    Write("Enter weight: ");
    double weight = double.Parse(ReadLine());

    Write("Enter height: ");
    double height = double.Parse(ReadLine());

    BFPBlueprint bmiCalculator = new BFPBlueprint(height, weight);

    double bmiBefore = bmiCalculator.GetBMIBefore();
    double bmiAfter = bmiCalculator.GetBMIAfter();
    //etc...

The point here is to encapsulate all your bmi calculation logic and values in one class so it is easy to use.

OR

You could instead use a static class that implements these methods and doesn't contain any member variables:

public static class BmiCalculator
{
    private const double BMI_CONST = 703;

    public double static GetNewBMI(double height, double weight)
    {
        double newBMI = (height * height) * weight;
        return newBMI;
    }

    public double GetAdjustedBMI(double oldBMI) 
    {
        double adjustedBMI = oldBMI * BMI_CONST;
        return adjustedBMI;
    }

To implement in your Main:

static void Main() {
    Write("Enter weight: ");
    double weight = double.Parse(ReadLine());

    Write("Enter height: ");
    double height = double.Parse(ReadLine());

    double bmiBefore = BmiCalculator.GetNewBMI(height, weight);
    double bmiAfter = BmiCalculator.GetAdjustedBMI(bmiBefore);
    //etc...

Upvotes: 1

Thejaka Maldeniya
Thejaka Maldeniya

Reputation: 1076

Here's a simple example:

using System;

namespace ConsoleApplication
{
    class BMIBlueprint
    {
        private const int BMI_VAR = 703;

        public double Bmi { get; private set; }

        public BMIBlueprint(double height, double weight)
        {
            Bmi = height * height * weight;
        }

        public void Adjust()
        {
            Bmi *= BMI_VAR;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Enter weight: ");
            double weight = double.Parse(Console.ReadLine());

            Console.Write("Enter height: ");
            double height = double.Parse(Console.ReadLine());

            BMIBlueprint calcBmi = new BMIBlueprint(height, weight);

            calcBmi.Adjust();

            //then display after calculated
            Console.WriteLine("The finished cal should be shown here: {0:N2}", calcBmi.Bmi);

            Console.Write("\nPress any key...");
            Console.ReadKey();
        }
    }
}

Upvotes: 0

Related Questions