To undo a calculation and subtract it from the running total - c#

This is a simple calculator. It performs calculations. However, every time it calculates I save that total and add it to a running total. But when I type in undo, the running total disappears and the previous calculation is not subtracted from the running total. Can someone please help me? This is suppose to be in memento format. So when I undo, a stack is removed or a total from a previous calculation. I am struggling with that.
class Calculator
{
public Stack<double> result= new Stack<double>();
double total = 0;
public void Add(double a, double b)
{
total += a + b;
Console.WriteLine("Sum:{0}", total);
result.Push(total);
}
public void Sub(double a, double b)
{
total += a - b;
Console.WriteLine("Difference:{0}", total);
result.Push(total);
}
public void Mul(double a, double b)
{
total += a * b;
Console.WriteLine("Product:{0} ", total);
result.Push(total);
}
public void Div(double a, double b)
{
if (b!=0)
{
total += a / b;
Console.WriteLine("Quotient:{0}", total);
result.Push(total);
}
else
{
Console.WriteLine("Error: Cannot divide by 0");
}
}
double GetTotal()
{
return total;
}
void Undo()
{
if (result.Count==0)
{
Console.WriteLine("UNDO IS NOT AVAILABLE");
}
Console.WriteLine("Running total:{0}", total);
}
void clear()
{
while (result.Count !=0)
result.Pop();
total = 0;
Console.WriteLine("Running total:{0}", total);
}
static int Main()
{
Calculator cal=new Calculator();
string line="";
while (true)
{
Console.WriteLine("Enter (Clear, Undo, Exit, Expression):");
if (line.ToLower() == "exit")
break;
else if (line.ToLower() == "undo")
cal.Undo();
else if (line.ToLower() == "clear")
cal.clear();
else
{
double a, b;
Console.WriteLine("Write the first number");
double.TryParse(Console.ReadLine(), out a);
Console.WriteLine("Write the second number");
double.TryParse(Console.ReadLine(), out b);
Console.WriteLine("Write the operand (+, -, /, *)");
char.TryParse(Console.ReadLine(), out char c);
if (c == '+')
cal.Add(a, b);
if (c == '-')
cal.Sub(a, b);
if (c == '*')
cal.Mul(a, b);
if (c == '/')
cal.Div(a, b);
}
}
return 0;
}

There are a couple things you need to fix here.
First, you never assign anything to line, so your code immediately falls into the else block for "Expression". So not only is Undo() not working, but I don't see how the Clear() or Exit() methods could be working either. Something like this will help with that by assigning to line:
while (true)
{
Console.WriteLine("Enter (Clear, Undo, Exit, Expression):");
line = Console.ReadLine();
if (line.ToLower() == "exit")
break;
//Rest of the code left out for simplicity...
}
Note that this considers invalid input as "Expression" and false down the else path, so you might want to consider explicitly checking for line.ToLower() == "expression" and giving an error message otherwise.
Also consider changing to a switch statement. It's not required by any means, but a little easier to maintain and read, IMO. You should also probably do a case-insensitive Equals() with this overload rather than converting the input to lowercase.
As for the actual implementation of your Undo() method, since your last action is just one item down on the Stack, just Pop() the top item off and Peek() at the Stack for your previous total:
void Undo()
{
if (result.Count==0)
{
Console.WriteLine("UNDO IS NOT AVAILABLE");
}
result.Pop(); //Remove current total from last expression
total = result.Peek(); //Take previous total
Console.WriteLine("Running total:{0}", total);
}
This should get you most of the way there. They may be other things that you'll need to fix as well. I did test the undo and clear functionality and they seem to work as expected, but did not test anything else (other than basic + and - expressions).

Related

Getting a CS7036 error when passing variables between methods for a calculator (from a code test I found on the internet))

