I have a dvd app that stores dvds and blu-rays, I want to search the arrays by director. Below is the code for the inventory class I have seen many different ways to do this. There seems to be some debate as the best/most efficient way to accomplish this, any suggestions?
Blockquote
namespace MovieInventoryApplication
{
class Inventory
{
public Bluray[] BlurayMovies;
public DVD[] DVDMovies;
private int blurayCount;
private int dvdCount;
public Inventory()
{
BlurayMovies = new Bluray[5];
DVDMovies = new DVD[5];
blurayCount = 0;
dvdCount = 0;
}
public void AddBluray()
{
String strTitle;
int intReleaseYear;
int intRunningTimeMinutes;
String strDirector;
int intPrice;
int intRegionCode;
try
{
Console.Write("Enter a title: ");
strTitle = Console.ReadLine();
Console.Write("Enter a release year: ");
intReleaseYear = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the running time in minutes: ");
intRunningTimeMinutes = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the directors name: ");
strDirector = Console.ReadLine();
Console.Write("Enter a rental price: ");
intPrice = Convert.ToInt32(Console.ReadLine());
BlurayMovies[blurayCount] = new Bluray(strTitle, intReleaseYear, intRunningTimeMinutes, strDirector, intPrice);
blurayCount++;
Console.Write("Enter the DVD region code: ");
intRegionCode = Convert.ToInt32(Console.ReadLine());
DVDMovies[dvdCount] = new DVD(strTitle, intReleaseYear, intRunningTimeMinutes, strDirector, intPrice, intRegionCode);
dvdCount++;
}
catch (FormatException FormatException)
{
Console.WriteLine(FormatException.Message);
Console.WriteLine("Please enter a number in this field.");
}
}
public void AddDVD()
{
String strTitle;
int intReleaseYear;
int intRunningTimeMinutes;
String strDirector;
int intPrice;
int intRegionCode;
try
{
Console.Write("Enter a title: ");
strTitle = Console.ReadLine();
Console.Write("Enter a release year: ");
intReleaseYear = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the running time in minutes: ");
intRunningTimeMinutes = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the directors name: ");
strDirector = Console.ReadLine();
Console.Write("Enter a rental price: ");
intPrice = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the region code: ");
intRegionCode = Convert.ToInt32(Console.ReadLine());
DVDMovies[dvdCount] = new DVD(strTitle, intReleaseYear, intRunningTimeMinutes, strDirector, intPrice, intRegionCode);
dvdCount++;
}
catch (FormatException FormatException)
{
Console.WriteLine(FormatException.Message);
Console.WriteLine("Please enter a number in this field.");
}
}
public void ListAllBluray()
{
int position = 0;
while (BlurayMovies[position] != null)
{
Console.WriteLine(position + " " + BlurayMovies[position].strTitle);
position++;
}
}
public void ListAllDVD()
{
int position = 0;
while (DVDMovies[position] != null)
{
//position + 1 + " " +
Console.WriteLine(position + " " + DVDMovies[position].strTitle);
position++;
}
}
public void BlurayInfo(int position)
{
Console.WriteLine("Title: {0}", DVDMovies[position].strTitle);
Console.WriteLine("Release Year: {0}", DVDMovies[position].intReleaseYear);
Console.WriteLine("Running Time (Minutes): {0}", DVDMovies[position].intRunningTimeMinutes);
Console.WriteLine("Director: {0}", DVDMovies[position].strDirector);
Console.WriteLine("Price: {0}", DVDMovies[position].intPrice);
}
public void DVDInfo(int position)
{
Console.WriteLine("Title: {0}", DVDMovies[position].strTitle);
Console.WriteLine("Release Year: {0}", DVDMovies[position].intReleaseYear);
Console.WriteLine("Running Time (Minutes): {0}", DVDMovies[position].intRunningTimeMinutes);
Console.WriteLine("Director: {0}", DVDMovies[position].strDirector);
Console.WriteLine("Price: {0}", DVDMovies[position].intPrice);
Console.WriteLine("Region Code: {0}", DVDMovies[position].intRegionCode);
}
}
}
I think you have a flaw in the design.
The DVD and BluRay classes really should be either:
A single class with a Type property, probably an enum that would contain DVD and BluRay. This way, in several years once you get a new media, you can just add a value to the Enum and your application will be up to date.
Two different classes that implement a custom interface that you could call, say, IMedia.
Also, I highly suggest you take advantage of the List object in C# instead of arrays. It's very fast and you can add/remove items easily without having to resize your array.
Here's a lesson on Linq: http://www.functionx.com/csharp/linq/Lesson09.htm
Here's how I would create the Media class:
public class Media
{
public enum MediaType
{
DVD,
Bluray
}
public MediaType TypeOfMedia { get; set; }
public string Director { get; set; }
public string Title { get; set; }
public Media(string Title, string Director, MediaType TypeOfMedia)
{
this.TypeOfMedia = TypeOfMedia;
this.Director = Director;
this.Title = Title;
}
}
And here's an example how to use it:
List<Media> data = new List<Media>();
results.Add(new Media("Movie 1", "John D", Media.MediaType.DVD));
results.Add(new Media("Movie 2", "John D", Media.MediaType.DVD));
results.Add(new Media("Movie 3", "SomeOtherDirector", Media.MediaType.Bluray));
results.Add(new Media("Movie 4", "John D", Media.MediaType.Bluray));
IEnumerable<Media> listDirectors = from media in data
where media.Director == "John D"
select media;
foreach (Media media in listDirectors)
Console.WriteLine(media.Title);
Another example, your "List DVD" and "List Bluray" functions could really be a single function:
private void ListMediaByType(List<Media> data, Media.MediaType type)
{
foreach (Media media in data.Where(media => media.TypeOfMedia == type))
Console.WriteLine(media.Title);
}
As you see, these techniques simplifies querying by a LOT. :)
The most easies (imho) is using Linq:
string director = "Alfred Hitchcock";
IEnumerable<DVD> dvds = DVDMovies.Where(dvd => dvd.Director == director);
IEnumerable<DVD> blueRays = BlurayMovies.Where(br => br.Director == director);
List<DVD> allMatches = new List<DVD>();
allMatches.AddRange(dvds.Concat(blueRays));
Related
I have to create a function that enables me to enter data for every customer in a hardware store. The data that I should enter for every customer is: first name, last name, product bought and its price. This data should be stored in an array. Have this function declare a 1D container, have the user initialise this 1D container with the above data, and have the function return this 1D container back to MAIN. In MAIN, invoke this function three times to create data for 3 customers.
Afterwards, I need to create another function that takes all three 1D containers of customer data from MAIN as parameters and adds up all the prices of the products they bought. Have this function return the total cost back to MAIN. (This is where I'm stuck.)
Lastly, I need to create a procedure that takes the total cost returned to MAIN as parameter and figures out if this total price(set to a simple integer) is a prime number:
if the value is prime, print: "Customers win the Price"
otherwise, print: "Customers won't get the price"
I am stuck on the second function, I tried to do a C-style for loop, but it doesn't work.
I tried to add these three prices as array positions with indices but nothing.
This is the code I have:
using System;
namespace ghghh
{
class Program
{
public static string [] inputData()
{
Console.WriteLine("Please enter your first name: ");
string FirstName = Console.ReadLine();
Console.WriteLine("Please enter your last name: ");
string LastName = Console.ReadLine();
Console.WriteLine("Please enter the product you ahve bought: ");
string product = Console.ReadLine();
Console.WriteLine("Please enter the price: ");
string price = Console.ReadLine();
string[] info = new string[4] { FirstName, LastName, product, price };
return info;
}
public static void sumOfPrice(string[] arr)
{
for(int i = 0; i<arr.Length; i++)
{
string sum = arr[i] + arr[i] + arr[i];
}
}
public static void isTotalCostPrime(int n)
{
if(n %2 == 0)
{
Console.WriteLine("Customers wont get get the prize.");
}
else
{
Console.WriteLine("Customers win the prize");
}
}
public static void Main (string[] args)
{
string[] final = inputData();
sumOfPrice(final);
}
}
}
Here you go with a partial solution to your problem. I made the prices decimal numbers (because most currencies are decimalized). That precludes your prime test at the end.
I also included a quantity. I was tempted to take out the first and last names for each item (since it requires a lot of typing). All in all, though, this should give you enough to get started.
I start with a POCO class to hold the purchased items (POCO stands for "Plain Old CLR Object"; it's a class that consists purely of properties. It's a bit like an old-fashioned C struct.
public class PurchasedItem
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
}
I separated the user interface out into a separate class (for reasons of separation of concerns). You could easily collapse this into a single class:
public class ItemUserInterface
{
public static PurchasedItem PromptForItem()
{
var purchasedItem = new PurchasedItem();
Console.Write("What is your First Name (or type \"exit\" if complete)? > ");
var firstName = Console.ReadLine();
if (firstName.Equals("exit", StringComparison.OrdinalIgnoreCase))
{
return null;
}
purchasedItem.FirstName = firstName;
Console.Write("What is your Last Name? > ");
purchasedItem.LastName = Console.ReadLine();
Console.Write("What did you purchase? > ");
purchasedItem.ProductName = Console.ReadLine();
purchasedItem.Quantity = PromptForInteger("How many did you buy");
purchasedItem.Price = PromptForDecimal("What was the price");
Console.WriteLine(""); //empty line
return purchasedItem;
}
public static void ShowPurchase (PurchasedItem item)
{
Console.WriteLine($"{item.FirstName} {item.LastName} bought {item.Quantity} of {item.ProductName} at {item.Price} each");
}
public static int PromptForInteger(string prompt)
{
while (true)
{
Console.Write(prompt + " > ");
var entered = Console.ReadLine();
if (int.TryParse(entered, out var result))
{
return result;
}
//otherwise error
Console.WriteLine("Sorry, you must enter a proper integer value");
}
}
public static decimal PromptForDecimal(string prompt)
{
while (true)
{
Console.Write(prompt + " > ");
var entered = Console.ReadLine();
if (decimal.TryParse(entered, out var result))
{
return result;
}
//otherwise error
Console.WriteLine("Sorry, you must enter a proper decimal value");
}
}
}
By the way, while (true) will loop forever unless you do something like return or break out of the loop. Notice that I prompt the user over and over again until he/she enters a correctly formatted number (for the number entries).
Finally, here's my Main routine:
var itemsList = new List<PurchasedItem>();
while (true)
{
var item = ItemUserInterface.PromptForItem();
if (item == null)
{
break;
}
itemsList.Add(item);
}
// at this point, everything is entered
var totalPurchasePrice = 0.00m;
var totalItemsCount = 0;
foreach (var item in itemsList)
{
ItemUserInterface.ShowPurchase(item);
totalPurchasePrice += (item.Quantity * item.Price);
totalItemsCount += item.Quantity;
}
Console.WriteLine($"Purchase Summary: {itemsList.Count} different items ({totalItemsCount} total items) for {totalPurchasePrice:C}");
Console.ReadLine(); //pause
}
If I run this program the output looks like:
What is your First Name (or type "exit" if complete)? > Fly
What is your Last Name? > Dog57
What did you purchase? > Cabbage
How many did you buy > 2
What was the price > 1.99
What is your First Name (or type "exit" if complete)? > Fly
What is your Last Name? > Dog57
What did you purchase? > Hammer
How many did you buy > 6
What was the price > abc
Sorry, you must enter a proper decimal value
What was the price > 10.55
What is your First Name (or type "exit" if complete)? > exit
Fly Dog57 bought 2 of Cabbage at 1.99 each
Fly Dog57 bought 6 of Hammer at 10.55 each
Purchase Summary: 2 different items (8 total items) for $67.28
I have Pokemon.cs here:
using System;
using System.Collections.Generic;
namespace PokemonPocket{
public class PokemonMaster{
public string Name {get;set;}
public int NoToEvolve {get; set;}
public string EvolveTo {get; set;}
public PokemonMaster(string name, int noToEvolve, string evolveTo){
this.Name = name;
this.NoToEvolve = noToEvolve;
this.EvolveTo = evolveTo;
}
}
}
and I have created this program here called Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
namespace PokemonPocket
{
class Program
{
static void Main(string[] args)
{
//PokemonMaster list for checking pokemon evolution availability.
List<PokemonMaster> pokemonMasters = new List<PokemonMaster>(){
new PokemonMaster("Pikachu", 2, "Raichu"),
new PokemonMaster("Eevee", 3, "Flareon"),
new PokemonMaster("Charmander", 1, "Charmeleon")
};
// Use "Environment.Exit(0);" if you want to implement an exit of the console program
PokemonMenu(pokemonMasters);
}
static void PokemonMenu(List<PokemonMaster> pokemans)
{
// From now on myDictionary is available for any menu option
var myDictionary = new Dictionary<string, string>();
while (true)
{ // <- loop until exit option (key 'Q') is pressed
Console.WriteLine("Welcome to Pokemon Pocket App!");
Console.WriteLine("(1). Add Pokemon to my pocket");
Console.WriteLine("(2). List Pokemon(s) in my pocket");
Console.WriteLine("(3). Check if I can evolve Pokemon");
Console.WriteLine("(4). Evolve Pokemon\n");
Console.Write("Please only enter [1,2,3,4] or Q to exit:");
char menu = Convert.ToChar(Console.ReadLine());
if (menu == '1')
{ //Part 1
Console.Write("Enter Pokemon Name :");
string name = Console.ReadLine();
Console.Write("Enter Pokemon HP : ");
int hp = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter Pokemon EXP : ");
int exp = Convert.ToInt32(Console.ReadLine());
if (myDictionary.Count <= 0)
{
myDictionary.Add("Pokemon's Name", name);
myDictionary.Add("Pokemon's HP", hp.ToString());
myDictionary.Add("Pokemon's EXP", exp.ToString());
Console.WriteLine("Pokemon has been added!");
}
}
else if (menu == '2')
{ //Part 2
foreach (var v in myDictionary)
Console.WriteLine(string.Format("{1}: {0}", v.Value, v.Key));
}
else if (menu == '3') //Part 3
{
if (!myDictionary.TryGetValue("Pokemon's Name", out var myPokemon))
{
// No pokemon in pocket so just exit
Console.WriteLine("You have no pokemon!");
continue;
}
var matchedPokemon = pokemans.Find(p => p.Name == myPokemon);
if (matchedPokemon != default)
{
Console.WriteLine("Can evolve a pokeman!");
Console.WriteLine($"{matchedPokemon.Name} --> {matchedPokemon.EvolveTo}");
}
}
else if (menu == 'Q')
{
Console.WriteLine("App exited!");
Environment.Exit(0);
}
}
}
}
}
After adding the Pokemon in 1, when I input 2 this is what the program displays:
Pokemon's Name: Charmander
Pokemon's HP: 20
Pokemon's EXP: 30
When I input 4, I want the name to be overrided into Charmeleon, something like evolution in original Pokemon. Then when I input 2, I want it to display this:
Pokemon's Name: Charmeleon
Pokemon's HP: 0 //hp will become 0 when evolved
Pokemon's EXP: 0 //hp will become 0 when evolved
Pokemon's Skill = Solar power //skill will now be there as original input doesnt have skill
How do i do so?
You won't be able to update it, but you could do something like
Read in the pokemon's Value (TryGetValue)
Remove the existing Key (Remove)
Add the value back in with the new key (the new name) (Add)
Because Key of a Dictionary cannot be updated
I've only been learning for a few weeks and I'm still at the beginning. To practice I wrote a small program that prompts for a score and a name, then compares it and gives feedback. see here:
static int highscore = 1000;
static void Main(string[] args)
{
///////////////////////////////////
Console.WriteLine("\n\nDer aktuelle Highscor ist: {0} \n\n ", highscore);
Console.Write("\nBitte gib Deinen Score ein:\t");
int score = Convert.ToInt32(Console.ReadLine());
Console.Write("\nBitte gib Deinen Namen ein:\t");
string spielerName = Console.ReadLine();
string highscoreSpielerName;
if (score <= highscore)
{
Console.WriteLine("\n\nPech gehabt {0}, Du hast keinen neuen Highscore.", spielerName);
}
else if (score > highscore)
{
int newHigsore = highscore + score - 1000;
int divHighscore = score - 1000;
Console.Clear();
Console.WriteLine("\n\nHerzlichen Glückwunsch, der neue Highscore ist {0} Punkte !! ", newHigsore);
Console.WriteLine("\n\nDer alte Highscore war {0} Pnkte und wurde um {1} Punkte übertroffen.", highscore, divHighscore);
Console.WriteLine("\n\n{0} hät den neuen Highscore mit {1} Punkten !", spielerName, newHigsore);
}
Console.ReadKey();
}
}
Now I want to extend it as follows:
The input should be stored in a file (array,list), sorted by the highest score, then the following output should be made:
You are among the top-ten, output whole list with ranking.
Or
Bad luck, you have no new highscore.
Since I don't know much about arrays, saving and overwriting, I'm stuck here. Would be nice if you could help me here. This is my approach so far:
static void Main(string[] args)
{
String[] zeilen = File.ReadAllLines(#"F:\visual Projekte\NeuDatenLesen\bin\Testdaten\Gewinner.CSV");
foreach (string zeile in zeilen)
{
string[] daten = zeile.Split(';');
double rang = double.Parse(daten[0]);
string name = daten[1];
double punkte = double.Parse(daten[2]);
Console.WriteLine("Platz {0}\t{1}\tPunkte {2}", rang, name, punkte);
Console.ReadLine();
You may want to use objects.
Once objects are created, tools for Lists can be used.
Included here is a nugget for Newtonsoft.Json (used to serialize for file)
Also the use of Linq.
public class Scores
{
public string Name { get; set; }
public int Score { get; set; }
}
class Program
{
static void Main(string[] args)
{
var ScoreList = new List<Scores>();
ScoreList.Add(new Scores() { Name = "Alpha", Score = 98324 });
ScoreList.Add(new Scores() { Name = "Bravo", Score = 88099 });
ScoreList.Add(new Scores() { Name = "Charlie", Score = 12012 });
ScoreList.Add(new Scores() { Name = "Delta", Score = 76590 });
ScoreList.Add(new Scores() { Name = "Echo", Score = 87199 });
ScoreList.Add(new Scores() { Name = "Foxtrot", Score = 99832 });
ScoreList.Add(new Scores() { Name = "Golf", Score = 20204 });
ScoreList.Add(new Scores() { Name = "Hotel", Score = 37209 });
ScoreList.Add(new Scores() { Name = "India", Score = 08732 });
ScoreList.Add(new Scores() { Name = "Juliett", Score = 78782 });
ScoreList.Add(new Scores() { Name = "Kilo", Score = 99120 });
ScoreList.Add(new Scores() { Name = "Lima", Score = 76555 });
var saveScores = JsonConvert.SerializeObject(ScoreList);
File.WriteAllText(#"C:\work\Scores.json", saveScores);
// read existin file
var fileRead= File.ReadAllText(#"C:\work\Scores.json");
List<Scores> existingScores = JsonConvert.DeserializeObject<List<Scores>>(fileRead);
var highScores = existingScores.OrderByDescending(o => o.Score).Take(10).ToList();
}
}
I just started doing some C# and gave myself the task of making a simple console-based coffee shop programme that just simply makes a list of what you want and then outputs it back to you when you put it all in. The only way I have found so far that has worked well for me has been to do this:
string Tea = "tea";
string Option1 = Console.ReadLine();
if ((Option1 == Tea)
{
Console.Clear();
//Confirmation Text
Console.WriteLine("So you want a " + Option1 + ".");
//Second Question
Console.WriteLine("Do you want milk, sugar, both or none?");
//Second Option
string Option2 = Console.ReadLine();
//Milk
if (string.Equals(Milk, Option2))
{
Console.Clear();
//Confirmation Text
Console.WriteLine("So you want a " + Option1 + " with " + Option2 + ".");
//Third Question
Console.WriteLine("And so what size will that be, small, medium, or large?");
//Third Option
string Option3 = Console.ReadLine();
if (string.Equals(Large, Option3))
{
Console.Clear();
//Last Confirmation
Console.WriteLine("Here is your " + Option3 + " " + Option1 + " with " + Option2 + ".");
Console.ReadKey();
}
else if (string.Equals(Medium, Option3))
{
Console.Clear();
//Last Confirmation
Console.WriteLine("Here is your " + Option3 + " " + Option1 + " with " + Option2 + ".");
Console.ReadKey();
}
else if (string.Equals(Small, Option3))
{
Console.Clear();
//Last Confirmation
Console.WriteLine("Here is your " + Option3 + " " + Option1 + " with " + Option2 + ".");
Console.ReadKey();
}
else Console.WriteLine("Sorry that is not one of our sizes.");
}
But this seems like far too much code to do a simple task as I keep having to repeat things over and over again. I have tried to look up other methods but I can't seem to grasp how you implement them into what I'm trying to do. And also implementing a loop was also a goal but I couldn't figure that out either.
Generally in software development if you are reusing the same code over and over again you should move that code into a method.
My following solution is far from perfect because I have had to use static methods due to accessing the methods I have wrote from the "main" class which is static itself. It would have been much better for me to have created a class to handle the logic and instantiate that class.
Considering you say you are new to programming I have avoided doing anything that might be confusing and instead tried to just reuse the code where possible just to demonstrate code reuse.
Here is my solution to your problem:
using System;
class MainClass {
public static void Main (string[] args) {
string Option1 = Console.ReadLine();
if (Option1 == "Tea")
{
string[] questionSet1 = { "So you want a " + Option1 + ".",
"Do you want milk, sugar, both or none?"};
//Confirmation Text
string Option2 = PrintTextArray(questionSet1);
//Milk
if (Option2.Equals("Milk"))
{
string[] questionSet2 = { "So you want a " + Option1 + " with " + Option2 + ".",
"And so what size will that be, small, medium, or large?"};
//Confirmation Text
string Option3 = PrintTextArray(questionSet2);
if (Option3.Equals("Large"))
{
//Last Confirmation
PrintText("Here is your " + Option3 + " " + Option1 + " with " +
Option2 + ".");
}
else if (Option3.Equals("Medium"))
{
//Last Confirmation
PrintText("Here is your " + Option3 + " " + Option1 + " with " + Option2 + ".");
}
else if (Option3.Equals("Small"))
{
//Last Confirmation
PrintText("Here is your " + Option3 + " " + Option1 + " with " + Option2 + ".");
}
else Console.WriteLine("Sorry that is not one of our sizes.");
}
}
}
private static string PrintText(string textToPrint)
{
string[] textListToPrint = { textToPrint };
return PrintTextArray(textListToPrint);
}
private static string PrintTextArray(string[] textListToPrint)
{
Console.Clear();
for(int i = 0; i < textListToPrint.Length; i++)
{
Console.WriteLine(textListToPrint[i]);
}
return Console.ReadLine();
}
}
Basically I have wrote two methods, one of them being an overloaded method, which takes a string or array of strings, prints them out and returns the next key press.
I am not going to sit and pretend that this is the perfect solution because a method should only do one thing according to the Single Reponsibility Principle but, again, considering you are new to programming I was trying to avoid over complicating it. I would highly recommend studying the SOLID Principles.
Finally, a couple of pointers, in C# a method should be declared starting with a capital letter for it's name and variables should be declared using the camel case convention. Find more information on camel case Here
That is indeed a lot of duplicated code for a simple program.
Here are some suggestions to clarify the intent and simplify the implementation.
1. Separate your state from the application flow.
Right now, the more options you would add, the deeper your if conditions would become.
Try creating data types that represent your state. Here is a suggestion:
public enum OrderType
{
Tea,
Coffee
}
public class Order
{
/// <summary>
/// The type of this order (either tea or coffee).
/// </summary>
public OrderType Type { get; set; }
/// <summary>
/// The list of all options for your order. (Example ["Milk", "Sugar"])
/// </summary>
public List<string> Options { get; } = new List<string>();
}
2. Clarify your application flow / intent
Use methods with clear names do create your application flow. Here's an example:
static void Main(string[] args)
{
while (true)
{
var order = new Order();
Console.WriteLine("Hello, would you like tea or coffee?");
// Read the order type from the user.
order.Type = ReadOrderType();
// Get the options available for that order type.
var availableOptions = GetAvailableOptionsFor(order.Type);
// Print the order type and the available options for that order type.
Console.WriteLine($"{order.Type}, all right! Would you like something in it?");
// Get the chosen options from the user.
order.Options = ReadChosenOptions(order.Type, availableOptions);
if (order.Options.Any())
{
// Print the order with options.
Console.WriteLine($"Okay so that's a {order.Type} with {string.Join(", ", order.Options)}. See ya!");
}
else
{
// Print the order without options.
Console.WriteLine($"Okay so that's a plain {order.Type}. Have a great day!");
}
}
}
3. Create methods to read user input.
That allows you to reuse code instead of repeating it. Here's an example:
private static OrderType ReadOrderType()
{
var orderType = Console.ReadLine();
switch (orderType.ToUpper())
{
case "TEA":
return OrderType.Tea;
case "COFFEE":
return OrderType.Coffee;
default:
Console.WriteLine($"I'll assume coffee.");
return OrderType.Coffee;
}
}
Full code example
Here's the full console application I wrote to help me answer.
class Program
{
static void Main(string[] args)
{
while (true)
{
var order = new Order();
Console.WriteLine("Hello, would you like tea or coffee?");
// Read the order type from the user.
order.Type = ReadOrderType();
// Get the options available for that order type.
var availableOptions = GetAvailableOptionsFor(order.Type);
// Print the order type and the available options for that order type.
Console.WriteLine($"{order.Type}, all right! Would you like something in it?");
// Get the chosen options from the user.
order.Options = ReadChosenOptions(order.Type, availableOptions);
if (order.Options.Any())
{
// Print the order with options.
Console.WriteLine($"Okay so that's a {order.Type} with {string.Join(", ", order.Options)}. See ya!");
}
else
{
// Print the order without options.
Console.WriteLine($"Okay so that's a plain {order.Type}. Have a great day!");
}
}
}
private static List<string> ReadChosenOptions(OrderType orderType, List<string> availableOptions)
{
var options = new List<string>();
bool areMoreOptionsDesired = ReadYesOrNo();
if (!areMoreOptionsDesired)
{
// Return no options;
return options;
}
while (areMoreOptionsDesired)
{
Console.WriteLine($"Here are our options: {string.Join(", ", availableOptions)}.");
var option = ReadOption(availableOptions);
if (option != null)
{
options.Add(option);
Console.WriteLine($"So far you got a {orderType} with {string.Join(", ", options)}.");
}
Console.WriteLine($"Would you like something else in it?");
areMoreOptionsDesired = ReadYesOrNo();
}
return options;
}
private static string ReadOption(List<string> availableOptions)
{
var input = Console.ReadLine();
if (availableOptions.Contains(input, StringComparer.OrdinalIgnoreCase))
{
return input;
}
else
{
Console.WriteLine($"{input} is not a valid option.");
return null;
}
}
private static bool ReadYesOrNo()
{
var desicion = Console.ReadLine();
if (desicion.ToUpper() == "YES")
{
return true;
}
else if (desicion.ToUpper() == "NO")
{
return false;
}
else
{
Console.WriteLine($"I'll take that as a \"no\".");
return false;
}
}
private static List<string> GetAvailableOptionsFor(OrderType orderType)
{
switch (orderType)
{
default:
case OrderType.Tea:
return new List<string>() { "Milk", "Sugar" };
case OrderType.Coffee:
return new List<string>() { "Milk", "Sugar", "Cream" };
}
}
private static OrderType ReadOrderType()
{
var orderType = Console.ReadLine();
switch (orderType.ToUpper())
{
case "TEA":
return OrderType.Tea;
case "COFFEE":
return OrderType.Coffee;
default:
Console.WriteLine($"I'll assume coffee.");
return OrderType.Coffee;
}
}
}
public enum OrderType
{
Tea,
Coffee
}
public class Order
{
/// <summary>
/// The type of this order (either tea or coffee).
/// </summary>
public OrderType Type { get; set; }
/// <summary>
/// The list of all options for your order. (Example ["Milk", "Sugar"])
/// </summary>
public List<string> Options { get; set; }
}
Since you're just starting out, I'd ignore Object Oriented Programming for now and focus on how to make your code not only easy to follow, but simple enough to add new drinks to your system.
The first thing I'd do is create a function that displays a list of options to be presented to the user, and doesn't allow them to leave until they've entered a valid response from that list of options. This will allow you to focus on the "flow" of the main program and not clutter it up with repeated hard-coded menus for each part of the system.
Here is a function that receives a prompt and a string array of options:
static int getMenuResponse(string prompt, string[] options)
{
while(true)
{
Console.WriteLine();
Console.WriteLine(prompt);
for(int i=0; i<options.Length; i++)
{
Console.WriteLine($"[{i+1}] {options[i]}");
}
Console.Write("Your choice: ");
string response = Console.ReadLine();
int option;
if (int.TryParse(response, out option) && option>=1 && option<=options.Length)
{
return (option-1);
}
Console.WriteLine("Invalid Selection. Please try again.");
Console.WriteLine();
}
}
An example usage might be:
string prompt = "How are you feeling today?";
string[] feelings = new string[] { "Good", "Indifferent", "Bad" };
int response = getMenuResponse(prompt, feelings);
Console.WriteLine();
Console.WriteLine("You are feeling " + feelings[response]);
Output:
With that in place, you can model your store as a set of menus represented by string arrays. Here I've setup drinks, sizes, and a different set of items that can be added to each drink:
string[] drinks = new string[] {"Exit", "Tea", "Coffee", "Smoothie"};
string[] drinkSizes = new string[] { "Small", "Medium", "Large" };
string[] teaOptions = new string[] { "Done", "Milk", "Sugar" };
string[] coffeeOptions = new string[] { "Done", "Creamer", "Sugar", "Vanilla Syrup", "Hazelnut Syrup"};
string[] smoothieOptions = new string[] { "Done", "Strawberry", "Banana", "Blueberry" };
We can use a Dictionary to associate each list of options with its respective drink name:
Dictionary<string, string[]> drinkOptions = new Dictionary<string, string[]>();
drinkOptions.Add("Tea", teaOptions);
drinkOptions.Add("Coffee", coffeeOptions);
drinkOptions.Add("Smoothie", smoothieOptions);
This will allow us to retrieve the list of items that can be added to each respective drink.
Next we'll declare some variables to track the current drink, size, and a List of items that have been added:
string size;
string drink;
List<string> options = new List<string>();
With the framework for our menus setup, we'll now use do...while loops to ask for the drink type and size. Inside that, we'll use another inner do...while loop to allow as many items to be added to the drink as the user would like:
bool exit = false;
int option;
do
{
Console.WriteLine();
Console.WriteLine("Welcome to The Drink Shop!");
option = getMenuResponse("What drink would you like?", drinks);
exit = (option == 0);
if (!exit)
{
drink = drinks[option];
options.Clear();
if (drinkOptions.ContainsKey(drink))
{
string[] curOptions = drinkOptions[drink];
do
{
option = getMenuResponse("What would you like in your " + drink + "?", curOptions);
if (option != 0)
{
string itemToAdd = curOptions[option];
Console.WriteLine();
if (!options.Contains(itemToAdd))
{
options.Add(itemToAdd);
Console.WriteLine(itemToAdd + " added.");
}
else
{
Console.WriteLine(itemToAdd + " previously added.");
}
Console.WriteLine("Current Items: " + string.Join(", ", options));
}
} while (option != 0);
option = getMenuResponse("What size would you like?", drinkSizes);
size = drinkSizes[option];
string optionsAdded = "Nothing Added";
if (options.Count > 0)
{
optionsAdded = String.Join(", ", options);
}
Console.WriteLine();
Console.WriteLine("You have ordered a " + size + " " + drink + " with: " + optionsAdded);
}
else
{
Console.WriteLine();
Console.WriteLine("Error: Options missing for " + drink + "!");
}
}
} while (!exit);
Example of the program running:
Here is the whole program all together:
class Program
{
static void Main(string[] args)
{
string[] drinks = new string[] {"Exit", "Tea", "Coffee", "Smoothie"};
string[] drinkSizes = new string[] { "Small", "Medium", "Large" };
string[] teaOptions = new string[] { "Done", "Milk", "Sugar" };
string[] coffeeOptions = new string[] { "Done", "Creamer", "Sugar", "Vanilla Syrup", "Hazelnut Syrup"};
string[] smoothieOptions = new string[] { "Done", "Strawberry", "Banana", "Blueberry" };
Dictionary<string, string[]> drinkOptions = new Dictionary<string, string[]>();
drinkOptions.Add("Tea", teaOptions);
drinkOptions.Add("Coffee", coffeeOptions);
drinkOptions.Add("Smoothie", smoothieOptions);
string size;
string drink;
List<string> options = new List<string>();
bool exit = false;
int option;
do
{
Console.WriteLine();
Console.WriteLine("Welcome to The Drink Shop!");
option = getMenuResponse("What drink would you like?", drinks);
exit = (option == 0);
if (!exit)
{
drink = drinks[option];
options.Clear();
if (drinkOptions.ContainsKey(drink))
{
string[] curOptions = drinkOptions[drink];
do
{
option = getMenuResponse("What would you like in your " + drink + "?", curOptions);
if (option != 0)
{
string itemToAdd = curOptions[option];
Console.WriteLine();
if (!options.Contains(itemToAdd))
{
options.Add(itemToAdd);
Console.WriteLine(itemToAdd + " added.");
}
else
{
Console.WriteLine(itemToAdd + " previously added.");
}
Console.WriteLine("Current Items: " + string.Join(", ", options));
}
} while (option != 0);
option = getMenuResponse("What size would you like?", drinkSizes);
size = drinkSizes[option];
string optionsAdded = "Nothing Added";
if (options.Count > 0)
{
optionsAdded = String.Join(", ", options);
}
Console.WriteLine();
Console.WriteLine("You have ordered a " + size + " " + drink + " with: " + optionsAdded);
}
else
{
Console.WriteLine();
Console.WriteLine("Error: Options missing for " + drink + "!");
}
}
} while (!exit);
Console.WriteLine();
Console.WriteLine("Goodbye!");
Console.WriteLine();
Console.Write("Press Enter to Quit...");
Console.ReadLine();
}
static int getMenuResponse(string prompt, string[] options)
{
while(true)
{
Console.WriteLine();
Console.WriteLine(prompt);
for(int i=0; i<options.Length; i++)
{
Console.WriteLine($"[{i+1}] {options[i]}");
}
Console.Write("Your choice: ");
string response = Console.ReadLine();
int option;
if (int.TryParse(response, out option) && option>=1 && option<=options.Length)
{
return (option-1);
}
Console.WriteLine("Invalid Selection. Please try again.");
Console.WriteLine();
}
}
}
From the comments:
Could you explain how the function works a bit? I get what certain
parts do but not all of it.
Sure, I've added some comments in the code below:
static int getMenuResponse(string prompt, string[] options)
{
while(true) // we keep asking for a number until we've gotten valid input
{
Console.WriteLine();
Console.WriteLine(prompt); // display the prompt
// display each item from the passed in string array,
// with "1", "2", "3", etc in front of it
for(int i=0; i<options.Length; i++)
{
// the output below is using "string interpolation"
Console.WriteLine($"[{i+1}] {options[i]}");
// the line above could instead be written as:
// Console.WriteLine("[" + (i+1) + "] " + options[i]);
}
// get a STRING response from the user
Console.Write("Your choice: ");
string response = Console.ReadLine();
// attempt to convert the string into a valid integer
// int.TryParse() returns true if successful, otherwise false
// if successful, AND the integer is between 1 and
// the number of choices in the string array,
// then return the zero based index number representing their choice
int option;
if (int.TryParse(response, out option) && option>=1 && option<=options.Length)
{
return (option-1);
}
// if we get here, then the user input was not a valid integer
// and/or was outside the range of valid choices from the menu
Console.WriteLine("Invalid Selection. Please try again.");
Console.WriteLine();
} // end of the while loop - go back to the top and repeat
}
I'd generate an XML file, with al the information: Items available, all the posible extras, the relationship between items, the order.. maybe the cost and all the "information".
First job is to design this xml file, which depends on the kind of information you need to deal with.
Then the C# code should load that xml and give the user the options, capture the answers and so.
This way you have properly separated the information from the logic. You can then add items to the xml file.. translate it to other languages simply, without need to modify the logic part. As well as modify the logic (replace the console for some winform por example) without modifying the xml file.
A bit harder al the begining but much more powerful and manteinable on the long term.
I am currently writing a program where I have to
1) Giving user some options: 1.Search by name? 2. Search by date of birth?
2) If user selects search by name, ask them to put first name and then give the output
3) If user selects search by date of birth, ask them to put date of birth with format (MM/DD/YYYY) and then give the output.
I have to Repeat the options if the validation failed or couldn’t find the data.
I am struggling with the concept of repeating the options. ANy help is extremely appreciated.
My code so far
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Week2Tutorial
{
class Program
class Student
{
public int Id { get; set; }
public string FirstName { get; set; }
public string Lastname { get; set; }
public DateTime DOB { get; set; }
public string Gender { get; set; }
}
static void Main(string[] args)
{
var students = new List<Student>()
{
new Student() { Id = 1,FirstName = "Min Chul",Lastname = "Shin",DOB = new DateTime(2010,01,01),Gender = "Male"},
new Student() { Id = 2,FirstName = "Nicky", Lastname = "Lauren", DOB = new DateTime(2009, 01, 01), Gender = "Female"},
new Student() { Id = 3, FirstName = "Amy", Lastname = "Park", DOB = new DateTime(2008, 01, 01), Gender = "Female" },
new Student() { Id = 4, FirstName = "Aurelie", Lastname = "Adair", DOB = new DateTime(2007, 01, 01), Gender = "Female" }
};
//foreach (var x in students)
//{
// Console.WriteLine("Id = {0}, FirstName = {1}, Lastname = {2}, DOB = {3}, Gender = {4}",x.Id,x.FirstName,x.Lastname,x.DOB,x.Gender);
//}
Console.WriteLine(" Please Choose one of the options:");
Console.WriteLine("1> Search by first name");
Console.WriteLine("2> Search by date of birth");
switch ( Convert.ToInt32(Console.ReadLine()))
{
case 1:
Console.WriteLine("You choose:1");
Console.WriteLine("Type your first name:");
var a = Console.ReadLine();
var case1 = students.Where(x=>x.FirstName==a);
if (case1.Count()!=0)
{
Console.WriteLine("Found! Here are the details:");
foreach (var x in case1)
{
Console.WriteLine("Name: {0}{1} D.O.B:{2} and Gender{3}", x.FirstName, x.Lastname, x.DOB, x.Gender);
}
}
else
{
Console.WriteLine(" Enter the correct information");
}
break;
case 2:
Console.WriteLine("You choose:2");
Console.WriteLine("Enter your Date of Birth in format MM/DD/YYYY:");
var b = DateTime.Parse(Console.ReadLine());
//Console.WriteLine(b);
//Console.ReadLine();
var case2 = students.Where(x => x.DOB == b);
if (case2.Count() != 0)
{
Console.WriteLine("Found! Here are your details");
foreach (var x in case2)
{
Console.WriteLine("Name:{0} {1} DOB:{2} Gender:{3}", x.FirstName, x.Lastname, x.DOB, x.Gender);
}
}
else
{
Console.WriteLine(" Enter the correct information");
}
break;
default:
Console.WriteLine("Please enter the valid option");
break;
}
}
}
}
It can be Done be with do while loop here is the general syntax of do while Loop
do {
code to be executed;
} while (condition is true);
what is do while loop it is an endless loop that is executes the code till the condition is true.
In Your Case we are taking a new varibale temp which is intially zero means no
result if any of your switch case gets true and find results according to user's search query the count of that result will be copied to temp variable now temp no longer have zero value means condition is false means the code will not be executed again
You Just Need to start an endless loop till the condition is true
do{
var temp=0; ///Temporary variable to check the result count
//intially variable b will be zero because INtially result count is zero
Console.WriteLine(" Please Choose one of the options:");
Console.WriteLine("1> Search by first name");
Console.WriteLine("2> Search by date of birth");
switch ( Convert.ToInt32(Console.ReadLine()))
{
case 1:
Console.WriteLine("You choose:1");
Console.WriteLine("Type your first name:");
var a = Console.ReadLine();
var case1 = students.Where(x=>x.FirstName==a);
temp=case1.Count(); //Getting result count in another variable
if (case1.Count()!=0)
{
Console.WriteLine("Found! Here are the details:");
foreach (var x in case1)
{
Console.WriteLine("Name: {0}{1} D.O.B:{2} and Gender{3}", x.FirstName, x.Lastname, x.DOB, x.Gender);
}
}
else
{
Console.WriteLine(" Enter the correct information");
}
break;
case 2:
Console.WriteLine("You choose:2");
Console.WriteLine("Enter your Date of Birth in format MM/DD/YYYY:");
var b = DateTime.Parse(Console.ReadLine());
//Console.WriteLine(b);
//Console.ReadLine();
var case2 = students.Where(x => x.DOB == b);
temp=case2.Count(); //Getting result count in another variable
if (case2.Count() != 0)
{
Console.WriteLine("Found! Here are your details");
foreach (var x in case2)
{
Console.WriteLine("Name:{0} {1} DOB:{2} Gender:{3}", x.FirstName, x.Lastname, x.DOB, x.Gender);
}
}
else
{
Console.WriteLine(" Enter the correct information");
}
break;
default:
Console.WriteLine("Please enter the valid option");
break;
}
}while(temp==0); ////Endless Loop while result is zero
intially temp is equal to zero means result count is zero
so it will again intiate the loop However if there is any result
that means temp is not equal to zero it will not execute the code
Just use while loop.
Example from: https://www.dotnetperls.com/console-readline
using System;
class Program
{
static void Main()
{
while (true) // Loop indefinitely
{
Console.WriteLine("Enter input:"); // Prompt
string line = Console.ReadLine(); // Get string from user
if (line == "exit") // Check string
{
break;
}
Console.Write("You typed "); // Report output
Console.Write(line.Length);
Console.WriteLine(" character(s)");
}
}
}