How to save a variables value when leaving the method? - c#

I have a method which counts the amount of times a user has withdrawn from the atm(as there is a limit) and also counts up the amount of money the user has withdrawn in the day. However the values in the count var and in the amountWithdrawn variable are both lost upon leaving the method, how do I keep them "saved"? Also as a side note, I have a class called Account which has the balance and such, would it be best to put them there? But would also like to know if it is possible to save the variables in the method for future reference.
public decimal WithDraw()
{
int timesWithdrawn = 9;
decimal amountWithdrawnToday = 0;
decimal money = 0;
bool success = false;
if (timesWithdrawn < 10)
{
do
{
//Console.WriteLine("{0} available to withdraw.", FundsAvailable);
Console.WriteLine("How much would you like to withdraw?");
try
{
money = decimal.Parse(Console.ReadLine());
if (money % 5 == 0 && money <= account.CurrentBalance && money <= 1000)
{
success = true;
}
if (money == 0)
{
bool exit = true;
Console.WriteLine("Do you want to exit? Type \"yes\", or \"no\".");
while (exit == true)
{
string response = Console.ReadLine();
if (response.ToLower() == "yes")
{
break;
}
else
{
exit = false;
}
}
}
}
catch (FormatException)
{
Console.WriteLine("Please enter a number to withdraw.");
}
} while (success == false);
//do while this is true
Console.WriteLine(account.CurrentBalance);
Console.WriteLine("Withdrawing {0} pounds.", money);
Console.WriteLine("You have {0} remaining in your account.", account.CurrentBalance - money);
amountWithdrawnToday += money;
timesWithdrawn += 1;
Console.WriteLine("{0} pounds withdrawn today", amountWithdrawnToday);
return account.CurrentBalance -= money;
}
else
{
Console.WriteLine("You have exceeded daily withdrawls. You have withdrawn {0}", amountWithdrawnToday);
return amountWithdrawnToday;
}
}

I will suggest you need to put those variable in the Account class, also I suggest that you could put the withdraw method itself in the Account class, This could be more OOP friendly.
and to save the timesWithdrawn number, you just need to make it as class instance vairable instead of making it local variable
here is the code
class Account
{
public decimal CurrentBalance { get; set; }
public int timesWithdrawn { get; set; } = 9;
public decimal WithDraw()
{
decimal amountWithdrawnToday = 0;
decimal money = 0;
bool success = false;
if (timesWithdrawn < 10)
{
do
{
//Console.WriteLine("{0} available to withdraw.", FundsAvailable);
Console.WriteLine("How much would you like to withdraw?");
try
{
money = decimal.Parse(Console.ReadLine());
if (money % 5 == 0 && money <= CurrentBalance && money <= 1000)
{
success = true;
}
if (money == 0)
{
bool exit = true;
Console.WriteLine("Do you want to exit? Type \"yes\", or \"no\".");
while (exit == true)
{
string response = Console.ReadLine();
if (response.ToLower() == "yes")
{
break;
}
else
{
exit = false;
}
}
}
}
catch (FormatException)
{
Console.WriteLine("Please enter a number to withdraw.");
}
} while (success == false);
//do while this is true
Console.WriteLine(CurrentBalance);
Console.WriteLine("Withdrawing {0} pounds.", money);
Console.WriteLine("You have {0} remaining in your account.", CurrentBalance - money);
amountWithdrawnToday += money;
timesWithdrawn += 1;
Console.WriteLine("{0} pounds withdrawn today", amountWithdrawnToday);
return CurrentBalance -= money;
}
else
{
Console.WriteLine("You have exceeded daily withdrawls. You have withdrawn {0}", amountWithdrawnToday);
return amountWithdrawnToday;
}
}
}
as you notice from the code, I removed the reference to the account variable and made the CurrentBalance as instance variable and also the timesWithdrawn.
this could preserve the value of the timesWithdrawn even after the method has been finished.

As long as the program is running it is saved there, but once quite it resets, so yes you have to save it somewhere in a database a excel table or in a text document
Saving data to a file in C#
check this out if you need some help how to do stuff like this

You could pass an 'out' parameter to the function, it's basically a variable you send to the function, which holds its value outside the function.
For example:
public void WithDraw(out int c) {
c = something ; //c must receive a value during the call
}
int myvar; // the parameter which will hold the value when the function returns
WithDraw(out myvar); //call to the function
myvar //will now hold a value from the function (something)
You could also consider returning a tuple, or putting the value you wish to save into a 'global variable'.

Related

cannot figure out while random number generator game is not working c#

