Calculator using delegates in C#.net .(arithmetic is unassigned) - c#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ArithmaticOperation
{
class Program
{
delegate double ArithmaticDelegate(double x, double y);
static void Menu()
{
Console.WriteLine("Select an arithmatic operation");
Console.WriteLine("1)Addition");
Console.WriteLine("2)Subtraction");
Console.WriteLine("3)Multiplication");
Console.WriteLine("4)Division");
Console.WriteLine("5)Remainder");
Console.WriteLine("6)Quit");
}
static double Add(double a, double b)
{
return a + b;
}
static double Subtract(double a, double b)
{
return a - b;
}
static double Multiply(double a, double b)
{
return a * b;
}
static double Divide(double a, double b)
{
return a / b;
}
static double Modulus(double a, double b)
{
return a % b;
}
static void Main(string[] args)
{
int operation;
ArithmaticDelegate arithmatic;
double x, y;
do
{
Console.WriteLine("Enter two numbers seperated by Enter");
x = double.Parse(Console.ReadLine());
y = double.Parse(Console.ReadLine());
Console.Clear();
Menu();
operation = int.Parse(Console.ReadLine());
switch (operation)
{
//Addition
case 1:
arithmatic = new ArithmaticDelegate(Add);
break;
//Subtraction
case 2:
arithmatic = new ArithmaticDelegate(Subtract);
break;
//Multiplication
case 3:
arithmatic = new ArithmaticDelegate(Multiply);
break;
//Division
case 4:
arithmatic = new ArithmaticDelegate(Divide);
break;
//Remainder
case 5:
arithmatic = new ArithmaticDelegate(Modulus);
break;
default:
Console.WriteLine("Exiting program");
break;
}
Console.Clear();
Console.WriteLine(arithmatic(x, y));
Console.WriteLine("Press any key to continue");
Console.ReadKey(true);
Console.Clear();
} while (operation != 6);
}
}
}
I am trying to write a simple calculator using delegates. The code below would give an error at the line 81 "Console.WriteLine(arithmatic(x,y));" reporting that the variable arithmatic is unassigned local variable. I believe the cause has something to do with the variable scope in the do-while and the switch body, however the variable is declared outside the do-while so its scope should span the entire main method, and anything assigned to it from within the do-while and switch statement should remain in effect after its outside. Yet the compiler still report its uninitialized/unassigned

You are getting error message because arithmatic is not initialized in all the cases of switch statement (meaning not assigned in all execution paths).
To fix this issue:
either have some dummy method and assign that dummy method in default
static double DummyMethod(double a, double b)
{
return 6; // or any number other than 1 through 5
}
and in default case, arithmatic = DummyMethod;
(or) initialze as below:
So, to fix the error: please modify your programs to initialize arithematic as below:
ArithmaticDelegate arithmatic = null;
and then surround your arithematic call with if as below:
if (arithmatic != null)
{
Console.WriteLine(arithmatic(x, y));
}
or return in default case to skip the execution path when control enters into default case.

Related

C# Class Inheritance Issue with Simple Calculator

