Creating Calculator with Class - C#, However unable to solve error - c#

I'm trying to create a Calculator with a Class. However using references from the internet particularly from this website (https://www.sourcecodester.com/tutorials/c/7548/simple-calculator-using-class-c.html)
It did not mention to declare "Information" or whatsoever.
When I typed in the code, the error list return with Information does not exist in current context.
Is there a way to modify the code below? Thank you so much.
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
}
private void Form4_Load(object sender, EventArgs e)
{
}
public void RadioButton_Click(object sender, System.EventArgs e)
{
//call a constructor method and return to cal as an instance of a class
calculate cal = new calculate();
//declaring the string variable represent as a textbox
string txtnum1 = TextBox1.Text;
string txtnum2 = TextBox2.Text;
//declaring the double variable
double dbl_val1 = default(double);
double dbl_val2 = default(double);
if (**Information**.IsNumeric(txtnum1) && **Information**.IsNumeric(txtnum2)) //check if the textbox has a numeric value
{
//convert the string to double
dbl_val1 = double.Parse(txtnum1);
dbl_val2 = double.Parse(txtnum2);
//get the value of the converted variable
//to pass it into the variable in the class
cal.num1 = dbl_val1;
cal.num2 = dbl_val2;
//the condition is, if the radiobutton is clicked,
//the operation of MDAS executes.
if (Radio_Multiplication.Checked)
{
//result:
cal.multiply(); //call a subname in a class for multiplying
}
else if (Radio_Addition.Checked)
{
//result:
cal.add(); //call a subname in a class for adding
}
else if (Radio_Subtraction.Checked)
{
//result:
cal.subtract(); //call a subname in a class for subtracting
}
}
else
{
//the result is:
//if the textbox is empty or has a string value
TextBox3.Text = "Enter a number";
return;
}
//put the result of the MDAS to a textbox.
TextBox3.Text = cal.total.ToString();
}
}

I had a quick look at the link and they don't appear to have declared Information anywhere nor have they indicated that they've overridden anything so...I don't know.
That line, however, is just validating that the information entered into the two text boxes are actually numbers and not anything else that can't be calculated.
There are lots of methods you could use to check those numbers. Options would include, but are not limited to:
if(Int32.TryParse(txtNum1, out int temp1) && Int32.TryParse(txtNum2, out int temp2))
{
do stuff;
}
or
if(txtNum1.All(char.IsDigit) && txtNum2.All(char.IsDigit))
{
do stuff;
}
There are other options, but those two might be worth looking into.

