using decimal values in user settings - c#

I'm having some troubles setting decimal values in the settings file, when it asks me for the type of variable I'm choosing the decimal and the default value is 0.10, this is to imitate 10 cents, but when I run my program and check the value of the variable it's showing as 0.01, this is because I should add an "m" at the end and that's not allowed in the settings file. is there some work-around for this?
also the user may set his/her own price that's entered in to a textbox, this for example could be 0.30 (30 cents) how can i convert the textbox value to 0.30m?
using a double is not an option, I don't want to end up with something like $2.99999999 decimal type is perfect if only I could use it in the settings file like I can hard-coded.
Thanks for replies.
public void beginUser(int tblSize)
{
decimal tblPrice = 0.00m;
int minCount = 0;
decimal curCost = 0.00m;
string timeStarted = string.Format("{0:HH:mm:ss tt}", DateTime.Now);
//Setup table price
switch (tblSize)
{
case 0:
tblPrice = Properties.Settings.Default.tblSmallPrice;
//tblPrice = 0.10m //this works
break;
case 1:
tblPrice = Properties.Settings.Default.tblBigPrice;
//tblPrice = 0.15m // this works
break;
default:
tblPrice = 0.10m;
break;
}
//Check how tblPrice appears.
MessageBox.Show(Convert.ToString(tblPrice));
try
{
while (true)
{
Thread.Sleep(100);
curCost += tblPrice;
minCount += 1;
if (minCount == 60) { Thread.CurrentThread.Abort(); }
}
}
catch (ThreadAbortException)
{
TimeSpan span = TimeSpan.FromMinutes(minCount);
string output = String.Format("Cost: €{0}\r\ncurCost: {1} hour(s) {2} minutes\r\nStarted: {3}", curCost, span.Hours, span.Minutes, timeStarted);
MessageBox.Show(output);
}
}

Use commas! It should work:
0.1 becomes 0,1.
Here you can see how I managed to insert it:

Related

C# do while loops - How to remember user input?

I'm new to C#, and i'm writing a do while loop that continues to ask the user to enter "price", until they enter "-1" for price.
Afterwards, I need to add up all the values for price they entered and declare that as the subtotal.
The problem I have is that it only remember the last number entered, which would be -1. What would I have to do to fix this?
using System;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
Console.WriteLine("Your Receipt");
Console.WriteLine("");
Console.WriteLine("");
decimal count;
decimal price;
decimal subtotal;
decimal tax;
decimal total;
count = 1;
do
{
Console.Write("Item {0} Enter Price: ", count);
++count;
price = Convert.ToDecimal(Console.ReadLine());
} while (price != -1);
subtotal = Convert.ToInt32(price);
Console.Write("Subtotal: ${0}", subtotal);
}
}
}
Try this variation to Artem's answer. I think this is a little cleaner.
int count = 0;
decimal input = 0;
decimal price = 0;
while (true)
{
Console.Write("Item {0} Enter Price: ", count++);
input = Convert.ToDecimal(Console.ReadLine());
if (input == -1)
{
break;
}
price += input;
}
In each iteration of the loop, you overwrite the value of price. Separate input and storage price.
decimal input = 0;
do
{
Console.Write("Item {0} Enter Price: ", count);
++count;
input = Convert.ToDecimal(Console.ReadLine());
if (input != -1)
price += input;
} while (input != -1);
Use a list and keep adding the entries to the list.
Or you can keep a running total in another integer.
Something like:
int total = 0; // declare this before your loop / logic other wise it will keep getting reset to 0.
total = total+ input;
Please try to use this
using System;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
Console.WriteLine("Your Receipt");
Console.WriteLine("");
Console.WriteLine("");
decimal count;
decimal price;
decimal subtotal = 0m; //subtotal is needed to be initialized from 0
decimal tax;
decimal total;
count = 1;
do
{
Console.Write("Item {0} Enter Price: ", count);
++count;
price = Convert.ToDecimal(Console.ReadLine());
if (price != -1) //if the console input -1 then we dont want to make addition
subtotal += price;
} while (price != -1);
//subtotal = Convert.ToInt32(price); this line is needed to be deleted. Sorry I didnt see that.
Console.Write("Subtotal: ${0}", subtotal); //now subtotal will print running total
}
}
}

input string was not in a correct format error