I am beginner to C# and am trying to get my second class, MyCalc2, to inherit from MyCalc. But I encounter the following error message in regards to MyCalc2:
There is no argument given that corresponds to the required formal parameter 'x' of 'MyCalc.MyCalc(int, int, string, string)'
The goal here is to just add another class that inherits from the base class.
I know that I need to add something like 'MyCalc: base(x)' to my base class but am lost to where to place the parameter (if that is even the correct thing to do). Any guidance would be appreciated. Here is what I have so far:
using System;
class MyCalc
{
// class variable
public int x;
public int z;
public string y;
public string n;
// constructor
public MyCalc(int x, int z, string y, string n)
{
this.x = x; // assign the parameter passed to the class variable
this.z = z;
this.y = y;
this.n = n;
}
// calculate the operations
public int GetAdd()
{
return (this.x + this.z);
}
public int GetSubtract()
{
return (this.x - this.z);
}
public int GetMultiply()
{
return (this.x * this.z);
}
public int GetDivide()
{
return (this.x / this.z);
}
public string GetYes()
{
return (this.y);
}
public string GetNo()
{
return (this.n);
}
}
class MyCalc2:MyCalc //where the error is occurring
{
static void Main(string[] args)
{
bool repeat = false;
do
{
repeat = false;
int x = 0; int z = 0; string y; string n;
Console.WriteLine("Enter the First Number");
x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter the Second Number");
z = Convert.ToInt32(Console.ReadLine());
//Using a switch statement to perform calculation:
Console.WriteLine("Enter operator\r");
switch (Console.ReadLine())
{
case "+":
Console.WriteLine($"The Answer is: {x} + {z} = " + (x + z));
break;
case "-":
Console.WriteLine($"The Answer is: {x} - {z} = " + (x - z));
break;
case "*":
Console.WriteLine($"The Answer is: {x} + {z} = " + (x + z));
break;
case "/":
Console.WriteLine($"The Answer is: {x} - {z} = " + (x - z));
break;
}
//Repeat or Exit program using the do-while loop:
string input = Console.ReadLine();
Console.WriteLine("Do you want another operation(Y / N) ?");
input = Console.ReadLine();
repeat = (input.ToUpper() == "Y");
}
while (repeat);
Console.WriteLine("Thanks for using our system.");
Console.ReadKey();
}
}
MyCalc2 does not have a way of initializing MyCalc (Base Class) Because in your BaseClass you do not have a parameter less constructor.
Solution:
Add a param less constructor in Base Class
Add a constructor in Derived class which has a way of calling base class constructor
for your code below should work:
class MyCalc2 : MyCalc
{
public MyCalc2 () : base(0, 0, "", "")
{
}
}
MyCalc2 has no explicit constructor. Which means it has only one implicit constructor which takes no arguments and sets no values. If made explicitly it would look like this:
public MyCalc2()
{
}
However, MyCalc does have an explicit constructor. Which means it has no implicit constructor. And its constructor does take arguments:
public MyCalc(int x, int z, string y, string n)
{
this.x = x; // assign the parameter passed to the class variable
this.z = z;
this.y = y;
this.n = n;
}
So when you create an instance of MyCalc2 it has no way of providing any values to MyCalc. You essentially have three options:
Add a constructor to MyCalc (you can have as many constructors as you want, as long as the parameters differ) which takes no parameters. However, in that case the class-level values for MyCalc would all be default values. You'd have to set them explicitly after constructing the object.1
Add a constructor to MyCalc2 which accepts those values and passes them to the parent constructor, or at least passes default values to the parent constructor.
Don't use inheritance here.
Honestly, in this case I'd go with the third option. What is inheritance meant to accomplish here? MyCalc2 isn't meaningfully an instance of MyCalc. All it does it hold the initial entry point of the application (the Main method), and that's really all it should do.
The logic in your Main method should create and use an instance of MyCalc, but the class which has that Main method shouldn't try to be an instance of MyCalc. That will only cause more confusion than solve any meaningful problems.
1 Side Note: Public class fields are historically a bad habit to get into in object-oriented programming. There's a variety of talk on the subject, and you'll see this often as you continue in your experience. In general you want your objects to expose behaviors, not values. The methods on the object look somewhat Java-like in convention. For C# conventions consider using properties (which compile down to methods themselves, the syntax is just semantically different). You can have { get; set; } auto-properties for the values themselves, and explicit read-only { get { /*...*/ } } properties for the calculated values.
Here is a possible solution. There are two classes MyClass, for the calculator (you may want to rename it) and Propram. Program holds just the method Main, which get your program started. It works like this, but there are some bugs left. I leave it to you to fix them. Except that you miss a clear understanding of the concepts class and inheritance, your code is not too bad for a beginner. It is almost working.
using System;
namespace TestCalculator
{
class MyCalc
{
// class variable
public int x;
public int z;
public string y;
public string n;
// constructor
public MyCalc(int x, int z, string y, string n)
{
this.x = x; // assign the parameter passed to the class variable
this.z = z;
this.y = y;
this.n = n;
}
// calculate the operations
public int GetAdd()
{
return (this.x + this.z);
}
public int GetSubtract()
{
return (this.x - this.z);
}
public int GetMultiply()
{
return (this.x * this.z);
}
public int GetDivide()
{
return (this.x / this.z);
}
public string GetYes()
{
return (this.y);
}
public string GetNo()
{
return (this.n);
}
}
class Program
{
static void Main(string[] args)
{
bool repeat = false;
do
{
repeat = false;
int x = 0; int z = 0; string y; string n;
Console.WriteLine("Enter the First Number");
x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter the Second Number");
z = Convert.ToInt32(Console.ReadLine());
//Using a switch statement to perform calculation:
Console.WriteLine("Enter operator\r");
switch (Console.ReadLine())
{
case "+":
Console.WriteLine($"The Answer is: {x} + {z} = " + (x + z));
break;
case "-":
Console.WriteLine($"The Answer is: {x} - {z} = " + (x - z));
break;
case "*":
Console.WriteLine($"The Answer is: {x} + {z} = " + (x + z));
break;
case "/":
Console.WriteLine($"The Answer is: {x} - {z} = " + (x - z));
break;
}
//Repeat or Exit program using the do-while loop:
string input = Console.ReadLine();
Console.WriteLine("Do you want another operation(Y / N) ?");
input = Console.ReadLine();
repeat = (input.ToUpper() == "Y");
}
while (repeat);
Console.WriteLine("Thanks for using our system.");
Console.ReadKey();
}
}
}