I am programming a game that generates a random number and then has the user try to guess the number when the user inputs a number the program will respond with either too high or too low depending on the number generated.The problem I am having is that the loop will just keep executing and the program will not take another user input if the number is incorrect.I have tried using different types of loops like a do while and for loop but keep getting the same problem I feel as though I am missing something simple or making a simple mistake thanks
string usernumber;
Random rnd = new Random();
int value = rnd.Next(1,50); //generates a random number upto 50
int guess = 0;
Console.WriteLine("please enter a number"); //asks for and takes user input
usernumber = Console.ReadLine();//stores user input
guess = Convert.ToInt32(usernumber);
while (guess != value) //this stands for not equals to
{
//guess = Convert.ToInt32(usernumber);
if (value > guess)
{
Console.WriteLine("too high");
}
else if (value < guess)
{
Console.WriteLine("too low");
}
else if (value == guess)
{
Console.WriteLine("bang on the answer was" + value);
}
else
{
Console.WriteLine("errrrrrrrrr");
}
}
Thread.Sleep(2000); //delays the program closing for a bit
You can use this corrected and refactored to have more explicit variables names.
We add 1 to 50 because the Random.Next last parameter is the upper bound excluded.
We use a do...while loop to have a concise algorithm.
We use int.TryParse to get the int from the user. This method returns false and sets the value to 0 in case of conversion error instead of an exception.
We use Console.ReadKey instead of Thread.Sleep, that is more UX friendly.
var random = new Random();
int numberTarget = random.Next(1, 50 + 1);
int numberUser;
do
{
Console.Write("Please enter a number between 1 and 50: ");
if ( int.TryParse(Console.ReadLine(), out numberUser) )
{
if ( numberUser > numberTarget )
{
Console.WriteLine("Too high, retry.");
}
else
if ( numberUser < numberTarget )
{
Console.WriteLine("Too low, retry.");
}
else
{
Console.WriteLine($"Bang on the answer was {numberTarget}.");
}
}
else
{
Console.WriteLine("You didn't enter a valid number, retry.");
}
}
while ( numberUser != numberTarget );
Console.WriteLine("Press a key to exit.");
Console.ReadKey();
In your while loop, you forgot to make another ReadLine.
while (guess != value) //this stands for not equals to
{
if (value > guess)
{
Console.WriteLine("too high");
guess = Convert.ToInt32(Console.ReadLine());
}
else if (value < guess)
{
Console.WriteLine("too low");
guess = Convert.ToInt32(Console.ReadLine());
}
else if (value == guess)
{
Console.WriteLine("bang on the answer was" + value);
}
else
{
Console.WriteLine("errrrrrrrrr");
}
}

When code hits exception case program immidiately stops, need program to reprompt the user after exception throw