Here is the code:
public void calculations()
{
int value;
try
{
if ((string.IsNullOrEmpty(txtrate.Text)) || (string.IsNullOrEmpty(txttotalkm.Text)))
{
MessageBox.Show("Fill both the Values", "Try Again", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else if ((int.TryParse(txtrate.Text, out value)) && (int.TryParse(txttotalkm.Text, out value)))
{
int rate = int.Parse(txtrate.Text.Trim());
int km = int.Parse(txttotalkm.Text.Trim());
decimal gross = rate * km;
decimal NBT = (gross * 8 / 100);
decimal vat = ((gross + NBT) * 11 / 100);
decimal total = vat + NBT + gross;
string snbt = String.Format("{0:Rs 0.00}", NBT);
string svat = String.Format("{0:Rs 0.00}", vat);
string stotal = String.Format("{0:Rs 0.00}", total);
lblnbt.Visible = true;
lblnbt.Text = snbt;
lblvat.Visible = true;
lblvat.Text = svat;
lbltotal.Visible = true;
lbltotal.Text = stotal;
string ltnbt = lblnbt.Text.ToString();
string ltvat = lblvat.Text.ToString();
string lttotal = lbltotal.Text.ToString();
int inbt = Convert.ToInt32(lblnbt.Text);
int ivat = Convert.ToInt32(lblvat.Text);
int itotal = Convert.ToInt32(lbltotal.Text);
//CreateWordDocument(#"C:\temp\test.docx",
// #"C:\temp\new.docx");
clear();
}
else
{
MessageBox.Show("Wrong Values Please Check again", "Try Again", MessageBoxButtons.OK, MessageBoxIcon.Information);
clear();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
When running the program, it says:
input string was not in a correct format error
I must say I'm just trying to code and learn, not a pro, I just can't find out the issue.
Tried removing the try...catch box and see the exception it says this:
If there is an easier way to do this, just let me know.
The error is here:
//snbt, svat and stotal are not valid integers, because they
//are text formatted that start with "Rs"...
string snbt = String.Format("{0:Rs 0.00}", NBT);
string svat = String.Format("{0:Rs 0.00}", vat);
string stotal = String.Format("{0:Rs 0.00}", total);
lblnbt.Visible = true;
lblnbt.Text = snbt;
lblvat.Visible = true;
lblvat.Text = svat;
lbltotal.Visible = true;
lbltotal.Text = stotal;
string ltnbt = lblnbt.Text.ToString();
string ltvat = lblvat.Text.ToString();
string lttotal = lbltotal.Text.ToString();
//HERE the exception is triggered, because the "text" in the
//Labels start with "Rs".
int inbt = Convert.ToInt32(lblnbt.Text);
int ivat = Convert.ToInt32(lblvat.Text);
int itotal = Convert.ToInt32(lbltotal.Text);
To correct this, instead of converting AGAIN from the labels to integer, why not simply use NBT, VAT and TOTAL?
Or better, why do you need to reconvert to integers from the labels at all?
Parsing should be performed by always keeping the wrong format input as Exception raising cause. For the same in C#, there are clear solutions like.
•If you've got a string, and you expect it to always be an integer (say, if some web service is handing you an integer in string format), you'd use Int32.Parse().
•If you're collecting input from a user, you'd generally use Int32.TryParse(), since it allows you more fine-grained control over the situation when the user enters in invalid input.
•Convert.ToInt32() takes an object as its argument, and I believe it invokes Int32.TryParse() when it finds that the object taken as the argument is a string
If you only allow numeric values in your TextBox "txtrate" and "txttotalkm", you can use a "NumericUpDown" control. It only allows numeric inputs and so there is no need to use the parse methods.

C# warning: "The variable is assigned but its value is never used"

I am a first-timer learning C# and I just started writing my first program. I am currently running into a snag in one of my while loops. Normally I find that outside the loop my variables work like they should, but for some reason Visual Studio is giving me a warning saying that "The variable 'itemPrice' is assigned but its value is never used."
How I can I get that warning to go away and avoid any kind of bad practices?
using System;
class Program
{
public static void Main()
{
// "whoa" <-- string literal
// 43 <-- int literal
// 43.34 <-- double literal
// false <-- bool literal
// 43.4f <-- float literal
// 43f <-- float literal
// 43m <-- decimal literal
bool hasEnteredMoney = false;
decimal money = 0;
int menuSelection;
decimal itemPrice;
bool isValidItem;
string itemName;
while (!hasEnteredMoney)
{
Console.Write("Please enter how much money you have: ");
hasEnteredMoney = decimal.TryParse(Console.ReadLine(), out money);
if (!hasEnteredMoney)
{
Console.WriteLine("Please enter a valid decimal value.");
}
}
while (money >= 3)
{
Console.WriteLine("You have $" + money + " left.");
Console.WriteLine("Please enter your selection:");
Console.WriteLine("[0] - Poke Ball - $200");
Console.WriteLine("[1] - Great Ball - $700");
Console.WriteLine("[2] - Ultra Ball - $1200");
Console.WriteLine("[3] - Potion - $300");
Console.WriteLine("[4] - Antidote - $100");
Console.WriteLine("[5] - Clear Mail - $50");
Console.WriteLine(": ");
if (int.TryParse(Console.ReadLine(), out menuSelection))
{
isValidItem = false;
if (menuSelection == 0)
{
itemPrice = 200;
itemName = "Poke Ball";
isValidItem = true;
}
if (menuSelection == 1)
{
itemPrice = 700;
itemName = "Great Ball";
isValidItem = true;
}
if (menuSelection == 2)
{
itemPrice = 1200;
itemName = "Ultra Ball";
isValidItem = true;
}
if (menuSelection == 3)
{
itemPrice = 300;
itemName = "Potion";
isValidItem = true;
}
if (menuSelection == 4)
{
itemPrice = 100;
itemName = "Antidote";
isValidItem = true;
}
if (menuSelection == 5)
{
itemPrice = 50;
itemName = "Clear Mail";
isValidItem = true;
}
}
else
{
Console.WriteLine("Invalid input.");
}
}
Console.WriteLine("... you ran out of money :(");
Console.ReadKey();
}
}
The variables itemPrice, isValidItem, itemName are being set (being assigned to), but the variables are not being used for other purposes later in the program.
The compiler is warning you that although you are setting itemPrice, isValidItem, and itemName, setting these variables is not doing anything in the program - E.G. when the program is executed, the variables will not have any effect on the operation of the program.
It is giving you this error because your variables are never use in the code.
itemPrice = 200;
itemName = "Poke Ball";
isValidItem = true;
So visual studio intellisense is basicly saying : you putting all those values in your variables, but are never using any of them no where.
If you Console.WriteLine(itemName); at the end of you code, the warning should go away for all the itemName in you loop.
tl;dr You set; them but never get; them
The warning is a good indication that you should actually do something with the value. In your case, I think you would want to do something like
money -= itemPrice;
First, it will get rid of the warning.
Second, it will keep the while loop from running indefinitely :)

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!");
}
}

What does "Use of unassigned local variable" mean?

This question already has answers here:
Why did I get the compile error "Use of unassigned local variable"?
(10 answers)
Closed 4 days ago.
I keep getting this error for annualRate, monthlyCharge, and lateFee.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Lab_5___Danny_Curro
{
class Program
{
static void Main(string[] args)
{
string firstName;
string lastName;
int accNumber;
string creditPlan;
double balance;
string status;
Boolean late = false;
double lateFee;
double monthlyCharge;
double annualRate;
double netBalance;
Console.Write("Enter First Name: ");
firstName = Console.ReadLine();
Console.Write("Enter Last Name: ");
lastName = Console.ReadLine();
Console.Write("Enter Account Number: ");
accNumber = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter Credit Card Plan Number[Blank Will Enter Plan 0]: ");
creditPlan = Console.ReadLine();
Console.Write("Enter Balance: ");
balance = Convert.ToDouble(Console.ReadLine());
Console.Write("Is This Account Late?: ");
status = Console.ReadLine().Trim().ToLower();
if (creditPlan == "0")
{
annualRate = 0.35; //35%
lateFee = 0.0;
monthlyCharge = balance * (annualRate * (1 / 12));
return;
}
if (creditPlan == "1")
{
annualRate = 0.30; //30%
if (status == "y")
{
late = true;
}
else if (status == "n")
{
late = false;
}
if (late == true)
{
lateFee = 25.00;
}
monthlyCharge = balance * (annualRate * (1 / 12));
return;
}
if (creditPlan == "2")
{
annualRate = 0.20; //20%
if (status == "y")
{
late = true;
}
else if (status == "n")
{
late = false;
}
if (late == true)
{
lateFee = 35.00;
}
if (balance > 100)
{
monthlyCharge = balance * (annualRate * (1 / 12));
}
else
{
monthlyCharge = 0;
}
return;
}
if (creditPlan == "3")
{
annualRate = 0.15; //15%
lateFee = 0.00;
if (balance > 500)
{
monthlyCharge = (balance - 500) * (annualRate * (1 / 12));
}
else
{
monthlyCharge = 0;
}
return;
}
netBalance = balance - (lateFee + monthlyCharge);
Console.WriteLine("Name: \t\t\t {0} {1}", firstName, lastName);
Console.WriteLine("Account Number: \t{0}", accNumber);
Console.WriteLine("Credit Plane: \t\t{0}",creditPlan);
Console.WriteLine("Account Late: \t\t{0}", late);
Console.WriteLine("Balance: \t\t{0}", balance);
Console.WriteLine("Late Fee: \t\t{0}", lateFee);
Console.WriteLine("Interest Charge: \t{0}", monthlyCharge);
Console.WriteLine("Net Balance: \t\t{0}",netBalance);
Console.WriteLine("Annual Rate: \t\t{0}", annualRate);
Console.ReadKey();
}
}
}
The compiler isn't smart enough to know that at least one of your if blocks will be executed. Therefore, it doesn't see that variables like annualRate will be assigned no matter what. Here's how you can make the compiler understand:
if (creditPlan == "0")
{
// ...
}
else if (creditPlan == "1")
{
// ...
}
else if (creditPlan == "2")
{
// ...
}
else
{
// ...
}
The compiler knows that with an if/else block, one of the blocks is guaranteed to be executed, and therefore if you're assigning the variable in all of the blocks, it won't give the compiler error.
By the way, you can also use a switch statement instead of ifs to maybe make your code cleaner.
Change your declarations to this:
double lateFee = 0.0;
double monthlyCharge = 0.0;
double annualRate = 0.0;
The error is caused because there is at least one path through your code where these variables end up not getting set to anything.
Because if none of the if statements evaluate to true then the local variable will be unassigned. Throw an else statement in there and assign some values to those variables in case the if statements don't evaluate to true. Post back here if that doesn't make the error go away.
Your other option is to initialize the variables to some default value when you declare them at the beginning of your code.
Give them a default value:
double lateFee=0.0;
double monthlyCharge = 0.0;
double annualRate = 0.0;
Basically, all possible paths don't initialize these variables.
Use the keyword "default"!!!
string myString = default;
double myDouble = default;
if(!String.IsNullOrEmpty(myString))
myDouble = 1.5;
return myDouble;
There are many paths through your code whereby your variables are not initialized, which is why the compiler complains.
Specifically, you are not validating the user input for creditPlan - if the user enters a value of anything else than "0","1","2" or "3", then none of the branches indicated will be executed (and creditPlan will not be defaulted to zero as per your user prompt).
As others have mentioned, the compiler error can be avoided by either a default initialization of all derived variables before the branches are checked, OR ensuring that at least one of the branches is executed (viz, mutual exclusivity of the branches, with a fall through else statement).
I would however like to point out other potential improvements:
Validate user input before you trust it for use in your code.
Model the parameters as a whole - there are several properties and calculations applicable to each plan.
Use more appropriate types for data. e.g. CreditPlan appears to have a finite domain and is better suited to an enumeration or Dictionary than a string. Financial data and percentages should always be modelled as decimal, not double to avoid rounding issues, and 'status' appears to be a boolean.
DRY up repetitive code. The calculation, monthlyCharge = balance * annualRate * (1/12)) is common to more than one branch. For maintenance reasons, do not duplicate this code.
Possibly more advanced, but note that Functions are now first class citizens of C#, so you can assign a function or lambda as a property, field or parameter!.
e.g. here is an alternative representation of your model:
// Keep all Credit Plan parameters together in a model
public class CreditPlan
{
public Func<decimal, decimal, decimal> MonthlyCharge { get; set; }
public decimal AnnualRate { get; set; }
public Func<bool, Decimal> LateFee { get; set; }
}
// DRY up repeated calculations
static private decimal StandardMonthlyCharge(decimal balance, decimal annualRate)
{
return balance * annualRate / 12;
}
public static Dictionary<int, CreditPlan> CreditPlans = new Dictionary<int, CreditPlan>
{
{ 0, new CreditPlan
{
AnnualRate = .35M,
LateFee = _ => 0.0M,
MonthlyCharge = StandardMonthlyCharge
}
},
{ 1, new CreditPlan
{
AnnualRate = .30M,
LateFee = late => late ? 0 : 25.0M,
MonthlyCharge = StandardMonthlyCharge
}
},
{ 2, new CreditPlan
{
AnnualRate = .20M,
LateFee = late => late ? 0 : 35.0M,
MonthlyCharge = (balance, annualRate) => balance > 100
? balance * annualRate / 12
: 0
}
},
{ 3, new CreditPlan
{
AnnualRate = .15M,
LateFee = _ => 0.0M,
MonthlyCharge = (balance, annualRate) => balance > 500
? (balance - 500) * annualRate / 12
: 0
}
}
};
Your assignments are all nested within your conditional if blocks which means that there is potential for them to never be assigned.
At the top of your class, initialise them to 0 or some other value
The compiler is saying that annualRate will not have a value if the CreditPlan is not recognised.
When creating the local variables ( annualRate, monthlyCharge, and lateFee) assign a default value (0) to them.
Also, you should display an error if the credit plan is unknown.
Not all code paths set a value for lateFee. You may want to set a default value for it at the top.
You don't assign values outside of the if statements ... and it is possible that credit might be something other than 0, 1, 2, or 3, as #iomaxx noted.
Try changing the separate if statements to a single if/else if/else if/else. Or assign default values up at the top.
If you declare the variable "annualRate" like
class Program
{
**static double annualRate;**
public static void Main() {
Try it..

Categories