Calling delegate result in error "unasigned"

I want to write on screen result i get after completing actions at the bottom of the code. But i don't want to use Console.WriteLine() in "IF" function i want to call it as delegate carying value but it says unasigned. (site says mostly code but i dont have to say anything else so i just type something here :D )
namespace ConsoleApp5
{
class program
{
delegate int first(int a, int b);
static void Main()
{
first beta;
int result;
Console.Write("insert number A: ");
int.TryParse(Console.ReadLine(), out int a);
if (a == 0)
{
Console.WriteLine("not a number");
Environment.Exit(0);
}
Console.Write("insert number B: ");
int b = int.Parse(Console.ReadLine());
if (a == 0)
{
Console.WriteLine("not a number");
Environment.Exit(0);
}
Console.WriteLine("plus(1) or minus (0)");
int c = int.Parse(Console.ReadLine());
if (c == 1)
{
beta = plus;
result = beta(a, b);
Console.WriteLine(result);
}
else if (c == 0)
{
beta = minus;
result = beta(a, b);
Console.WriteLine(result);
}
beta(); // PROBLEM HERE, I WANT TO WRITE ANSWER FROM THIS
//instead of "Console.WriteLine(result);" inside function
}
private static int plus(int a, int b)
{
return a + b;
}
private static int minus(int a, int b)
{
return a - b;
}
}
}
Example what i mean i want to accomplish but a bit in different way.
using System;
namespace consoleApplication4
{
class Program{
Delegate void Message();
static void Main (string[] args)
{
Message mes;
if (DateTime.Now.Hour < 12)
{
mes=GoodMorning;
}
else{
mes=GoodEvening;
}
mes(); //this does what i want here but in code above something is missing
Console.ReadKey();
}
private static void GoodMorning(){
console.WriteLine("Good Morning");
}
Private static void GoodEvening(){
Console.WriteLine("Good Evening");
}}}
You already have correct code to call your delegate in both branches of if. So to get code almost working those two lines calling beta need to be moved out of both branches:
if (c == 1)
{
beta = plus;
}
else if (c == 0)
{
beta = minus;
}
result = beta(a, b);
Console.WriteLine(result);
Now the other problem is still there - your if checks have 3 outcomes (0, 1, other) but beta is only assigned in two of cases. So we need to add that "other" case too with some desired output (or simply failure), switch statement expresses it better than chained ifs:
switch (c)
{
case 1: beta = plus; break;
case 0: beta = plus; break;
default: beta = (a,b)=>""; break;
// alternatively to fail: default: return 0;
}
result = beta(a, b);
Console.WriteLine(result);

C# - invalid outputs

I am using enums in C# to calculate the areas of different shapes. Below is my code:
using System;
class Area
{
public enum Shape{Circle,Square};
public void AreaShape(int x,Shape ob1)
{
double a;
switch(x)
{
case (int)Shape.Circle:
a=Math.PI*x*x;
Console.WriteLine("Circle "+a);
break;
case (int)Shape.Square:
a=x*x;
Console.WriteLine("Square "+a);
break;
default:
Console.WriteLine("Invalid");
break;
}
}
}
class MyTestOne
{
public static void Main(String[] a)
{
Area obj1=new Area();
obj1.AreaShape(15,Area.Shape.Circle);
obj1.AreaShape(15,Area.Shape.Square);
}
}
The following produces an error:
obj1.AreaShape(15,Shape.Circle);
obj1.AreaShape(15,Shape.Square);
How can I get the following output?
Circle 225*pi
Square 225
When I use Area.Shape.Circle and Area.Shape.Square, the output is:
Invalid
Invalid
Pass Shape enum class not int x variable
switch (ob1)
{
case Shape.Circle:
a = Math.PI * x * x;
Console.WriteLine("Circle " + a);
break;
case Shape.Square:
a = x * x;
Console.WriteLine("Square " + a);
break;
default:
Console.WriteLine("Invalid");
break;
}
Your switch statement switches on x, which you're always passing in as 15. You should be switching on the ob1 enumeration variable and you won't need the cast.

Using a reference parameter