I need the program to continue and prompt the user for a new value after an exception throw.
Program throws a run time error when hitting the exception, says it is unhandled
using System;
using static System.Console;
class SwimmingWaterTemperature
{
static void Main()
{
// Your code here
int temp = 0;
Console.WriteLine("Enter temperature or type 999 to quit");
do
{
temp = Convert.ToInt32(Console.ReadLine());
bool comfort = CheckComfort(temp);
}
while (temp != 999);
}
public static bool CheckComfort(int temp)
{
// your logic here
bool comfort;
if (temp >= 70 && temp <= 85)
{
Console.WriteLine("{0} Degrees is comfortable for swimming.", temp);
Console.WriteLine("Enter another temperature or 999 to quit");
comfort = true;
return comfort;
}
else if ((temp >= 32 && temp <= 70) || (temp >= 85 && temp <= 212) && temp != 999)
{
Console.WriteLine("{0} Degrees is not comfortable for swimming.", temp);
Console.WriteLine("Enter another temperature or 999 to quit");
comfort = false;
return comfort;
}
else if (temp == 999)
{
comfort = false;
return comfort;
}
else
{
throw new System.ArgumentException("Value does not fall within expected range");
Console.WriteLine("Enter another temperature or 999 to quit");
}
}
}
"Runtime error, unhandled exception"
A common rule of thumb is: Exceptions should be exceptional.
You should never, ever, use exceptions for control flow, we have a lot of other constructs that are better for that. There's absolutely no surprise if the user inputs something invalid, that's a valid usage of your application, so the application should not treat the case where the user goes off script as unexpected. In fact, you can expect it and test for it.
So, in your case, it's much, much better to refactor the code.
You know that 999 is the quit command (that can also be done better, but lets keep it)
You know that the valid range is 32 to 212, so you can have a method
that checks that.
Something along these lines is a much better approach:
static void Main()
{
// Your code here
int temp = 0;
do
{
// we can do at the start of every loop, no need to have the same code in multiple places
Console.WriteLine("Enter temperature or type 999 to quit");
temp = Convert.ToInt32(Console.ReadLine());
// no need to do additional processing if we got the quit sequence
if (temp != 999) {
// and here we KNOW that we are not in a quit sequence
// now check if the entered value is valid
bool isValid = CheckValidTemperature(temp);
if (isValid) {
// here we KNOW that the temperature is in the valid range
bool comfort = CheckComfort(temp);
if (comfort) {
Console.WriteLine("{0} Degrees is comfortable for swimming.", temp);
} else {
Console.WriteLine("{0} Degrees is not comfortable for swimming.", temp);
}
} else {
// here we KNOW that the temperature in NOT in the valid range
// no need for exceptions, we just show a message
Console.WriteLine("Value does not fall within expected range");
}
}
}
while (temp != 999);
}
public static bool CheckValidTemperature(int temp)
{
// the range 32 - 212 is valid, everything else is invalid
return (temp >= 32 && temp <=212);
}
public static bool CheckComfort(int temp)
{
// your logic here - no need to validate anything, as we know that it is valid
// however, we could validate here, and if it's invalid now, that would indeed be exceptional
//if (!CheckValidTemperature(temp)) {
// // quite ok to throw here, as this should never happen under normal circumstances
// throw new ArgumentException("Value does not fall within expected range");
//}
// this can be some complicated logic
if (temp >= 70 && temp <= 85)
{
return true;
}
else
{
return false;
}
}
I'll leave the case when the user enters something that is not a number at the prompt as a extension that will need to be implemented :D
try
{
throw new System.ArgumentException();
}
catch (ArgumentException)
{
Console.WriteLine("Value does not fall within the expected range.");
Console.WriteLine("Enter another temperature or 999 to quit");
comfort = false;
return comfort;
}

c# - Console App - Solving error when user presses enter without any numbers

The title is a bit messy in regards to getting what I want out there and it's my first time on here.
Basically I have converted my string into an int :
string _val = Console.ReadLine();
tempScoreToWin = Convert.ToInt32(_val);
And what I want to know is when user a presses enter without entering a value an error will occur and the application will end.
How can I get around this?
Here is my full code:
while (true)
{ //This will allow the player to manually change the score.
//------------------------------------------------------------------------------------------
string _val = "";
ConsoleKeyInfo key;
do
{
key = Console.ReadKey(true);
if (key.Key != ConsoleKey.Backspace)
{
double val = 0;
bool _x = double.TryParse(key.KeyChar.ToString(), out val);
if (_x)
{
_val += key.KeyChar;
Console.Write(key.KeyChar);
}
}
else
{
if (key.Key == ConsoleKey.Backspace && _val.Length > 0)
{
_val = _val.Substring(0, (_val.Length - 1));
Console.Write("\b \b");
}
}
}
while (key.Key != ConsoleKey.Enter);
Console.WriteLine();
//-----------------------------------------------------------------
tempScoreToWin = Convert.ToInt32(_val); // Converting the users input (Console.ReadLine()) into an integer.
if (tempScoreToWin > 0) // If the users input is higher than zero ...
{
scoreToWin = tempScoreToWin; // Reset the scoreToWin variable with the value of tempScoreToWin.
Console.WriteLine("The score has been set to {0}.", scoreToWin); // Let the user know that the score has been changed successfully.
break; // Break out of the while loop.
}
else
{ // If the player has not put a correct integer in ...
Console.WriteLine("The score has been set at a default of {0}.", scoreToWin); // then the score will be set to the default value of scoreToWin
break; // Break out of the while loop.
}
}
Console.ReadLine();
Console.Clear();
//-----------------------------------------------------------------
Cheers!
Using TryParse will allow you to parse a string for an integer while also checking if it succeeded.
if(int.TryParse(_val, out tempScoreToWin)
{
//Parse succeeded
}
else
{
//Parse failed
}
Brilliant! That worked MrZander. Thank you guys so much for the quick answer. I really appreciate it :)
if (int.TryParse(_val, out tempScoreToWin))
{
if (tempScoreToWin > 0) // If the users input is higher than zero ...
{
scoreToWin = tempScoreToWin; // Reset the scoreToWin variable with the value of tempScoreToWin.
Console.WriteLine("The score has been set to {0}.", scoreToWin); // Let the user know that the score has been changed successfully.
break; // Break out of the while loop.
}
else
{ // If the player has not put a correct integer in ...
Console.WriteLine("The score has been set at a default of {0}.", scoreToWin); // then the score will be set to the default value of scoreToWin
break; // Break out of the while loop.
}
}
else
{
//Parse failed
}

