I would like to use my variable i (that is used to sequence a loop) to name a record. This in order to know both how many of these records I have and to be able to loop through each one in a for loop.
This is how I have tried to do it:
while (UserValue != "none")
{
Console.WriteLine("Input a product Name or type \"none\" to exit.");
UserValue = Console.ReadLine();
if (UserValue == "none")
break;
Console.WriteLine("Input this products value in Pounds.");
products i = new(UserValue, float.Parse(Console.ReadLine()));
i = i + 1;
}
I'm not even sure if it is possible so if it isn't, any alternative solution would be greatly appreciated.
It seems, that you want a collection, say List<T> of items, e.g.
//TODO: decimal is better if "value" stands for money
// I used named tuple here, but you may want an elaborated custom class
var products = new List<(string name, float value)>();
// Keep asking user to input products until "none" is given
while (true) {
Console.WriteLine("Input a product Name or type \"none\" to exit.");
UserValue = Console.ReadLine();
//TODO: trim spaces and, probably, use case insensitive check
if (UserValue == "none")
break;
Console.WriteLine("Input this products value in Pounds.");
//TODO: float.TryParse is a better option
products.Add((UserValue, float.Parse(Console.ReadLine())));
}
then having collection you can loop over it:
for (int i = 0; i < products.Count; ++i) {
(string name, float value) = products[i];
...
}
or
foreach (var (name, value) in products) {
...
}
A better strategy is using a List<products>. Also, rename the products class to just product:
var allProducts = new List<product>();
// ...
Console.WriteLine("Input a product Name or type \"none\" to exit.");
UserValue = Console.ReadLine();
if (UserValue == "none")
break;
Console.WriteLine("Input this product's value in Pounds.");
allProducts.Add(new product(UserValue, float.Parse(Console.ReadLine())));
You can still loop over this allProducts list with either a for loop (look at the .Count property of the list) or a foreach loop.
Related
I want to create an application where the user can enter items and the price, then show the most expensive and the cheapest item.
I'm totally new to C# and have no programming experience of any language, started to learn 2,5 weeks ago. I don't understand how I can link the item with the price and then do the calculation. The penny hasn't dropped yet in terms of how I can build an application :(
ItemInput();
PricingInput();
}
private static void ItemInput()
{
Console.WriteLine("Add your items and price, once you're done, type 'end' ");
AskForTheItem();
AskForThePrice();
}
static void AskForTheItem()
{
while (itemPrice != "end")
{
Console.Write("Add your item:");
string item = Console.ReadLine();
Console.Write("Add the price:");
int price = int.Parse(Console.ReadLine());
itemPrice = Console.ReadLine();
}
Console.WriteLine("Add your item: ");
name = Console.ReadLine();
numberOfItems++;
}
static void AskForThePrice()
{
Console.WriteLine("Add the price: ");
price = int.Parse(Console.ReadLine());
numberOfPrice++;
}
private static void PricingInput()
{
Console.WriteLine($"The cheapest item is: {name} and the most expensive item is: {name} ");
private static void ItemInput()
{
PricingInput(AskForTheItem());
}
static Dictionary<String, int> AskForTheItem()
{
var result = new Dictionary<String, int>();
Console.WriteLine("Add your items and price, once you're done, type empty item ");
while (1)
{
Console.Write("Add your item or keep empty :");
string item = Console.ReadLine();
if(String.IsNullOrEmpty(item)) return result;
Console.Write("Add the price:");
while(!int.TryParse(out var price, Console.ReadLine()) Console.Write("Wrong price, please Add the price:");
result.Add(item, price);
}
}
private static void PricingInput(Dictionary<String,int> list)
{
String minItem = null;
int minPrice = -1;
String maxItem = null;
int maxPrice = -1;
foreach(var i in list) {
if(price<0 || i.Value<price) { minItem = i.Key; minPrice=i.Value;}
if( i.Value>price) { maxItem = i.Key; maxPrice=i.Value;}
Console.WriteLine($"The cheapest item is: {1} and the most expensive item is: {2} ",minItem,maxItem); }
Welcome to StackOverflow! Your question seems to be pretty broad but I think what you'd need is some first steps into object-oriented programming with classes.
Your code seems like a good start but for storing the information you'll need some objects.
You can create your own objects using a class. In this case you class would need a property for its name and one for it's price.
Defining the class would be as follows (you should do that in a new file):
class MyItem{
public string Name { get; set; }
public int Price { get; set; }
}
Then at the start of the class with the AskForTheItems method and probably also the Main method, you need to add a List to store the items. You'd do that like this:
private static List<MyItem> items = new List<MyItem>();
For the method which gets the items, you'll need to some adjustments. You also don't need the numberOfItems-variable anymore since you can just call items.Count if you need it.
private static void AskForTheItems()
{
do
{
Console.WriteLine("Add your item:");
// get the name
Console.Write("Name: ");
string name = Console.ReadLine();
// get and convert the price
Console.Write("Price: ");
int price = int.Parse(Console.ReadLine());
// create the item and fill it with the values
MyItem item = new MyItem();
item.Name = name;
item.Price = price;
// add the item to your list
items.Add(item);
// ask if the user want's to add another one
Console.WriteLine("Again? (y/n)");
}
while (Console.ReadKey(true).Key != ConsoleKey.N);
}
Printing the cheapest and most expensive one is fairly easy using Linq (there might even be an easier/better way).
private static void PrintCheapestAndMostExpensive() {
// get the first item where the price is the same as the minimum of all prices in the list
MyItem cheapestItem = items.First(i => i.Price == items.Min(i2 => i2.Price));
// get the first item where the price is the same as the maximum of all prices in the list
MyItem mostExpensiveItem = items.First(i => i.Price == items.Max(i2 => i2.Price));
Console.WriteLine($"The cheapest item is: {cheapestItem.Name} and the most expensive item is: {mostExpensiveItem.Name}");
}
I hope this helps. If you have any questions, feel free to ask - I'll try to explain anything you don't understand yet.
By the way there a are few things I didn't do/cover because I feel like it'd be a bit too much to explain for a small program like this. Currently there is no error handling when converting the input-string to an int (bad). There are also easier ways to write the initialisation for the item but I figured this way it's easier to understand.
Also with this code it always prints the first item which has the lowest price. If there are two which both have the lowest price, this might be a problem.
Linq itself is fairly hard (but very very important), that's why I would strongly reccomend you to read something about it. I'd happily explain the Linq I used here with more detail but since it's such a huge topic, I won't cover much more.
I am trying to compare if string that user inputs exists in list and if it does I would like to remove it from list.
I am getting an Error:
Argument 1: cannot convert from 'project.MainClass.Artical' to 'string'
I am aware that I am getting it because I am trying to compare string with list.
I have struct:
struct Artical {
public string name;
public float price;
public double weight;
}
And method:
static void DeleteArtical()
{
Artical k = new Artical();
Console.WriteLine("Enter name you want to delete: ");
k.name = Console.ReadLine();
List < Artical > articals = new List < Artical > ();
using(StreamWriter sw = File.AppendText((# "../../dat.txt"))) {
if (articals.Exists(x => string.Equals(x, k.name, StringComparison.OrdinalIgnoreCase))) {
Console.WriteLine("Done !!");
artikli.Remove(k);
}
}
}
x is underlined and gives me error that I mentioned above.
The error comes from the point that you are trying to comare an object of type Artical with a string. The x in your lambda expression represents one element from the List<Artical> so you need to access the property name with it, because this is what you want to compare:
if (articals.Exists(x => string.Equals(x.name, k.name, StringComparison.OrdinalIgnoreCase)))
Please note, that Remove :
Removes the first occurrence of a specific object from the List
Furthermore you need to make sure that all other values (price and weight) in the compare object have to match the one that you are trying to find, otherwise the item will not be removed!
EDIT:
what you could do is to pull out actually the struct that you are looking for using FirstOrDefault.
This method:
Returns the first element of the sequence that satisfies a condition or a default value if no such element is found.
The default value would be an empty struct with default values for each property. Knowing this you can then check for success of your finding procedure by checking wether name has a value at all. If you have successfully found the item you can now use the very same object to remove it from the list:
Artical objectForRemoval = articals.FirstOrDefault(x => string.Equals(x.name, k.name, StringComparison.OrdinalIgnoreCase));
if (!String.IsNullOrWhiteSpace(objectForRemoval.name))
{
Console.WriteLine("Done !!");
articals.Remove(objectForRemoval);
}
If you need to take the string the do not need to get it into the Article object. Instead use simple string.
And, in your code you are comparing the whole object with string so it throws the error. Change the x with x.name
static void DeleteArtical()
{
string input;
Console.WriteLine("Enter name you want to delete: ");
input = Console.ReadLine();
List < Artical > articals = new List < Artical > ();
using(StreamWriter sw = File.AppendText((# "../../dat.txt"))) {
if (articals.Exists(x => string.Equals(x.name, input, StringComparison.OrdinalIgnoreCase))) {
Console.WriteLine("Done !!");
artikli.Remove(k);
}
}
}
I'm wondering if I could use a few simple dictionaries to store the data behind this or if I need something more... Need a system to be able to add and remove items and have that translated to other menus (methods). Sorry if this is worded poorly
public int AddProducts(int customerIDinput)
{
//If the order already has 5 products then display an error that no more products can be added
//Prompts the user for a product ID
//If the user selects an invalid product then display an error
//If the user selects a product that is discontinued then display an error
//Prompt the user for a quantity
//If the user enters a value < 1 or > 100 then display an error
//Add the product and quantity to the order
//Display the updated order information
//Return to the main menu
int input;
input = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Please eneter a product ID:");
switch (customerIDinput)
{
case 1
break;
case 2
break;
case 3
break;
case 4
break;
case 5
break;
}
return customerIDinput;
}
You can use a generic List and switch the value entered by the user to be the INDEX Value of that list of products
a quick Example :
List<String> Products = new List<string>();
int Value = Int.Parse(Console.ReadLine());
switch(Value)
{
case 1:
if (Products.Item(1) == null)
Console.WriteLine("Doesnt Exist!"); // This check will be in all cases in the Default one of caus
break;
}
Or you can use that check in the first for example :
List<String> Products = new List<string>();
int Value = Int.Parse(Console.ReadLine());
if (Products.Items(Value) == null)
{
//Display Error
}
else
{
switch(Value)
{
case 1:
//what u want here
break;
}
}
I'd like to use the information gathered from ReadLine() in another code scope.
I've created a menu and I'm using an if-statement.
If I want to use the information gathered in option 1 in the menu, and write it into option 2, how do I go about doing that?
if (selectMenu == 1)
{
Console.WriteLine("What item will you put in the backpack?");
//Console.ReadLine();
string item = Console.ReadLine();
}
else if (selectMenu == 2)
{
}
So basically I want to be able to use item in the else if.
You could declare the variable in the outside scope:
string item = null;
if (selectMenu == 1)
{
Console.WriteLine("What item will you put in the backpack?");
item = Console.ReadLine();
}
else if (selectMenu == 2)
{
}
... you could use the item variable here but it will have its default value of null
if selectMenu was different than 1 because in this example we assign it
only inside the first if.
I'm saving Viewstates like this with several students:
ViewState[currentStudent] = currentGradesList;
But now i need to take all the viewstates to get the average of all grades, i've learnt to do it with strings like so:
foreach (string str in ViewState.Keys) {....} and that works.
But now when i try
foreach(List<double> grades in ViewState.Keys) {....}
the "grades" remain null and i get the error:
Unable to cast object of type 'System.String' to type 'System.Collections.Generic.List`1[System.Double]'.
I guess it says that Keys are strings, but how would i then get all the lists??
You are looping through the names of the keys in your foreach loop, not the actual values. You use the value of the foreach loop variable (which is now the name of a key in your ViewState dictionary) to go get the value from the viewstate.
Change your foreach loop to something like this
foreach(var key in ViewState.keys)[
var grades = ViewState[key] as List<double>;
//LINQ has built in Average and Sum abilities on lists
//I don't know what a CurrentStudentGrades looks like
//but here is an example of using the built in average
var studentAverage = grades.Average(x=>x.Grade);
//do whatever else you are wanting to do
}
foreach (string str in ViewState.Keys)
{
var grades = ViewState[str] as List<double>;
if(grades != null)
{
var average = grades.Average();
}
}
Solution:
I was looping through the names of the viewstate keys, not the values. So now i changed it to
Foreach (string str in ViewState.Keys)
{ //And then the value of "str"...
List<double> templist = (List<double>)ViewState[str];
And then the rest of my code which doesn't matter really but here it is to get average grade of each student, and all students together
foreach (double grade in templist)
{
currenttotal += grade;
}
currentaverage = currenttotal / templist.count;
AllAveragesList.add(currentaverage)
foreach (double average in AllAveragesList)
{
totalOfAll += average
}
averageOfAll = totalOfAll / AllAveragesList.count();`