Downloading the sample project, I had a look at what Information refers to. Turns out, it's a class from the Microsoft.VisualBasic namespace, presumably for exposing certain aspects of the VB core library to all .NET languages. You can use it in your program by adding a reference to Microsoft.VisualBasic to your project and adding:
using Microsoft.VisualBasic;
to the top of your code file.
(Personally, I can't imagine that this approach is terribly efficient. It's supposed to take an object and determine if it can be evaluated as a number, and I have no idea what approaches it uses to make that deduction based on any random object. You would probably be better off using one of the alternatives that Benny O'Neill suggests.)

Related

How to fill an array from several textboxes?

I am trying to fill an array from several textboxes, then calculate with the values in the array.
I have the following code, but don't know why it doesn't work. Explained in the code:
private void button1_Click(object sender, EventArgs e)
{
double[] temperaturen = new double[6];
temperaturen[0] = double.Parse(textBox1.Text);
MessageBox.Show(temperaturen[0].ToString()); //the messagebox is just to test if
//it works
}
The above code works, but it stops working after I add more values from more textboxes:
private void button1_Click(object sender, EventArgs e)
{
double[] temperaturen = new double[6];
temperaturen[0] = double.Parse(textBox1.Text); //now it stops working and gives
temperaturen[1] = double.Parse(textBox2.Text); //the following error:
temperaturen[2] = double.Parse(textBox3.Text); //format exceptions was unhandled.
temperaturen[3] = double.Parse(textBox4.Text);
temperaturen[4] = double.Parse(textBox5.Text);
temperaturen[5] = double.Parse(textBox6.Text);
temperaturen[6] = double.Parse(textBox7.Text);
MessageBox.Show(temperaturen[0].ToString());
}
Does anybody know if parsing from textbox is the right way of doing this whatsoever? and why this does not work?
Please note, that you have 7 textboxes, not 6, so you should declare new double[7].
To avoid such errors, let's query with a help of Linq:
using System.Linq;
...
double[] temperaturen = new TextBox[] {
textBox1, textBox2, textBox3,
textBox4, textBox5, textBox6,
textBox7 }
.Select(box => double.TryParse(box.Text, out var value) ? value : double.NaN)
.ToArray();
Note, that text box can have text which is not a valid floating point value (say, "bla-bla-bla"),
I put double.NaN (Not a Number) in this case.
What actually solved the problem is:
Adding a try catch, and changing the array to have 7 values.
The final code, fully functioning.
private void button1_Click(object sender, EventArgs e)
{
decimal[] temperaturen = new decimal[7];//the array
try // try block
{
temperaturen[0] = decimal.Parse(txtZondag.Text);//parsing input
temperaturen[1] = decimal.Parse(txtMaandag.Text);//from
temperaturen[2] = decimal.Parse(txtDinsdag.Text);//textboxes
temperaturen[3] = decimal.Parse(txtWoensdag.Text);
temperaturen[4] = decimal.Parse(txtDonderdag.Text);
temperaturen[5] = decimal.Parse(txtVrijdag.Text);
temperaturen[6] = decimal.Parse(txtZaterdag.Text);
decimal temp = 10.2m;//decimal temp for calculations
decimal uitkomst1 = 0.0m;//decimal for sum.
uitkomst1 = temperaturen[0] - temp;//calculation
textBox8.Text = uitkomst1.ToString();
decimal uitkomst2 = 0;
uitkomst2 = temperaturen[1] - temp;
textBox9.Text = uitkomst2.ToString();
decimal uitkomst3 = 0;
uitkomst3 = temperaturen[2] - temp;
textBox10.Text = uitkomst3.ToString();
decimal uitkomst4 = 0.0m;
uitkomst4 = temperaturen[3] = temp;
textBox11.Text = uitkomst4.ToString();
decimal uitkomst5 = 0;
uitkomst5 = temperaturen[4] - temp;
textBox12.Text = uitkomst5.ToString();
decimal uitkomst6 = 0;
uitkomst6 = temperaturen[5] - temp;
textBox13.Text = uitkomst6.ToString();
decimal uitkomst7 = 0;
uitkomst7 = temperaturen[6] - temp;
textBox14.Text = uitkomst7.ToString();
}
catch (Exception exception)//catch block
{
MessageBox.Show("Incorrecte invoer! " + exception.Message);
}
}
Your code is not SOLID, meaning that it doesn't follow the guidelines of the Solid principle. If you are not familiar with SOLID, consider to read some background information about SOLID
For instance, your code has more than one Responsibility. This principle states that each class should have a single purpose or responsibility. This helps reduce bugs by:
Simplifying the code,
Making testing easier, and
Allowing for more modularity (i.e., the ability to reuse and combine code).
In your case: you need a class that can read the temperature from somewhere. This can be from a text box, or from the internet, a digital thermometer, anything:
interface IThermometer
{
double ReadTemperature();
}
class TextBoxThermometer : IThermometer
{
public TextBox TextBox {get; set;}
public double ReadTemperature()
{
// TODO: add some error checking: null textbox, no proper value in the textbox, etc.
return Double.Parse(this.TextBox.Text);
}
}
This class is easy to create, easy to test, and easy to maintain: if you want a decimal as temperature, the changes will be minimal.
Once you've got this class, and created unit tests for them, you can be certain that the class is working correctly, for any TextBox that you attach to this class.
Apparently you don't have one Thermometer, you've got a collection of Thermometers. From each Thermometer you can read the temperature:
class ThermometerCollection : IReadOnlyCollection<IThermometer>
{
public List<IThermometer> Thermometers {get; set;}
// TODO: implement IReadOnlyCollection<IThermometer>
public double ReadTemperatur(int thermometerIndex)
{
// TODO: check validity of thermometerIndex
return this.Thermometers[thermometerIndex].ReadTemperature();
}
}
The thermometer collection is also a fairly simple class with functions with only one or two lines. Easy to understand, Easy to test, easy to maintain. If desired you can even have different types of thermometers in the collection: one that reads from a text box, another that reads from the internet.
Because you've unit tested the class, you can be certain that it works with all kinds of IThermometers.
Inside your form:
private IReadOnlyCollection<IThermometer> Thermometers {get;}
public MyForm() // constructor
{
InitializeComponent();
this.Thermometers = new ThermometerCollection
{
Thermometers = new List<IThermometer>()
{
new TextBoxThermometer() {TextBox = this.TextBox1},
new TextBoxThermometer() {TextBox = this.TextBox2},
new TextBoxThermometer() {TextBox = this.TextBox3},
new TextBoxThermometer() {TextBox = this.TextBox4},
new TextBoxThermometer() {TextBox = this.TextBox5},
new TextBoxThermometer() {TextBox = this.TextBox6},
},
}
}
Now your form has one ThermometerCollection with six thermometers. For users of these thermometers, it is not important how they get their temperature. They might read them from a text box, but if in future you decide to read the temperature from the internet, changes in your form will be minimal. Remember: because you've got unit tests for your TextBoxThermometer you can be sure that this type of Thermometer works flawless.
Now that you've decoupled the Thermometer from where it gets the temperature, in your form you can write methods to read the temperature
public double ReadTemperature(int thermometerIndex)
{
return this.ThermometerCollection.ReadTemperature(thermometerIndex);
}
Again a one liner method. Note that this is a method in your Form, so it is fairly difficult to unit test. But since you have tested the ThermometerCollection thoroughly, you hardly miss the test.
private void button1_Click(object sender, EventArgs e)
{
this.ProcessTemperatures();
// TODO: do other things that must be done when button1 is clicked
}
public void ProcessTemperatures()
{
// Read the temperatures, and process them:
ICollection<double> measuredTemperatures = Enumerable.Range(1,6)
.Select(thermometerIndex => this.ReadTemperature(thermometerIndex)
.ToList();
this.ProcessTemperatures(measuredTemperatures);
}
public void ProcessTemperatures(ICollection<double> measuredTemperatures)
{
// TODO: do what you wanted to do with your measured temperatures
}
I've decoupled the button click from the processing. If later you decide that you want to do something different if the button is clicked, changes will be minimal. Also, if you want to add a menu item that will also process the temperatures: the procedure will be a one liner.
Summary
Because I made methods that only have one specific task, you have methods that are easy to understand, easy to unit test, simple to change and maintain, simple to reuse.
Because I separated your from from the notion of Thermometers, you can reuse the thermometers in a different form. You have unit tested the Thermometer classes, so you can be certain that it will also work if you want 10 Thermometers.
Because I separated the Thermometer from where it gets its data from, it is easy to use a different type of Thermometer, for instance one that reads from a cell in a table, or from the internet. Users of your Thermometer class won't notice the difference.

Manipulating an object with a method in another class

Hi I'm very new to c# and I was hoping someone could point me in the right direction. I have created a text box with the value "Total" set to 0 in my main class, and I have created a button "button1_Click" in my "AddFunds" class in which I want it to change the Total value by reading in what the user has in putted "Deposit" putting through a loop and incrementing the "Total". How do I get the AddFunds class to recognize the int Total in my main class?
public void textBox1_TextChanged(object sender, EventArgs e)
{
int Total = new int();
Total = 0;
////string str = Convert.ToString(Total);
////Total.Text = str;
}
public void button1_Click(object sender, EventArgs e)
{
for (int Deposit = 0; Deposit <= 0; ++Deposit)
{
Total = Deposit;
}
}
public void richTextBox1_TextChanged(int initialDeposit)
{
int Deposit = int.Parse(Console.ReadLine());
}
You have some ways of doing that, but remember if this classes you're talking about are forms, they need to exist simultaneously, anything else will end up on you trying to access a null reference.
You can create a public property Total on your main class and pass an instace of Main to AddFund
If the composition is the oposite as the above, and Main holds an instance of AddFund you can make Main inject itself on the other class or pass a Funciotn to AddFund so it can access the value
This one is the only one that doesn't sound like a code smell given the information you provided, abstract your logic to some classes that are not forms and manipulate them on the forms.

Saving the user input as variable in c# windows form

So far if a user inputs something, I store in a label property. I know this can't be right. How can I update a variable based on user input for use across whichever event needs to use it?
This is one of many things I've tried. I can't even figure out the right search terms to google the solution for what I need to do.
namespace Words
{
public partial class formWords : Form
{
int x = 5;
int y = 50;
int buttonWidth = 120;
int buttonHeight = 40;
string fileList = "";
string word = "";
string wordFolderPath = #"C:\words\";// this is the variable I want to change with the dialog box below.
private void selectWordFolderToolStripMenuItem_Click(object sender, EventArgs e)
{
FolderBrowserDialog folder = new FolderBrowserDialog();
if (folder.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string folderPath = folder.SelectedPath;
formWords.wordFolderPath = folderPath;
}
}
wordFolderPath is a variable public to your class (but private outside of it). This means that anything inside your class can freely read/write the value.
As for your syntax, you can just use the variable name or use this.:
private void DoAThing()
{
wordFolderPath = "asdf";
this.wordFolderPath = "qwerty"; //these are the same
}
You can't use the current class's name when accessing an internal variable. formWords is a type, not an instance.
The only advantage of using this is because it is legal to have a variable of the same name defined within your method. Using this keyword makes sure you are talking about the class's member.
Just changing formWords.wordFolderPath = folderPath;
to wordFolderPath = folderPath;
or this.wordFolderPath = folderPath;
should fix your problem
Also, there should have been a compiler error in the error list saying "An object reference is required for the non-static field, method, or property..."
If you don't have your error list visible you should definitely turn it on.

How do I determine if the value of a string variable changed in C#?

I have something to do under a button click (add values to listbox) only if a particular string changes from its previous value. How do I manage this? Below is a sample of my code:
private void button6_Click(object sender, EventArgs e)
{
string x = //some varying value I get from other parts of my program
listBox1.Items.Clear();
listBox1.Items.Add(x + /*other things*/);
}
I can at times have same value for string x from previous value when clicking button6. In such cases I don't want listBox1 to add the item (string x). How to add to listbox only when value of string changes? There's no way to predetermine string x. It gets value when program is running.
Note: adding values to listBox1 every single time and later deleting the duplicates wont work in my program.
Have you considered keeping a copy of the old string value around in a private field, and simply comparing the new value to the old value to see if they match?
For example:
// holds a copy of the previous value for comparison purposes
private string oldString = string.Empty;
private void button6_Click(object sender, EventArgs e)
{
// Get the new string value
string newString = //some varying value I get from other parts of my program
// Compare the old string to the new one
if (oldString != newString)
{
// The string values are different, so update the ListBox
listBox1.Items.Clear();
listBox1.Items.Add(x + /*other things*/);
}
// Save the new value back into the temporary variable
oldString = newString;
}
Edit: As the other answers suggest, there are certainly other, more complicated solutions, like encapsulating all access to the string value in a property, or wrapping the string in a custom class. Some of these alternatives have the potential to be "cleaner", more object-oriented approaches. But they're all more complicated than simply saving the previous value in a field. It's up to you to decide whether your specific use case merits the complicated solution, or a simpler one. Think about long-term maintainability, not what's easier for you to implement right now.
string last = string.Empty;
private void button6_Click(object sender, EventArgs e)
{
string x = //some varying value I get from other parts of my program
if(x!=last)
{
listBox1.Items.Clear();
listBox1.Items.Add(x + /*other things*/);
last = x;
}
}
If this string is super important and gets passed around alot, maybe you should wrap it in a class. The class can hold the string value as a property, but also keep track of when it has changed.
public class StringValue
{
private bool _changed;
public string StrValue{get; set{ _changed = true;}
public bool Changed{get;set;}
}
this is rudimentery of course
I'm not sure I understand completely, but it sounds like you should be using a property to set String x;
string _x = string.Empty;
public string X
{
set
{
if(value != this._x)
{
DoFancyListBoxWork();
this._x = value;
}
}
get
{
return this._x;
}
}
If this is web application, store your last value into session variable. If this is windows application, store it at a class level variable or in singleton class and use this last value for comparison with new value.
On the page load add the current value to viewstate and at the button click check the current value is equal to the value in the view state. If both are equal we can say that the value is not changed.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["CurrentValue"] = Your Value;
}
}
protected void btnSubmit_click(object sender, EventArgs e)
{
if (NewValue== ViewState["CurrentValue"].ToString())
{
lblmsg.Text = "value is not changed..";
return;
}
else
lblmsg.Text = "value is changed..";
}
You can check the detailed article in this link.
Check Control Value is changed or not
First, I'd like to ask you to check most of the other answers. They are more complete, in that they treat more global issues of tracking the changes of a variable.
Now, I'm assuming, from reading the snippet of code you provided, that you need to track if a string was changed by the user. So, in other words, you probably have a TextBox or other kind of control through which the user can change that value. This is where you should focus your attention: just consume the TextChanged event.
If, however, I'm mistaken and your string comes from any other kind of external source, either use the wrapper class suggested by #Ryan Bennett or, if you are using .Net 4, use a dynamic container, which raises a PropertyChanged event whenever any property is changed.

C# and Winforms TextBox control: How do I get the text change?

I have an event handler for the TextBox.TextChanged event on a form of mine. In order to support undo, I'd like to figure out exactly what has changed in the TextBox, so that I can undo the change if the user asks for it. (I know the builtin textbox supports undo, but I'd like to have a single undo stack for the whole application)
Is there a reasonable way to do that? If not, is there a better way of supporting such an undo feature?
EDIT: Something like the following seems to work -- are there any better ideas? (It's times like this that I really wish .NET had something like the STL's std::mismatch algorithm...
class TextModification
{
private string _OldValue;
public string OldValue
{
get
{
return _OldValue;
}
}
private string _NewValue;
public string NewValue
{
get
{
return _NewValue;
}
}
private int _Position;
public int Position
{
get
{
return _Position;
}
}
public TextModification(string oldValue, string newValue, int position)
{
_OldValue = oldValue;
_NewValue = newValue;
_Position = position;
}
public void RevertTextbox(System.Windows.Forms.TextBox tb)
{
tb.Text = tb.Text.Substring(0, Position) + OldValue + tb.Text.Substring(Position + NewValue.Length);
}
}
private Stack<TextModification> changes = new Stack<TextModification>();
private string OldTBText = "";
private bool undoing = false;
private void Undoit()
{
if (changes.Count == 0)
return;
undoing = true;
changes.Pop().RevertTextbox(tbFilter);
OldTBText = tbFilter.Text;
undoing = false;
}
private void UpdateUndoStatus(TextBox caller)
{
int changeStartLocation = 0;
int changeEndTBLocation = caller.Text.Length;
int changeEndOldLocation = OldTBText.Length;
while (changeStartLocation < Math.Min(changeEndOldLocation, changeEndTBLocation) &&
caller.Text[changeStartLocation] == OldTBText[changeStartLocation])
changeStartLocation++;
while (changeEndTBLocation > 1 && changeEndOldLocation > 1 &&
caller.Text[changeEndTBLocation-1] == OldTBText[changeEndOldLocation-1])
{
changeEndTBLocation--;
changeEndOldLocation--;
}
changes.Push(new TextModification(
OldTBText.Substring(changeStartLocation, changeEndOldLocation - changeStartLocation),
caller.Text.Substring(changeStartLocation, changeEndTBLocation - changeStartLocation),
changeStartLocation));
OldTBText = caller.Text;
}
private void tbFilter_TextChanged(object sender, EventArgs e)
{
if (!undoing)
UpdateUndoStatus((TextBox)sender);
}
You might be better off using the Enter and Leave events instead. When entering, store the current text in a class variable, then when leaving compare the new text to the old.
Yes, don't tie it directly to the textbox. Your forms' state should be in some model object somewhere that isn't directly tied to the form (MVC is one way to do this, MVVM is another). By decoupling them like that, you can compare the new textbox value to the current model value whenever a change request comes in.
Actually, all I can think of is having some kind of collection where you store different string versions (so you can undo many times, not just once).
I would store the reference to TextBox's collections in TextBox.Tag, so it is straightforward to store/use it.
Last but not least, you update your collection of strings during the event TextChange. With no much work, you can maintain a full history, gettinjg the previous value from your own structure.
This is probably overkill for what you're trying to accomplish, but CSLA support n-level undo. CSLA is a great business objects framework written by Rocky Lhotka. The business objects handle the undo history and it flows to the UI through data binding.
Switching your app to use CSLA would be a big commitment, but another option would be to look through the freely available source code to see how he implemented it.
I am actually making an own Syntax-Highlight-System so I also need to know the changed text.
My solution is to watch for an enter or space or an depositioning of the cursor.
As WinForms provide the Keydown event I used the KeyEventArguments (e) and converted them to a char.
After that I storage the char into a string like :
string i="";
i+=convertedToChar; // convertedToChar = kc.ConvertToString(e.KeyData)
And as soon as there is a enter or space or depositioning - "event" I delete the string.
Result:
If a user enters a few chars and hit space I am able to read the last chars (till the last space).
An advantage would be the fact that you can use any delimiter char for that (as soon as they are storaged and provided by e.KeyCode)
However I hope that this is a solution for everybody watching this after 9years :D.
It´s never too late.

Categories