FormatException C#

so I'm currently taking a course on C# programming to get freshened up.
Turned out I forgot some important things!
namespace FitnessFrog
{
class Program
{
static void Main()
{
int runningTotal = 0;
bool keepGoing = true;
while(keepGoing)
{
// Prompt the user for minutes exercised
Console.Write("Enter how many minutes you exercised or type \"quit\" to exit: ");
string input = Console.ReadLine();
if (input == "quit")
{
keepGoing = false;
}
else
{
try
{
int minutes = int.Parse(input);
runningTotal = runningTotal + minutes;
if(minutes <= 0)
{
Console.WriteLine("Eh, what about actually exercising then?");
continue;
}
else if(minutes <= 10)
{
Console.WriteLine("Better than nothing, am I right?");
}
else if (minutes <= 24)
{
Console.WriteLine("Well done, keep working!");
}
else if (minutes <= 60)
{
Console.WriteLine("An hour, awesome! Take a break, ok?");
}
else if (minutes <= 80)
{
Console.WriteLine("Woah, remember to drink if you're going to exercise THAT long!");
}
else
{
Console.WriteLine("Okay, now you're just showing off!");
}
Console.WriteLine("You've exercised for " + runningTotal + " minutes");
}
catch(FormatException)
{
Console.WriteLine("That is not valid input");
continue;
}
// Repeat until the user quits
}
}
}
}
}
So I'm trying to make it say "This is not valid input" when you type a string instead of an integer.
Thanks in advance! <3
int minutes = int.Parse(input); - you should use TryParse() instead of Parse()
int minutes;
bool parsed = int.TryParse(input, out minutes);
if (parsed)
{
// your if statements
}
else
{
Console.WriteLine("That is not valid input");
}
You should use int.TryParse instead for Parse, since it having internal exception handling mechanisms, And you can use it's return value(true/false)to check whether the operation is successful or not, for a successful conversion it will return true, and the return value for a failure conversion will be false
int minutes;
if(!int.TryParse(input,out minutes)
{
Console.WriteLine("invalid input");
}
else
{
// Proceed
}
If you are receiving input from your users, you will want to consider actually using the Int32.TryParse() method to determine if the parse was successful or not :
int minutes;
// Attempt the parse here
if(Int32.TryParse(input, out minutes))
{
// The parse was successful, your value is stored in minutes
}
else
{
// The parse was unsuccessful, consider re-prompting the user
}

Ending a loop by sentinel and parsing an input string as an integer

I am trying to continuously ask user for a number between 300-850. When the user enters a valid number, add it to the total and ask again. If the number is invalid, display an error. Before program ends, display the average of total number by amount of times of input. End program if user enters a sentinel value. I don't know how to check if user enters a sentinel value.
using System;
class CreditScores
{
static void Main()
{
var iterations = 0;
double total = 0;
int sum = 0;
double average = 0;
int count = 0;
Console.WriteLine("Enter value between 300 to 850.");
int first = int.Parse(Console.ReadLine());
//trying to get it to stop when sentinel value reached.
while (iterations < 1000)
{
iterations++;
Console.WriteLine("Enter value between 300 to 850.");
int input = int.Parse(Console.ReadLine());
//not sure how to check if input is a number or not
if(input == integer)
{
if( input < 850 && input > 300 )
{
total +=input;
}
}
else
{
break;
}
}
total = sum + total;
Console.WriteLine("Total is {0}", total);
average = total / count;
Console.WriteLine("The average is {0}", average);
}
}
Modification/fix of Your Method
Also, I would read all the way to the end for the more robust method you could use.
First thing I would change:
while (iterations < 1000)
{
...
}
To this (which we are not done yet, read to the end):
while (input != "calculate") // or some other string
{
...
}
Then, before the while starts, make input a string.
string input = "";
while (input != "calculate") // or some other string
{
...
}
Now, we declared an input variable that is already an int later on. Let's fix that.
Console.WriteLine("Enter value between 300 to 850.");
input = Console.ReadLine();
int value = 0;
if (int.TryParse(input, out value))
{
// Clearly it's a valid integer at this point
if (value < 850 && value > 300)
{
total += value;
}
}
else
{
// Wasn't a number, might be our sentinel.
if (input == "calculate")
break;
else
{
// Throw an error or something.
}
}
Now, we need to put it together and do some cleaning.
int total = 0;
int numbersEntered = 0;
string input = "";
while (input != "calculate")
{
Console.WriteLine("Enter value between 300 to 850.");
input = Console.ReadLine();
int value = 0;
if (int.TryParse(input, out value))
{
// Clearly it's a valid integer at this point
if (value < 850 && value > 300)
{
total += value;
numbersEntered++;
}
}
else
{
// Wasn't a number, might be our sentinel.
if (input == "calculate")
break;
else
{
// Throw an error or something.
}
}
}
Console.WriteLine("Total is {0}", total);
double average = (double)total / numbersEntered;
Console.WriteLine("The average is {0}", average);
(I know, long answer. But it should help you step through the problem in the future. Also, I wrote this all by memory, I can't guarantee it will compile.)
Update: just tested it, works as expected.
A more Robust Method
Lastly, and this is really the coolest method in my opinion, use a List<int> and some extension methods.
List<int> values = new List<int>();
string input = "";
while (input != "calculate")
{
Console.WriteLine("Enter value between 300 to 850.");
input = Console.ReadLine();
int value = 0;
if (int.TryParse(input, out value))
// Clearly it's a valid integer at this point
if (value < 850 && value > 300)
values.Add(value);
else
{
// Was outside our range
}
else
// Wasn't a number, might be our sentinel.
if (input == "calculate")
break;
else
{
// Throw an error or something.
}
}
Console.WriteLine("Total is {0}", values.Sum());
Console.WriteLine("The average is {0}", values.Average());
Advantages to this method? It saves a list of the values entered, allowing you to do more with them that you cannot do with the method you currently have. It also uses the int.Sum() and int.Average() extension methods rather than your own math.
What is this int.TryParse(string, out int) sorcery?
The int.TryParse(string, out int) method (as defined by MSDN) will take an input string, and return a boolean value that indicates if it would make a valid int structure or not.
In the case that the string is a valid int, then the int parameter is filled with the integer representation of the string.
I.e.:
string myString = "100";
int value = 0;
if (int.TryParse(myString, out value))
Console.WriteLine("myString was a valid int: {0}", value);
else
Console.WriteLine("myString was not a valid int.");
This version will return true and print: myString was a valid int: 100.
Example 2:
string myString = "blah";
int value = 0;
if (int.TryParse(myString, out value))
Console.WriteLine("myString was a valid int: {0}", value);
else
Console.WriteLine("myString was not a valid int.");
This version will return false, and print myString was not a valid int.. The value variable would also be 0.
Warning:
When using int.TryParse(string input, out int value), do not rely on the value parameter as 0 to indicate failure. If the input is "0", then the value will also be 0, and the method will return true.
You want to set the condition of your while loop to something that a user can trigger as false (the sentinel).
Then put a for loop inside that if you want to do a set number of iterations, for loops are better for situations where you know how many iterations you're doing.
BUT if you want to stick to while loops only, here's a quick code snippet you could use:
while (input != 0 && iterations < 1000) //or some sentinel value you choose
{
//Your logic here, now the loop will quit if if the user enters 0
//OR you run out of iterations
}
using System;
class CreditScores
{
static void Main()
{
double total = 0;
int sum = 0;
int count = 0;
Console.WriteLine("Enter value between 300 to 850.");
int first = int.Parse(Console.ReadLine());
//trying to get it to stop when sentihel value reached.
for (iterations = 0; iterations < 1000; iterations++)
{
Console.WriteLine("Enter value between 300 to 850.");
int input;
// Check number is integer
if (int.TryParse(Console.ReadLine(), out input)
{
if(input > 300 && input < 850)
{
total +=input;
}
}
else
{
break;
}
count++;
}
total = sum + total;
Console.WriteLine("Total is {0}", total);
double average = total/count;
Console.WriteLine("The average is {0}", average);
Console.ReadLine(); // Either this or run with Ctrl-F5
}
}
The behaviour would be to add the totals until the user entered something that couldn't be parsed, and then exit.
Does this work?
string sentinalValue = "done";
string input = "";
while (iterations < 1000 && input != sentinalValue)
{
iterations++;
Console.WriteLine("Enter value between 300 to 850.");
input = Console.ReadLine();
int value;
if (int.TryParse(input, out value))
{
if( value < 850 && value > 300 )
{
total +=input;
}
}
else
{
Console.WriteLine("That is not a number!");
}
}

Categories