CS7036 C# There is no argument given that corresponds to the required formal parameter 'num1' of 'Calculator.Add(int, int, int)' same error for subtracting, divide and multiply.
The test rules said that it must have separate methods for each operation.
Trying to get back into coding after taking an unavoidably long break. Thought tests would be a good way to spark the code brain again.
Anyway,
I've tried different method parameters, such as passing the variables as references and as straight values, different ways of calling the methods, different security parameters (private, public, static etc).
I've spent 2 hours trawling different forums and scripting references to see if there was anything, but so far no luck. The test rules said that it must have separate methods for each operation.
I had an earlier error about the num1 2 and op being passed without identifiers as well, so that may be contributing here.
I do know this isn't the most effective or efficient way to make a calculator, however, it is how the test wants it to be done.
using System;
namespace code_challenge.Challenges
{
public class Calculator
{
/*
* Within this Calculator class you will need to create 4 methods.
* The four methods will relate to the basic functions of a calculator
and should be named:
*
* - Add
* - Subtract
* - Multiply
* - Divide
int num1 =0; int num2 =0; int ans =0; string op = " ";
public void Input(int num1,int num2,int ans,string op)
{
Console.WriteLine("Please enter the first number.");
num1 = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Please enter the opperand.");
op = Console.ReadLine();
Console.WriteLine("Please enter the Second number.");
num2 = Convert.ToInt32(Console.ReadLine());
if (op == "+")
{
ERROR LINE Add();
}
if (op == "-")
{
ERROR LINE Sub();
}
if (op == "*")
{
ERROR LINE Mul();
}
if (op == "/")
{
ERROR LINE Div();
}
}
// Implement the add function below here
public void Add(int num1, int num2, int ans)
{
ans = num1 + num2;
Console.WriteLine("Your Answer is: " + ans);
}
// Implement the subtract function below here
public void Sub(int num1,int num2,int ans)
{
ans = num1 - num2;
Console.WriteLine("Your Answer is: " + ans);
}
// Implement the multiply function below here
public void Mul(int num1,int num2,int ans)
{
ans = num1 * num2;
Console.WriteLine("Your Answer is: " + ans);
}
// Implement the divide function below here
public void Div(int num1,int num2,int ans)
{
ans = num1 / num2;
Console.WriteLine("Your Answer is: " + ans);
}
}
}
No actual output due to the errors.
The expected output is that the operand input will throw the if statement, which will throw the appropriate operation and push ans into the console
I'll help you with Add op and you repeat this with other methods:
first,
if (op == "+")
{
Add(num1, num2);
}
second, change add method
public void Add(int num1, int num2)
{
ans = num1 + num2;
Console.WriteLine($"Your Answer is: {num1 + num2}");
}
Firstly, you are not passing any input arguments to the function. You should provide that.
Secondly, you do not need to have an input argument called ans in any of the function.
You can modify your function as following
public void Add(int num1,int num2){
int ans = num1+num2;
Console.WriteLine(ans);
}
Or you can return the value from the method for example:
public int Add(int num1,int num2){
int ans = num1+num2;
Console.WriteLine(ans);
return ans;
}
and in the input method, pass
Add(num1,num2)

Input String was not in correct format || ConsoleApp

Basically I'm trying to not let the user input string instead of an integer; but on line of code:
else if (Convert.ToString(result) == "")
I get an error.
Full code:
class Program
{
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Red;
int calcKelvin = 273;
int calcFahren = 32;
int result = Convert.ToInt32(Console.ReadLine());
if (result == 0)
{
Console.WriteLine("Check it up on google!");
Console.Title = "I'M USELESS CONSOLE, YOU CAN NOW EXIT || I'M USELESS CONSOLE, YOU CAN NOW EXIT || I'M USELESS CONSOLE, YOU CAN NOW EXIT ||";
}
else if (Convert.ToString(result) == "")
{
Console.Write("Error, you can not convert a text");
}
else
{
Console.WriteLine("Kelvin = " + calcKelvin * result);
Console.WriteLine("Fahrenheit = " + calcFahren * result);
}
}
}
The safest way to get a number from a string is to use the TryParse method, because this method returns two values! The actual return type is a bool which indicates whether or not the string was successfully converted, and the other is an out parameter, which is of the type that we're converting to, and which gets set to the converted value (or is set to the default value of the type if the conversion fails).
For temperatures, we often deal with decimal numbers, so a double is probably a good type to store the result. So, we'll use double.TryParse.
Now, since we don't necessarily want to just quit if the user makes a mistake, we should probably do our conversion in a loop, so if it fails, we just ask the user to try again. And since this code will be used in other places as well, we can make a helper method that takes in a prompt that we display to the user, and returns the strongly-typed user response:
private static double GetDoubleFromUser(string prompt = null)
{
double result;
do
{
Console.Write(prompt);
} while (!double.TryParse(Console.ReadLine(), out result));
return result;
}
With this method, we can now just declare a double and assign it to the return value of the method above, like:
double userInput = GetDoubleFromUser("Enter a temperature: ");
Another thing we can correct in the code are the formulas used to do the conversions. A quick check online shows us that we add a number for kelvin and we do multiplication, division, and addition for Fahrenheit. We can calculate these values on the fly once we have the Celsius temperature from the user:
private static void Main()
{
double celcius = GetDoubleFromUser("Enter a Celcius temperature: ");
double fahrenheit = celcius * 9 / 5 + 32;
double kelvin = celcius + 273.15;
Console.WriteLine("Kelvin = " + kelvin);
Console.WriteLine("Fahrenheit = " + fahrenheit);
GetKeyFromUser("Done! Press any key to exit...");
}
Output
Convert.ToInt32 throws an exception if the input string is not a number. To fix that, you can use int.TryParse instead.
Example:
using System;
class Program
{
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Red;
int calcKelvin = 273;
int calcFahren = 32;
int result;
bool isNum=int.TryParse(Console.ReadLine(),out result);
if (!isNum)
{
Console.Write("Error, you can not convert a text");
}
else if (result == 0)
{
Console.WriteLine("Check it up on google!");
Console.Title = "I'M USELESS CONSOLE, YOU CAN NOW EXIT || I'M USELESS CONSOLE, YOU CAN NOW EXIT || I'M USELESS CONSOLE, YOU CAN NOW EXIT ||";
}
else {
Console.WriteLine("Kelvin = " + calcKelvin * result);
Console.WriteLine("Fahrenheit = " + calcFahren * result);
}
}
}

Check adjacent values in a 2d array

I'm making a treasure hunt game - I allow a user to input a coordinate - and if it contains 't' for treasure, then they win. But I want to add something so that it'll check what they enter and if t is within a 1 element radius of their guess - it'll say "You are hot". Or "You are cold" if 't' is > 1 element away.
I can't figure out the best way I could do this. I've tried things such as
if (Board[Row+1,Column] == 't' || Board[Row+1,Column+1] == 't' etc etc etc)
{
Console.WriteLine("You are hot.");
}
else
{
Console.Writeline("You are cold.");
}
But this doesn't seem to be working for me, I can't use Lists yet so I'd like to get around this without using them.
This is the part of the code that should figure it out.
string HotOrCold = "";
if (Board[Row, Column] != 'x')
{
Board[Row, Column] = 'm';
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.Clear();
if () // Here Is Where It Should Figure It Out
Console.WriteLine("Uh-oh! You haven't found the treasure, try again!");
Console.WriteLine("You are {0}.", HotOrCold);
Console.ForegroundColor = ConsoleColor.Gray;
wonGame = false;
PrintBoard(Board);
SaveGame(username, ref Board);
}
I've also tried a nested for loop - but maybe I haven't used that correctly.
Not really a code question.
What you can do though is get the absolute value (i.e. ignore negative sign) of the difference between T and their guess for X and Y.
If either the absolute difference between T and the guess X or Y is 1 then you can say they are warm or whatever.
Partial example for you (prefer X/Y but have used row/col to match your work):
var rowDiff = Math.Abs(guessRow - tRow);
var columnDiff = Math.Abs(guessColumn - tColumn);
if (rowDiff == 0 && columnDiff == 0)
{
Console.WriteLine("You got it...");
}
else if (rowDiff <= 1 && columnDiff <= 1)
{
Console.WriteLine("You are hot...");
}
else
{
Console.WriteLine("You are cold...");
}
Thanks for the tip off Wiz.
The array can be seen as a subset of a Cartesian space. And how to position the elements in the array lends itself well to distance calculations in a Cartesian coordinate system. This means that the corresponding mathematical function can be implemented and used with confidence.
So that's what I would advice you to do for example:
static double distanceToTreasure(int x, int y)
{
double dX = x * 1.0D;
double dY = y * 1.0D;
double dWinX = winningX * 1.0D;
double dWinY = winningY * 1.0D;
double deltaX = Math.Abs(dWinX - dX);
double deltaY = Math.Abs(dWinY - dY);
return Math.Sqrt(Math.Pow(deltaX, 2.0D) + Math.Pow(deltaY, 2.0D));
}
Now I can easily check for any radius wether or not the player is in the vicinity of the treasure
static Boolean isInTheViccinityOfTreasure(double radius, int x, int y)
{
return distanceToTreasure(x,y) <= radius;
}
I can also just as easily see if our player has tumbled on the treasure:
static Boolean hasGotTheTreasure(int x, int y)
{
return distanceToTreasure(x, y) == 0.0D;
}
I can now get inputs from the user and use the methods above to output the right result. I am looping in order to test various cases.
public static void Main(string[] args)
{
while (true)
{
// datas setting
initDatas();
// Random treasure position selection
setupWinningPosition();
// This is cheating: some kind of debugging so you can test the results
Console.WriteLine("Don' t tell tx=" + winningX + " and tY = " + winningY);
Console.WriteLine("Enter x");
int x = Int32.Parse(Console.ReadLine());
Console.WriteLine("Enter y");
int y = Int32.Parse(Console.ReadLine());
if (hasGotTheTreasure(x, y))
{
Console.WriteLine("You got the treasure dude!!!");
}
// A radius of 1 is used here
else if (isInTheViccinityOfTreasure(1, x, y))
{
Console.WriteLine("That's getting hot: keep going boy...");
}
else
{
Console.WriteLine("Oops it's getting very cold");
}
// This is the way out of the loop by hitting 'q'
ConsoleKeyInfo key = Console.ReadKey();
if (key.KeyChar == 'q')
{
break;
}
}
}
This is what my output looks like:
Ben is on the Right Path but code needs to be more like.
public static void FoundTreasure(int guessColumn, int guessRow )
{
if (Math.Abs(guessRow - TRow) == 0 && Math.Abs(guessColumn - TColumn) == 0)
{
Console.WriteLine("You got it...");
return;
}
if (Math.Abs(guessRow - TRow) <= 1 && Math.Abs(guessColumn - TColumn) <= 1)
{
Console.WriteLine("You are hot...");
return;
}
Console.WriteLine("You are cold...");
}
This assumes that TRow and Tcolumn (the Tresure location) is set in the parent class.

parsing 2 double values in 1 statement - C#

how can I parse 2 double values in 1 statement instead of 2 if statements ?
my code :
double a, b;
while (true)
{
if (Double.TryParse(Console.ReadLine(), out a))
{
}
else
{
continue;
}
if (Double.TryParse(Console.ReadLine(), out b))
{
}
else
{
continue;
}
break;
}
I have already searched for it but did not found any good result
Something like this:
if (Double.TryParse(Console.ReadLine(), out a)
&& Double.TryParse(Console.ReadLine(), out b))
{
}
else
{
continue;
}
Note that the if block is only entered if both values are successfully parsed.
The if is redundant here, you don't need it and it makes the code less readable with an unnecessary continue.
double a, b;
while (!(double.TryParse(Console.ReadLine(), out a) &&
double.TryParse(Console.ReadLine(), out b))
{
}
//a and b successfully parsed.

C# Budget Calculator issue with Starting money

So this is my budget calculator.
It calculates how much i can earn with deposit(% per year), i can add money(earnings) and can decrease money(loosing).
In my code you have to manually tell the size of starting money.
What i need is for example in the beginning i tell my program that starting capital is 500euro. When i use deposit, it become for example 570,50. When i use earnings, i need it to start from 570,50, but in my program it will always ask again, what is your starting capital. I need to do it automatically somehow. Sorry for my bad english and here is the whole code :)
class Program
{
static void Main(string[] args)
{
int menu;
do
{
Console.WriteLine("1 - '%'");
Console.WriteLine("2 - '+'");
Console.WriteLine("3 - '-'");
Console.WriteLine("0 - iziet");
Console.Write("Menu: ");
menu = Convert.ToInt32(Console.ReadLine());
if (menu > 0 && menu < 4)
{
switch (menu)
{
case 1:
{
Console.Write("Noguldamā naudas summu: ");
int a = Convert.ToInt32(Console.ReadLine());
Console.Write("Procentu likme (0 - 100): ");
int b = Convert.ToInt32(Console.ReadLine());
Console.Write("Laiks (gadi): ");
int c = Convert.ToInt32(Console.ReadLine());
double d = Procenti(a, b, c);
Console.WriteLine("\nNaudas summa pēc {0} gadiem būs {1}\n", c, d);
}
break;
case 2:
{
Console.Write("Sakuma nauda: ");
int a = Convert.ToInt32(Console.ReadLine());
Console.Write("Cik nopelnijat: ");
int b = Convert.ToInt32(Console.ReadLine());
double d = Pluss(a, b);
Console.WriteLine("Tagadejais budzhets ir: {0} euro", d);
}
break;
case 3:
{
Console.Write("Sakuma nauda: ");
double a = Convert.ToDouble(Console.ReadLine());
Console.Write("Cik izterejat: ");
double b = Convert.ToDouble(Console.ReadLine());
double d = Minuss(a, b);
Console.WriteLine("Tagadejais budzhets ir: {0} euro", d);
}
break;
}
}
else
{
Console.WriteLine();
Console.WriteLine("Ludzu ievadiet ciparus 0,1,2,3 - parejie cipari ir arpus robezham!");
Console.WriteLine();
}
} while (menu != 0);
}
//FUNKCIJASSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
static double Procenti(double a, double b, int c)
{
for (int i = 0; i < c; i++)
{
a = (a * (b / 100) + a);
}
return a;
}
static double Pluss(double a, double b)
{
return a + b;
}
static double Minuss(double a, double b)
{
return a - b;
}
}
you need to store the value inside a variable.
and before to start the transactions you ask the user for the value :
int menu;
float stored_money;
Console.Write("Enter the Initial Value: ");
stored_money = Convert.ToInt32(Console.ReadLine());
do
{
and in the functions use this variable
static double Pluss(double b)
{
stored_money = stored_money + b;
return stored_money;
}
static double Minuss(double b)
{
stored_money = stored_money - b;
return stored_money;
}
Well, basically it looks like you need to save your balance amount somewhere in your code, because right now you're entering it from console in each menu point.
Something like (note I've omitted most of code):
int menu;
decimal amount;
do
{
.... //your code
case 1:
{
Console.Write("Noguldamā naudas summu: ");
amount = Convert.ToDecimal(Console.ReadLine());
.... //your code
decimal d = Procenti(a, b, c);
amount += d;
}
case 2:
{
Console.Write("Cik nopelnijat: ");
decimal b = Convert.ToInt32(Console.ReadLine());
amount = Pluss(amount, b);
Console.WriteLine("Tagadejais budzhets ir: {0} euro", amount);
}
.... //your code
} while (menu != 0);
And later in all cases you should not enter amount, but use that saved value and modify it according to menu point task.
Or maybe you even should introduce new menu point to set initial amount and don't enter it in point 1 (if point 1 can be called multiple times) - it depends on your calculator logic and it's up to you.
Note - it's better to use decimal rather that int and double for financial calculations as it is designed to store full possible precision.

Categories

Resources