C# Calculator Class - c#

I was given this homework assignment, which I have been having a hard time with. The form was written and we had to write the class. Currently when I run the program my equals button does not appear to be working. I'm unsure why and I was wondering if someone could help me understand what I am missing. I believe I have written my class correctly. In my head what is going on is the calculator is calling the "currentValue" so I am constantly updating with the method I am using in my operators.
Am I in the right direction?
And why isn't my equals button calling the current value. The last time I ran this, if I typed 9 + 3 + then my display would populate with 12 and wait for me to enter the next number. So in theory why wouldn't my equals button load the answer? I believe I am calling the correct item yet I keep getting my initial entry. For instance if I typed 9 + 9 and hit = I keep getting 9.
Here is the calculator code (the part provided):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Calculator
{
public partial class frmCalculator : Form
{
public frmCalculator()
{
InitializeComponent();
}
// The following fields are used to store the value that's currently
// displayed by the calculator. displayString is a string value that's
// constructed as the user clicks numeric keys and the decimal and +/-
// key. The Convert.ToDecimal method is then used to convert this to a decimal
// field that's stored in displayValue.
private string displayString;
private decimal displayValue;
// The following bool fields are used to control numeric entry.
// newValue indicates whether the calculator is ready to receive a
// new numeric value. Once the user clicks a digit button, newValue is
// set to false. When the user clicks a button that "enters" the value,
// such as Add or Equals, newValue is set to true so the user can enter
// another value.
// decimalEntered is used to restrict the entry to a single decimal point.
// It is set to true whenever newValue is set to true, and it is set to
// false whenever the user clicks the decimal point button.
private bool newValue;
private bool decimalEntered;
private Calculator calc = new Calculator();
private void Form1_Load(object sender, System.EventArgs e)
{
displayValue = 0;
displayString = displayValue.ToString();
newValue = true;
decimalEntered = false;
}
// This method handles the 0 through 9 keys, appending the digit clicked
// to the displayString field.
private void btnNumber_Click(object sender, System.EventArgs e)
{
if (newValue)
{
displayString = "";
newValue = false;
}
displayString += ((Button)sender).Tag.ToString();
displayValue = Convert.ToDecimal(displayString);
txtDisplay.Text = displayValue.ToString();
}
// This method removes the last character from the displayString field.
private void btnBackSpace_Click(object sender, System.EventArgs e)
{
if (displayString.Length > 1)
{
displayString = displayString.Substring(0, displayString.Length - 1);
displayValue = Convert.ToDecimal(displayString);
txtDisplay.Text = displayValue.ToString();
}
else
{
displayString = "";
displayValue = 0;
txtDisplay.Text = displayValue.ToString();
}
}
private void btnClear_Click(object sender, System.EventArgs e)
{
calc.Clear();
displayString = "";
displayValue = 0;
txtDisplay.Text = displayValue.ToString();
newValue = true;
decimalEntered = false;
}
// This method appends a decimal point to the displayString field if the
// user has not already entered a decimal point.
private void btnDecimal_Click(object sender, System.EventArgs e)
{
if (newValue)
{
displayString = "0";
newValue = false;
}
if (!decimalEntered)
{
displayString += ".";
displayValue = Convert.ToDecimal(displayString);
txtDisplay.Text = displayValue.ToString();
decimalEntered = true;
}
}
private void btnSign_Click(object sender, System.EventArgs e)
{
displayValue = -displayValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnAdd_Click(object sender, System.EventArgs e)
{
calc.Add(displayValue);
newValue = true;
decimalEntered = false;
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnSubtract_Click(object sender, System.EventArgs e)
{
calc.Subtract(displayValue);
newValue = true;
decimalEntered = false;
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnMultiply_Click(object sender, System.EventArgs e)
{
calc.Multiply(displayValue);
newValue = true;
decimalEntered = false;
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnDivide_Click(object sender, System.EventArgs e)
{
calc.Divide(displayValue);
newValue = true;
decimalEntered = false;
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnSqrt_Click(object sender, System.EventArgs e)
{
calc.SquareRoot(displayValue);
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnReciprocal_Click(object sender, System.EventArgs e)
{
try
{
calc.Reciprocal(displayValue);
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
catch (DivideByZeroException)
{
displayValue = 0;
txtDisplay.Text = "Cannot divide by zero.";
newValue = true;
decimalEntered = false;
}
}
private void btnEquals_Click(object sender, System.EventArgs e)
{
try
{
if (newValue)
calc.Equals();
else
calc.Equals(displayValue);
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
newValue = true;
decimalEntered = false;
}
catch (DivideByZeroException)
{
displayValue = 0;
txtDisplay.Text = "Cannot divide by zero.";
newValue = true;
decimalEntered = false;
}
}
}
}
Here is my class (The part I wrote):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Calculator
{
public class Calculator
{
public Decimal displayValue;
public Decimal currentValue;
public void Add(Decimal displayValue)
{
currentValue += displayValue;
}
public void Subtract(Decimal displayValue)
{
currentValue -= displayValue;
}
public void Multiply(Decimal displayValue)
{
currentValue *= displayValue;
}
public void Divide(Decimal displayValue)
{
currentValue /= displayValue;
}
public void SquareRoot(Decimal displayValue)
{
currentValue = (decimal)Math.Sqrt(Convert.ToDouble(displayValue));
}
public void Reciprocal(Decimal displayValue)
{
currentValue = 1 / displayValue;
}
public decimal Equals()
{
return currentValue;
}
public void Clear()
{
currentValue = 0;
displayValue = 0;
}
public decimal CurrentValue
{
get
{
return currentValue;
}
}
}
}

In the main code, you have called the Equal() method like this:
if (newValue)
calc.Equals();
else
calc.Equals(displayValue); //Your class do not have this.
So, you should do this first
//I am not sure why you need to pass in the displayValue parameter, so I presume it would not return anything.
public void Equal(Decimal displayValue)
{
//Do the things you suppose to do
}
And for your 9 + 9 = 9 problem, it is simply because in your code, you only press your click event Add_Button for once. Make a break point at your Add() method. Then try to do like this:
9 --> press your Add_Button --> 9 --> press your Add_Button --> check your currentValue

displayValue is both a class field and a method argument. Is that your intention? You need to make this.displayValue = ... when you assign to the field argument in order to make it clear what you are doing. Currently you are overwriting the local copy of the argument and the field value is always 0.
Just delete the decimal displayValue; declaration (and from the Clear() function) and then store the displayValue outside of the class in the form.
public class Calculator
{
//public Decimal displayValue;
public Decimal currentValue;
public void Add(Decimal displayValue)
{
currentValue+=displayValue;
}
...
public void Clear()
{
currentValue=0;
//displayValue=0;
}
public decimal CurrentValue
{
get { return currentValue; }
}
}
class Program
{
static void Main(string[] args)
{
Calculator calc=new Calculator();
calc.Add(1000m);
calc.Divide(25m);
calc.Subtract(8m);
Console.WriteLine(calc.CurrentValue);
// (1000/25)-8 = 32
}
}

The main problem I see with your code is that you are only adding one of your operands, So for example 8 + 8 will always equal 8 for example.You have to do something like this ( included Add and reciprocal functions only):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Calculator
{
public class Calculator
{
public Decimal displayValue;
public Decimal currentValue;
private Decimal Operand_1;
private Decimal Operand_2;
private bool Operand_1_Added = false;
private bool Operand_2_Added = false;
private string Operation = "";
private void AddOperand(Decimal Operand)
{
if(Operand_1_Added)
{
Operand_2 = Operand;
Operand_2_Added = true;
}
else {
Operand_1 = Operand;
Operand_1_Added = true;
currentValue = Operand_1;
}
}
public void Add(Decimal Arg1)
{
this.AddOperand(Arg1);
Operation = "Addition";
}
public void Reciprocal(Decimal Arg)
{
this.AddOperand(Arg);
Operation = "Reciprocal";
}
public void Clear()
{
currentValue = 0;
displayValue = 0;
Operand_1 = 0;
Operand_2 = 0;
}
public void Equals()
{
switch(Operation)
{
case "Addition":
currentValue = Operand_1 + Operand_2;
break;
case "Reciprocal":
currentValue = 1/Operand_1;
break;
default: break;
}
}
public void Equal(Decimal displayValue)
{
currentValue = displayValue;
}
public decimal CurrentValue
{
get
{
return currentValue;
}
}
}
Haven't tested code but this should work with the form class.

Let's look at the requirement:
"The results of multipication should show no more decimal places than the result of the first number than in the second number. Example 55.5*89.68 = 4977.240"
The natural of multiplication in basic arithmetic means that this happens by default anyway. Eg. you're never going to multiply X.X by X.XX and get result X.XXXXXXX... - it just can't happen.
Formatting is therefore easy - if you need to explicitly format then format as num.ToString("#.##############") which allows for a while bunch of numbers.
You haven't outlined any requirements for Division, so I can't comment.
BTW - if you say x = 1 / 3 and y = z * x, then you are going to get a lot of numbers after the decimal place, because x is .333333333... to start with. This is within the requirement AFAICT.

Related

Undo and Redo word by word in Rich Text Box in Winforms

I've been trying to get undo and redo working in my text editor for about 3 days now. It's doing my head in.
I have a text box (named richTextBoxPrintCtrl1), which I would like to be able to undo and *redo *(word by word).
So if I click the undo button, it undoes the last word. And if I then clicked the redo button, it redoes the last word.
Could somebody help me get this working?
richTextBoxPrintCtrl1.Undo(); doesn't work very well. It deletes everything typed in the text box.
and if you type too much this error will appear
Thanks in advance for your help.
I know this question has been asked many times before, but I can't get it working using the information from the questions I've browsed here on SO. if it helps here my code
private string[] temp = new string[100];
private int index;
private int currentpostion;
public Undo()
{
index = 0;
currentpostion = 0;
}
public void Set_Text(string s)
{
temp[index] = s;
currentpostion = index;
++index;
}
public string UndoCons()
{
if (currentpostion > 0)
{
return temp[--currentpostion];
}
return null;
}
public string RedoCosns()
{
if (currentpostion < index)
{
return temp[++currentpostion];
}
return null;
}
Adding to #piedpiper's comment, you can look at the Memento design pattern (https://refactoring.guru/design-patterns/memento) which is a behavioral pattern and deals with this type of functionality.
But one way to approach this is to push every word to an array/List. You then have a with a position counter which you decrement on the undo, and then concatenate all the string in your array up to your position counter and replace all the text in your textbox with the concatenated string. The same logic applies for the redo, where you only increment the position counter.
Here is an example of how this can work.
I've used a Windows Form, RichEditBox and I disabled the 'ShortcutsEnabled' property on the RichEditBox to False.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private IList<Keys> ignoreKeys = new List<Keys> { Keys.Control, Keys.Tab, Keys.Shift, Keys.ControlKey, Keys.ShiftKey, Keys.LShiftKey, Keys.RShiftKey };
private IList<string> Words { get; set; }
private int counter = 0;
public Form1()
{
InitializeComponent();
Words = new List<string>();
}
private void richTextBox1_KeyUp(object sender, KeyEventArgs e)
{
if (e.Control)
{
if (e.KeyCode == Keys.Z)
{
counter--;
}
if (e.KeyCode == Keys.Y)
{
counter++;
}
richTextBox1.Text = String.Join(" ", Words.Take(counter));
}
else if (!ignoreKeys.Any(ignoreKey => ignoreKey == e.KeyCode))
{
Words = richTextBox1.Text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
counter = Words.Count;
}
}
}
}
I have found a way. I hope this end all the other questions. the code that I
have now is working :
public class Operation
{
private static List<string> _txt_list = new List<string>() { "" };
private static int Position { get; set; }
public void ChangeText(string txt)
{
if (_txt_list.Count < 100)
{
_txt_list.Add(txt);
//a 0
//al 1
//ali 2
}
else
{
for (int i = 0; i < 100; i++)
{
if (i == 99)
{
_txt_list[i] = txt;
}
else
{
_txt_list[i] = _txt_list[i + 1];
}
}
}
if (Position < 99)
{
Position = _txt_list.Count -1;
}
}
public string Undo()
{
if (Position > 0)
{
Position--;
}
return _txt_list[Position];
}
public string Redo()
{
if (Position < 99)
{
Position++;
}
return _txt_list[Position];
}
}
events:
private void Menu_Edit_Undo_Click(object sender, EventArgs e)
{
txt_Notepad.Text = _operationObj.Undo();
txt_Notepad.SelectionStart = txt_Notepad.Text.Length;
txt_Notepad.SelectionLength = 0;
}
private void Menu_Edit_Redo_Click(object sender, EventArgs e)
{
txt_Notepad.Text = _operationObj.Redo();
txt_Notepad.SelectionStart = txt_Notepad.Text.Length;
txt_Notepad.SelectionLength = 0;
}
textbox change
private void txt_keyUp(object sender, KeyEventArgs e)
{
_operationObj.ChangeText(txt_Notepad.Text);
}

C# Class scope issue?

I am a student. This is our first project using two different class files, and it is also only the second one using Forms. So, I don't have much experience with either.
The object is declared and instantiated, but the object is not recognized in any of the subsequent methods. I am following the code on the book. The code on the book declares/instantiates like this:
new Order = new Order( );
I think it needs to be like this, but that still doesn't help the subsequent references:
Order newOrder = new Order( );
This a a complete listing of the driver and the two class files:
Driver:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Diner
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new OrderGUI());
}
}
}
OrderGUI.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 Diner
{
public partial class OrderGUI : Form
{
public OrderGUI()
{
InitializeComponent();
}
//For Load - create object
private void OrderGUI_Load(object sender, System.EventArgs e)
{
newOrder = new Order();
for (int i = 0; i < newOrder.menuEntree.Length; i++)
{
this.lstBxEntree.Items.Add(newOrder.menuEntree[i]);
}
}
// Event handler that gets the entree from the
// Listbox and sets the entree price of the Order object.
private void lstBxEntree_SelectedIndexChanged
(object sender, System.EventArgs e)
{
newOrder.Entree = this.lstBxEntree.Text;
}
// Event handler that gets the special request -
// if one is selected from the predefined list.
private void cmboSpecial_SelectedIndexChanged
(object sender, System.EventArgs e)
{
newOrder.SpecialRequest = this.cmboSpecial.Text;
}
// Menu item that displays the order.
private void menuDisplayOrder_Click(object sender,
System.EventArgs e)
{
}
// Event handler that gets the radio button selected and
// sets the drink selection for the Order object
private void Drink_CheckedChanged(object sender,
System.EventArgs e)
{
if (this.radTea.Checked)
newOrder.DrinkSelection = radTea.Text;
else
if (this.radCoffee.Checked)
newOrder.DrinkSelection = radCoffee.Text;
else
if (this.radSoda.Checked)
newOrder.DrinkSelection = radSoda.Text;
else
if (this.radLemon.Checked)
newOrder.DrinkSelection = radLemon.Text;
else
if (this.radJuice.Checked)
newOrder.DrinkSelection = radJuice.Text;
else
if (this.radMilk.Checked)
newOrder.DrinkSelection = radMilk.Text;
}
// Event handler that gets raised when the check box
// for the Water gets clicked.
private void ckBxWater_CheckedChanged
(object sender, System.EventArgs e)
{
if (this.ckBxWater.Checked)
newOrder.WaterSelection = true;
else
newOrder.WaterSelection = false;
}
// Event handler that gets raised when the user types
// values into the text area of the combo box.
private void cmboSpecial_KeyPress
(object sender,
System.Windows.Forms.KeyPressEventArgs e)
{
newOrder.SpecialRequest = this.cmboSpecial.Text;
}
// Event handler that gets raised when the Edit menu
// is clicked to change the entree.
private void menuEditEntree_Click
(object sender, System.EventArgs e)
{
}
// Event handler that gets raised when the Edit menu
// is clicked to change the drink.
private void menuEditDrink_Click
(object sender, System.EventArgs e)
{
}
// Clears selections for all drink radio buttons.
public void ClearDrinks()
{
this.radMilk.Checked = false;
this.radJuice.Checked = false;
this.radSoda.Checked = false;
this.radLemon.Checked = false;
this.radTea.Checked = false;
this.radCoffee.Checked = false;
}
// Clears all selections so that a new order
// can be placed. Resets the Order object back
// to its default values.
private void menuClearOrder_Click
(object sender, System.EventArgs e)
{
}
// Displays the values for the current instance of
// Order object members
private void menuPlaceOrder_Click(object sender,
System.EventArgs e)
{
}
// Event handler that gets raised when the Edit menu
// is clicked to change the special requests.
private void menuEditSpecial_Click(object sender,
System.EventArgs e)
{
}
// Event handler that gets raised when the Help
// menu is clicked to show the About message.
private void menuAbout_Click(object sender,
System.EventArgs e)
{
MessageBox.Show("Student Union -" +
" Diner by the Valley" +
"\n\n\nVersion 1.0");
}
// Event handler that gets raised when the
// Exit is clicked
private void menuExit_Click(object sender,
System.EventArgs e)
{
Application.Exit();
}
}
}
Order.cs:
using System;
using System.Windows.Forms;
namespace Diner
{
public class Order
{
public string[] menuEntree = new
string[] {"Chicken Salad",
"Ham and Cheese",
"Turkey",
"Vegetable Wrap",
"Tuna Salad",
"Avocado and Cheese",
"Club",
"Peanut Butter & Jelly",
"Cheese Toasty",
"Reuben"};
public decimal[] menuEntreePrice = new
decimal[] {4.50m,
5.00m,
4.75m,
4.00m,
4.50m,
4.00m,
5.50m,
3.75m,
3.50m,
5.00m};
private string entree;
private bool waterSelection;
private string drinkSelection;
private string specialRequest;
private decimal entreePrice;
private decimal drinkPrice;
// Default Constructor
public Order()
{
entree = "";
waterSelection = false;
specialRequest = "";
drinkPrice = 0;
entreePrice = 0;
}
//Property for Entree
public string Entree
{
get
{
return entree;
}
set
{
entree = value;
SetEntreePrice();
}
}
// Property for special request
public string SpecialRequest
{
get
{
return specialRequest;
}
set
{
specialRequest = value;
}
}
// Property for Water Selection
public bool WaterSelection
{
set
{
waterSelection = value;
}
}
// Property for Drink Selection
public string DrinkSelection
{
get
{
return drinkSelection;
}
set
{
drinkSelection = value;
SetDrinkPrice();
}
}
// Read-only property for entreee price
public decimal EntreePrice
{
get
{
return entreePrice;
}
}
// Read-only property for drink price
public decimal DrinkPrice
{
get
{
return drinkPrice;
}
}
// After the entree is set, store the entree price
public void SetEntreePrice()
{
for (int i = 0; i < menuEntree.Length; i++)
{
if (menuEntree[i] == entree)
{
entreePrice = menuEntreePrice[i];
}
}
}
// Return the water selection
public string GetWaterSelection()
{
string waterOrNot;
if (waterSelection)
{
waterOrNot = "Water";
}
else
{
waterOrNot = "No Water";
}
return waterOrNot;
}
// After the drink is set, store the drink price
public void SetDrinkPrice()
{
switch (drinkSelection)
{
case "Tea":
case "Coffee":
drinkPrice = 1.50m;
break;
case "Soda":
case "Lemonade":
drinkPrice = 2.00m;
break;
case "Milk":
case "Juice":
drinkPrice = 1.75m;
break;
}
}
// return the total cost of the order
public decimal DetermineTotalCharges()
{
return entreePrice + drinkPrice;
}
public override string ToString()
{
return "Toatal Due: " + DetermineTotalCharges().ToString("C");
}
}
}

Some data is being lost upon calculation

UPDATE: Whenever values are entered in classes 2 onwards the only result that is shown is that of the last entered inputs. So for example: if data is entered in class1 row and class2 row only calculations for class2 row is displayed. Could someone tell me why this is happening please?
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;
using System.IO;
namespace Grade_Point_Average_Calculator
{
public partial class GPA_Calculator : Form
{
SaveFileDialog saveFileDialog1;
public GPA_Calculator()
{
InitializeComponent();
}
private void GPA_Calculator_FormClosed(object sender, FormClosedEventArgs e)
{
Application.Exit();
}
// Closes application after exitToolStripMenuItem_Click
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
// Displays information about the application version number and creator
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Version 1.0., "About");
}
private void calculateBtn_Click(object sender, EventArgs e)
{
int maskbox1, maskbox2, maskbox3, maskbox4, maskbox5, maskbox6;
CalculatorLogics oCalculatorLogics1 = new CalculatorLogics(this);
oCalculatorLogics1.SelectedGrade = double.Parse(comboBox1.SelectedValue.ToString());
if (!int.TryParse(maskedTextBox1.Text, out maskbox1))
{
maskbox1 = 0; // Assign zero is parse fails
}
else
{
oCalculatorLogics1.CourseCredit = int.Parse(maskedTextBox1.Text);
}
oCalculatorLogics1.performGpaCalculations();
answerLabel.Text = oCalculatorLogics1.CalcGrade.ToString();
CalculatorLogics oCalculatorLogics2 = new CalculatorLogics(this);
oCalculatorLogics2.SelectedGrade = double.Parse(comboBox2.SelectedValue.ToString());
if (!int.TryParse(maskedTextBox2.Text, out maskbox1))
{
maskbox2 = 0; // Assign zero is parse fails
}
else
{
oCalculatorLogics2.CourseCredit = int.Parse(maskedTextBox2.Text);
}
oCalculatorLogics2.performGpaCalculations();
answerLabel.Text = oCalculatorLogics2.CalcGrade.ToString();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Grade_Point_Average_Calculator
{
class CalculatorLogics
{
private double grade;
private double gradeValue;
private double calculateGrades;
private int credits;
private GPA_Calculator _GPA_Calculator;
// Pass form to CalculatorLogics constructor
public CalculatorLogics(GPA_Calculator theGPA_Calculator)
{
_GPA_Calculator = theGPA_Calculator;
}
public double SelectedGrade
{
get { return grade; }
set { grade = value; }
}
public int CourseCredit
{
get { return credits; }
set { credits = value; }
}
public double CalcGrade
{
get
{
return calculateGrades;
}
}
public void performGpaCalculations()
{
gradeVal = grade * credits;
totalCredits += credits; // Add the amount of credits
totalGradeValue += gradeVal;
calculateGrades = totalGradeValue/totalCredits; // Calculates gpa
return calculateGrades;
}
}
}
As the code stands, your issue is that you are not calling the performGpaCalculations() method in your CalculatorLogics class and this is causing the calculateGrades value returned from the CalcGrade property to be the default value of a double (0.0).
You need to call the performGpaCalculations() method in your code, like this:
private void calculateBtn_Click(object sender, EventArgs e)
{
CalculatorLogics oCalculatorLogics = new CalculatorLogics();
oCalculatorLogics.performGpaCalculations();
answerLabel.Text = oCalculatorLogics.CalcGrade.ToString();
}
This will allow the CalcGrade class to determine the value of calculateGrades.
UPDATE:
But your real problem is that you are instantiating a new instance of the form class GPA_Calculator, which blows away the values the user selected.
Instead you need to pass an instance of the GPA_Calculator form class to the constructor of your CalculatorLogics class, like this:
public CalculatorLogics(GPA_Calculator theGPA_Calculator)
{
}
Now that your form is being passed to the constructor, you need somewhere to store it so the CalculatorLogics class can use it, here is a rewrite of your CalculatorLogics class to support this:
public class CalculatorLogics
{
private double grade;
private double gradeValue;
private double calculateGrades;
private int credits;
private GPA_Calculator _GPA_Calculator;
public CalculatorLogics(GPA_Calculator theGPA_Calculator)
{
_GPA_Calculator = theGPA_Calculator;
}
public double SelectedGrade
{
get { return grade; }
set { grade = value; }
}
public int CourseCredit
{
get { return credits; }
set { credits = value; }
}
public double CalcGrade
{
get
{
return calculateGrades;
}
}
public void performGpaCalculations()
{
const double grade_A = 4.00;
const double grade_A_minus = 3.67;
const double grade_B_plus = 3.33;
const double grade_B = 3.00;
const double grade_B_minus = 2.67;
const double grade_C_plus = 2.33;
const double grade_C = 2.00;
const double grade_C_minus = 1.67;
const double grade_D = 1.33;
const double grade_F = 0.00;
switch (_GPA_Calculator.comboBox1.SelectedItem.ToString())
{
case "A":
gradeValue = grade_A;
break;
case "A-":
gradeValue = grade_A_minus;
break;
case "B+":
gradeValue = grade_B_plus;
break;
case "B":
gradeValue = grade_B;
break;
case "B-":
gradeValue = grade_B_minus;
break;
case "C+":
gradeValue = grade_C_plus;
break;
case "C":
gradeValue = grade_C;
break;
case "C-":
gradeValue = grade_C_minus;
break;
case "D":
gradeValue = grade_D;
break;
case "F":
gradeValue = grade_F;
break;
}
calculateGrades = gradeValue * credits;
}
}
Finally, when you instantiate your CalculatorLogics class you will need to pass a reference to the form you are in, like this:
CalculatorLogics oCalculatorLogics = new CalculatorLogics(this);
Note: this is a pointer to the class itself, in this case the GPA_Calculator form.
To obtain the selected values of the comboBoxes, it does not help to just create a new instance of the form class.
Instead, you may pass the current form to the method like:
public void performGpaCalculations(GPA_Calculator form)
or better just pass a list of the selected items:
public void performGpaCalculations(int[] selectedValues)
int[] because i would suggest you to not use selectedItem of the comboBox but selectedIndex and create a static grade array
double[] grades = {4.00, 3.67, // ...
so you don't need that switch.
UPDATE:
OK, the answer above was updated with what I wrote, so my answer won't be helpful anymore...

c# visual studio how to pass value from subclass to parent class?

I'm new here, and also new in C# programming in Visual Studio.
Currently I have an assignment about C# refactoring.
This is the original class
calculator.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace HUANG_Kai_30077528_Assign1
{
public partial class calculator : Form
{
public calculator()
{
InitializeComponent();
}
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
}
private void calorieCalculation()
{
if (rbtnMale.Checked)
{
txtCalories.Text = (66
+ (6.3 * Convert.ToDouble(txtWeight.Text))
+ (12.9 * ((Convert.ToDouble(txtFeet.Text) * 12)
+ Convert.ToDouble(txtInches.Text)))
- (6.8 * Convert.ToDouble(txtAge.Text))).ToString();
}
else
{
txtCalories.Text = (655
+ (4.3 * Convert.ToDouble(txtWeight.Text))
+ (4.7 * ((Convert.ToDouble(txtFeet.Text) * 12)
+ Convert.ToDouble(txtInches.Text)))
- (4.7 * Convert.ToDouble(txtAge.Text))).ToString();
}
}
private void weightCalculation()
{
double maleVariable = 50;
double femaleVariable = 45.5;
double Formula = (2.3 * (((Convert.ToDouble(txtFeet.Text) - 5) * 12) + Convert.ToDouble(txtInches.Text)));
if (rbtnMale.Checked)
{
txtIdealWeight.Text = ((maleVariable + Formula) * 2.2046).ToString();
}
else
{
txtIdealWeight.Text = ((femaleVariable + Formula) * 2.2046).ToString();
}
}
private void txtFeetValidation()
{
double feet;
if (!double.TryParse(txtFeet.Text, out feet))
{
MessageBox.Show("Feet must be a numeric value.");
txtFeet.Select();
if (!(Convert.ToDouble(txtFeet.Text) >= 5))
{
MessageBox.Show("Height has to be equal to or greater than 5 feet!");
txtFeet.Select();
return;
}
}
}
private void txtInchesValidation()
{
double inches;
if (!double.TryParse(txtInches.Text, out inches))
{
MessageBox.Show("Inches must be a numeric value.");
txtInches.Select();
return;
}
}
private void txtWeightValidation()
{
double weight;
if (!double.TryParse(txtWeight.Text, out weight))
{
MessageBox.Show("Weight must be a numeric value.");
txtWeight.Select();
return;
}
}
private void txtAgeValication()
{
double age;
if (!double.TryParse(txtAge.Text, out age))
{
MessageBox.Show("Age must be a numeric value.");
txtAge.Select();
return;
}
}
private void btnCalculate_Click(object sender, EventArgs e)
{
txtFeetValidation();
txtInchesValidation();
txtWeightValidation();
txtAgeValication();
//Clear old results
txtIdealWeight.Text = "";
txtCalories.Text = "";
calorieCalculation();
weightCalculation();
}
private void label8_Click(object sender, EventArgs e)
{
}
private void btnExit_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnAddPatient_Click(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(txtIdealWeight.Text))
{
Form secondForm = new patientInfo(this);
secondForm.Show();
}
else
{
MessageBox.Show("Please enter all datas and click on 'Add Patient' to add patient's records");
}
}
private void btnPatientList_Click(object sender, EventArgs e)
{
Form secondForm = new patientList(this);
secondForm.Show();
}
private void btnClear_Click(object sender, EventArgs e)
{
rbtnMale.Checked = false;
rbtnFemale.Checked = false;
txtFeet.Text = "";
txtInches.Text = "";
txtWeight.Text = "";
txtAge.Text = "";
txtCalories.Text = "";
txtIdealWeight.Text = "";
}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
}
}
The following classed are the parent class and sub-classes I would like to setup.
parent: calculator.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace HUANG_Kai_30077528_Assign1
{
public partial class calculator : Form
{
//private string maleCaloriesCalculation();
//private string maleWeightCalculation();
//private string femaleCaloriesCalculation();
//private string femaleWeightCalculation();
public calculator()
{
InitializeComponent();
}
private void rbtnMale_CheckedChanged(object sender, EventArgs e)
{
}
private void btnCalculate_Click(object sender, EventArgs e)
{
//Clear old results
txtIdealWeight.Text = "";
txtCalories.Text = "";
/* Validate User Input: */
//Validate height (feet) is numeric value
double result;
if (!double.TryParse(txtFeet.Text, out result))
{
MessageBox.Show("Feet must be a numeric value.");
txtFeet.Select();
return;
}
//Validate height (inches) is numeric value
if (!double.TryParse(txtInches.Text, out result))
{
MessageBox.Show("Inches must be a numeric value.");
txtInches.Select();
return;
}
//Validate weight is numeric value
if (!double.TryParse(txtWeight.Text, out result))
{
MessageBox.Show("Weight must be a numeric value.");
txtWeight.Select();
return;
}
//Validate age is numeric value
if (!double.TryParse(txtAge.Text, out result))
{
MessageBox.Show("Age must be a numeric value.");
txtAge.Select();
return;
}
if (!(Convert.ToDouble(txtFeet.Text) >= 5))
{
MessageBox.Show("Height has to be equal to or greater than 5 feet!");
txtFeet.Select();
return;
}
/*End validation*/
calculation();
}
private void calculation()
{
if (rbtnMale.Checked)
{
txtCalories.Text = maleCalculator.maleCalories().ToString();
//txtCalories.Text = maleCalculator.maleCaloriesCalculation();
//txtIdealWeight.Text = maleCalculator.maleWeightCalculation();
}
else
{
txtCalories.Text = femaleCalculator.femaleCaloriesCalculation();
txtIdealWeight.Text = femaleCalculator.femaleWeightCalculation();
}
}
private void btnClear_Click(object sender, EventArgs e)
{
rbtnMale.Checked = false;
rbtnFemale.Checked = false;
txtFeet.Text = "";
txtInches.Text = "";
txtWeight.Text = "";
txtAge.Text = "";
txtCalories.Text = "";
txtIdealWeight.Text = "";
}
}
}
subclass: maleCalculation.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HUANG_Kai_30077528_Assign1
{
class maleCalculator: calculator
{
//private string maleCaloriesCalculation;
//private string maleWeightCalculation;
public maleCalculator maleCalories()
{
(66 + (6.3 * Convert.ToDouble(txtWeight.Text))
+ (12.9 * ((Convert.ToDouble(txtFeet.Text) * 12)
+ Convert.ToDouble(txtInches.Text)))
- (6.8 * Convert.ToDouble(txtAge.Text))).ToString();
return maleCalories();
//this.txtCalories.Text = new maleCalculator.maleCalories;
}
public maleCalculator maleWeight()
{
((50 + (2.3 * (((Convert.ToDouble(txtFeet.Text) - 5) * 12)
+ Convert.ToDouble(txtInches.Text)))) * 2.2046).ToString();
return maleWeight();
}
}
}
subclass: femaleCalculation.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HUANG_Kai_30077528_Assign1
{
class femaleCalculator : calculator
{
public double femaleCaloriesCalculation()
{
txtCalories.Text = (655 + (4.3 * Convert.ToDouble(txtWeight.Text))
+ (4.7 * ((Convert.ToDouble(txtFeet.Text) * 12)
+ Convert.ToDouble(txtInches.Text)))
- (4.7 * Convert.ToDouble(txtAge.Text))).ToString();
return femaleCaloriesCalculation();
}
public double femaleWeightCalculation()
{
txtIdealWeight.Text = ((45.5 + (2.3 * (((Convert.ToDouble(txtFeet.Text) - 5) * 12)
+ Convert.ToDouble(txtInches.Text)))) * 2.2046).ToString();
return femaleWeightCalculation();
}
}
}
As we can see, these two sub-classes are use to do the calculation for the calories and ideal weight. They are plan to take place of private void calorieCalculation() and private void weightCalculation() in the original class calculator.cs.
The function I need is like this:
When I execute the program and need to calculate the idealWeight and calories, the parent class calculator.cs will get the result from the formula contain in the sub-class, and ToString in the text box. That's why there are txtCalories and txtIdealWeight inside the calculator.cs.
So the question is how to get the results in the sub-class, and fill in the text boxes?
Guys, please help me with it as this is really important to me!!
Thank you all!!
Do you mean a virtual function? If so,
class Ancestor
{
public virtual int DoSomething()
{
// execute commands here.
// for now just throw exception.
throw new NotImplementedException();
}
}
class Derived_A : Ancestor
{
public override int DoSomething()
{
return 1 + 1;
}
}
class Derived_B : Ancestor
{
public override int DoSomething()
{
return 1 + 2;
}
}
This is ancestry, with virtual functions. For more on this:
Practical usage of virtual functions in c#
http://msdn.microsoft.com/en-us/library/9fkccyh4(v=vs.80).aspx
This type of code can also be done with interfaces. See http://msdn.microsoft.com/en-us/library/vstudio/ms173156.aspx.

display information about an object selected in a listbox in textboxes

I want to display the information about whichever flight is selected in the listbox in textboxes next to it. My problem is I can't get my curFlight variable to work right gives me InvalidCastException was unhandled error and says When casting froim a number, the value must be a number less than infinity.
heres my form code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Reservations
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Flight curFlight;
Flight flight1 = new Flight("Cessna Citation X", "10:00AM", "Denver", 6, 2);
Flight flight2 = new Flight("Piper Mirage", "10:00PM", "Kansas City", 3, 2);
private void Form1_Load(object sender, EventArgs e)
{
MakeReservations();
DisplayFlights();
}
private void lstFlights_SelectedIndexChanged(object sender, EventArgs e)
{
curFlight = (Flight)lstFlights.SelectedItem;
txtDepart.Text = curFlight.DepartureTime;
txtDestination.Text = curFlight.Destination;
}
private void MakeReservations()
{
flight1.MakeReservation("Dill", 12);
flight1.MakeReservation("Deenda", 3);
flight1.MakeReservation("Schmanda", 11);
flight2.MakeReservation("Dill", 4);
flight2.MakeReservation("Deenda", 2);
}
private void DisplayFlights()
{
lstFlights.Items.Clear();
lstFlights.Items.Add(flight1.Plane);
lstFlights.Items.Add(flight2.Plane);
}
private void btnMakeReservation_Click(object sender, EventArgs e)
{
string name;
int seatNum;
name = txtCustomerName.Text;
seatNum = Convert.ToInt16(txtSeatNum.Text);
curFlight.MakeReservation(name, seatNum);
}
}
}
HERES THE CLASS CODE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Reservations
{
class Flight
{
private string mPlane;
private string mDepartureTime;
private string mDestination;
private int mRows;
private int mSeats;
private string[] mSeatChart;
public Flight()
{
}
public Flight(string planeType, string departureTime, string destination, int numRows, int numSeatsPerRow)
{
this.Plane = planeType;
this.DepartureTime = departureTime;
this.Destination = destination;
this.Rows = numRows;
this.Seats = numSeatsPerRow;
// create the seat chart array
mSeatChart = new string[Rows * Seats];
for (int seat = 0; seat <= mSeatChart.GetUpperBound(0); seat++)
{
mSeatChart[seat] = "Open";
}
}
public string Plane
{
get { return mPlane; }
set { mPlane = value; }
}
public string DepartureTime
{
get { return mDepartureTime; }
set { mDepartureTime = value; }
}
public string Destination
{
get { return mDestination; }
set { mDestination = value; }
}
public int Rows
{
get { return mRows; }
set { mRows = value; }
}
public int Seats
{
get { return mSeats; }
set { mSeats = value; }
}
public string[] SeatChart
{
get { return mSeatChart; }
set { mSeatChart = value; }
}
public void MakeReservation(string name, int seat)
{
if (seat <= (Rows * Seats) && mSeatChart[seat - 1] == "Open")
{
mSeatChart[seat - 1] = name;
}
else
{
//let calling program know it didnt work.
}
}
public bool IsFull()
{
return false;
}
}
}
The reason you are getting the error is because you are assigning a string to the listbox and then trying to cast that string to a Flight Object
lstFlights.Items.Add(flight1.Plane); // Just say it is named "Plane 1"
lstFlights.Items.Add(flight2.Plane); // Just say it is named "Plane 2"
curFlight = (Flight)lstFlights.SelectedItem; // Now you are trying to convert "Plane 2" into a flight object which is incorrect
Try this instead
Add a Global List of type flights
List<Flight> flightList = new List<Flight>();
Flight flight1 = new Flight("Cessna Citation X", "10:00AM", "Denver", 6, 2);
Flight flight2 = new Flight("Piper Mirage", "10:00PM", "Kansas City", 3, 2);
in your form load add SetupFlights
private void Form1_Load(object sender, EventArgs e)
{
MakeReservations();
DisplayFlights();
SetupFlights(); // added this line
}
private void SetupFlights()
{
flightList.Add(flight1);
flightList.Add(flight2);
}
and your selected Index Changed should be something like this
private void lstFlights_SelectedIndexChanged(object sender, EventArgs e)
{
curFlight = flightList.FirstOrDefault(x => x.Plane == lstFlights.SelectedItem.ToString()); // Changed this line
txtDepart.Text = curFlight.DepartureTime;
txtDestination.Text = curFlight.Destination;
}
Although the answer by MVCKarl is more general, I'll show an easier way, which could suit in simple cases.
You could simply override ToString for the Flight class:
class Flight
{
//your code
public override string ToString()
{
//or anything you want to display
return this.Plane;
}
}
Then edit DisplayFlights method to add flights into the list:
private void DisplayFlights()
{
lstFlights.Items.Clear();
lstFlights.Items.Add(flight1);
lstFlights.Items.Add(flight2);
}
After this your lstFlights_SelectedIndexChanged would start working as expected:
private void lstFlights_SelectedIndexChanged(object sender, EventArgs e)
{
curFlight = (Flight)lstFlights.SelectedItem;
textBox1.Text = curFlight.DepartureTime;
textBox2.Text = curFlight.Destination;
}

Categories