I'm learning C# by myself by book and would appreciate some help. I want to create a simple console program to allow the user to enter a number to be doubled. It says that the variable result in the Main method is unassigned, however, what am I doing wrong?
using System;
class Program
{
private static void Double(ref int num, ref int result)
{
result = num * 2;
}
private static int readNumber(string question)
{
Console.Write(question);
string ans = Console.ReadLine();
int number = int.Parse(ans);
return number;
}
public static void Main()
{
int num, result;
num = readNumber("Enter an integer to be doubled: ");
Double(ref num, ref result);
Console.WriteLine("The double of {0} is {1}", num, result);
Console.WriteLine("Press enter to exit...");
Console.ReadLine();
}
}
The compiler is yelling at you because it wants to force you to initialize the variables before passing them to the method call.
Meaning:
int num, result;
Should be:
int num = 0;
int result = 0;
There may be a better way of doing what you're trying to do, without any ref parameters at all, by simply using the return value of the method:
private static int Double(int num)
{
return num * 2;
}
And consume it like this:
public static void Main()
{
int num = readNumber("Enter an integer to be doubled: ");
int result = Double(num);
Console.WriteLine("The double of {0} is {1}", num, result);
Console.WriteLine("Press enter to exit...");
Console.ReadLine();
}
This may even (IMO) enhance the readability of your code and convey your intentions better.
´Why don´t you simply change the methods signatur to return a double instead of using a ref?
private static double Double(int num)
{
return num * 2;
}
Now you can simply call result = Double(num).

inputs in methods at visual c# 2005

I am facing a problem in creating a console application in Visual Studio c# 2005
I created the following program in which a method (to sum 2 predefined values) is called in the program
here is the code of it
class program
{
static void Main()
{
program a;
a = new program();
Console.WriteLine(a.am1(1,2));
Console.ReadLine();
}
int sum;
public int am1(int num1, int num2)
{
sum = num1 + num2;
return sum;
}
}
Now here is the main problem I am facing, well in this program two integers (num1 and num2) are predefined, I wanted those 2 numbers to be taken from user, means user input the two numbers and then the same program goes on like above. How it should be done?
P.S remember everything should be done in methods
i hope i got your requirements ... if not, please elaborate!
public sealed class Program
{
private readonly int _number1;
private readonly int _number2;
public Program(int number1, int number2)
{
this._number1 = number1;
this._number2 = number2;
}
public int Sum()
{
return this._number1 + this._number2;
}
public static void Main(string[] args)
{
// this one here is really brutal, but you can adapt it
int number1 = int.Parse(args[0]);
int number2 = int.Parse(args[1]);
Program program = new Program(number1, number2);
int sum = program.Sum();
Console.WriteLine(sum);
Console.ReadLine();
}
}
sry, this is not my main coding style ... pfuh ... really ugly!
edit:
don't give blind trust in int.Parse(). the params are coming from the user, you better double check them!
you better triple check them, as you are doing a sum ... thankfully c# compiles with unchecked - this code may fail with an OverflowException if compiled in vb - remember ranges of int
why do you want to do a simple addition in an extra class?
you should elaborate your style (regarding your comment): separate ui-code from business-layer code!
you do not need to create an instance variable for each task - you can do that with scope variables too...!
...
Use console application command line arguments. If it suites you. Below is an example from MSDN.
public class Functions
{
public static long Factorial(int n)
{
// Test for invalid input
if ((n < 0) || (n > 20))
{
return -1;
}
// Calculate the factorial iteratively rather than recursively:
long tempResult = 1;
for (int i = 1; i <= n; i++)
{
tempResult *= i;
}
return tempResult;
}
}
class MainClass
{
static int Main(string[] args)
{
// Test if input arguments were supplied:
if (args.Length == 0)
{
System.Console.WriteLine("Please enter a numeric argument.");
System.Console.WriteLine("Usage: Factorial <num>");
return 1;
}
// Try to convert the input arguments to numbers. This will throw
// an exception if the argument is not a number.
// num = int.Parse(args[0]);
int num;
bool test = int.TryParse(args[0], out num);
if (test == false)
{
System.Console.WriteLine("Please enter a numeric argument.");
System.Console.WriteLine("Usage: Factorial <num>");
return 1;
}
// Calculate factorial.
long result = Functions.Factorial(num);
// Print result.
if (result == -1)
System.Console.WriteLine("Input must be >= 0 and <= 20.");
else
System.Console.WriteLine("The Factorial of {0} is {1}.", num, result);
return 0;
}
}
// If 3 is entered on command line, the
// output reads: The factorial of 3 is 6.

Categories

Resources