User input commands in Console application - c#

I would like my console application to have commands like user types /help and console writes help. I would like it to use switch like:
switch (command)
{
case "/help":
Console.WriteLine("This should be help.");
break;
case "/version":
Console.WriteLine("This should be version.");
break;
default:
Console.WriteLine("Unknown Command " + command);
break;
}
How can I achieve this? Thanks in advance.

Based on your comment to errata's answer, it appears you want to keep looping until you're told not to do so, instead of getting input from the command line at startup. If that's the case, you need to loop outside the switch to keep things running. Here's a quick sample based on what you wrote above:
namespace ConsoleApplicationCSharp1
{
class Program
{
static void Main(string[] args)
{
string command;
bool quitNow = false;
while(!quitNow)
{
command = Console.ReadLine();
switch (command)
{
case "/help":
Console.WriteLine("This should be help.");
break;
case "/version":
Console.WriteLine("This should be version.");
break;
case "/quit":
quitNow = true;
break;
default:
Console.WriteLine("Unknown Command " + command);
break;
}
}
}
}
}

Something along these lines might work:
// cmdline1.cs
// arguments: A B C
using System;
public class CommandLine
{
public static void Main(string[] args)
{
// The Length property is used to obtain the length of the array.
// Notice that Length is a read-only property:
Console.WriteLine("Number of command line parameters = {0}",
args.Length);
for(int i = 0; i < args.Length; i++)
{
Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]);
}
}
}
run the command: cmdline1 A B C
Output:
Number of command line parameters = 3
Arg[0] = [A]
Arg[1] = [B]
Arg[2] = [C]
I don't do c# much(any) anymore but hope this helps.

There exist .open source projects like http://www.codeproject.com/Articles/63374/C-NET-Command-Line-Argument-Parser-Reloaded that take care of this. Why reinventing the wheel?

Related

Stack overflow exception with instances of classes

In my Main Menu class, I have a switch statement that calls the DisplaySellMenu method in the sell menu class(instance of the sell menu class was created in main menu class) when the user types the number to go to the sell menu. I then created a new instance of the Main menu class in the Sell Menu class, below you can see the switch statement I made so that when the user selects to exit to the Main Menu it calls the DisplayMainMenu method in the MainMenu class so the user can go back to the MainMenu. This is causing a stack overflow exception between the instances of the classes. How do I stop this from happening while still allowing the user to exit back to the main menu?
Main menu class:
class MainMenu
{
public BuyMenu buyMenu = new BuyMenu();
public SellMenu sellMenu = new SellMenu();
public ShipGarage shipGarage = new ShipGarage();
int Exit = 0;
public void DisplayMenu()
{
Console.WriteLine("Whatcha tryin to do yo?");
Console.WriteLine("Type 1 to buy");
Console.WriteLine("Type 2 to sell");
Console.WriteLine("Type 3 for SpaceShip Upgrade ");
Console.WriteLine("Type 4 to quit game");
int userSelection = int.Parse(Console.ReadLine());
do
{
switch (userSelection)
{
case 1:
buyMenu.DisplayInventory(buyMenu);
DisplayMenu();
break;
case 2:
sellMenu.SoldItems();
DisplayMenu();
break;
case 3:
shipGarage.DisplayGarage(shipGarage);
DisplayMenu();
break;
case 4:
Exit += 1;
break;
default:
Console.WriteLine("Invalid Input");
break;
}
} while (Exit == 1);
}
}
Sell menu class:
class SellMenu
{
static Random rnd = new Random();
MoneyMath Money = new MoneyMath();
MainMenu MainMenu = new MainMenu();
int goldPrice = rnd.Next(100, 1001);
int silverPrice = rnd.Next(100, 1001);
int titaniumPrice = rnd.Next(100, 1001);
int Exit = 0;
public string DisplayInventory()
{
Console.WriteLine("What would you like to sell?");
Console.WriteLine("Type 1 for Gold");
Console.WriteLine("Type 2 for Silver");
Console.WriteLine("Type 3 for Titanium");
Console.WriteLine("Type 4 for Main Menu");
string itemList = "Gold" + " " + "$" + (goldPrice) + "\n" +
"Silver" + " " + "$" + (silverPrice) + "\n" +
"Titanium" + " " + "$" + (titaniumPrice);
Console.WriteLine(itemList);
return itemList;
}
public void SoldItems()
{
do
{
DisplayInventory();
int userSelection = int.Parse(Console.ReadLine());
switch (userSelection)
{
case 1:
Money.MoneyAddition(goldPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 2:
Money.MoneyAddition(silverPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 3:
Money.MoneyAddition(titaniumPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 4:
Exit += 1;
MainMenu.DisplayMenu();
break;
default:
Console.WriteLine("Invalid Input");
break;
}
} while (Exit == 1);
}
}
It seems to me that your SoldItems() case 4 should simply be this:
case 4:
return;
You're already calling SoldItems() from DisplayMenu() in MainMenu, so all you need to do is return to the DisplayMenu() switch statement and continue its loop.
Having an Exit variable is unnecessary here because return will leave the entire method body, terminating the while loop. The same applies to DisplayMenu()'s Exit variable, too.
Complete code for SoldItems():
public void SoldItems()
{
do
{
DisplayInventory();
int userSelection = int.Parse(Console.ReadLine());
switch (userSelection)
{
case 1:
Money.MoneyAddition(goldPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 2:
Money.MoneyAddition(silverPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 3:
Money.MoneyAddition(titaniumPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 4:
return;
default:
Console.WriteLine("Invalid Input");
break;
}
}
while (true);
}
Explanation of StackoverflowException:
This exception is caused when the stack gets full. Imagine you have three methods:
public void A() { B(); }
public void B() { C(); }
public void C() { }
When A calls B, an extra layer is pushed onto the stack. The same happens when B calls C. When C returns to B, that layer is pushed off the stack, and then the same then B returns to A.
The .NET stack has a finite size, so you can't infinitely call methods. This is typically big enough for any code you write, except recursive functions can be a little dangerous. Imagine this code:
public void A() { A(); }
It calls itself recursively forever. This code is doomed to experience a Stackoverflow exception. When you write code like this, you need to place a limitation on it to ensure that it only goes so deep. Example:
public void A(int maxDepth = 0) { if (maxDepth < 5) { A(++maxDepth); } }
You can read more about the stack and this exception here.
Obligatory Google Easter egg

First C# program with two Classes. Confused

pretty new to programming and I'm a bit stuck. This is the first program I've written with two classes (in two seperate class files). I'll include all the code below. It's a program to play a dice game called Craps. My task is too create a method in the CrapsGame class that allows me to play the game over and over again until I decide to stop. But I'm having a little trouble working out how to correctly call the manyPlay() method. I'm not really sure what I'm doing. The program will play the game once by calling myCraps.play() but then won't go any further. If anyone else notices anything wrong with the code or anything that's bad practice then please point it out as I am very keen to learn. Thanks to anyone that takes the time to answer.
using System;
namespace Task4_7
{
public class CrapsGame
{
string replay;
private Craps myCraps;
private CrapsGame newGame;
public static void Main()
{
CrapsGame newGame = new CrapsGame();
Craps myCraps = new Craps ();
myCraps.play ();
newGame.manyPlay ();
}
public void manyPlay() {
string input; // declare local variable
do {
myCraps.play();
replay:
Console.Write("Would you like to play again? y/n");
input = Console.ReadLine();
if (input == "y") {
replay = input;
}
else if (input == "n") {
replay = "n";
}
else {
Console.WriteLine("\n Erroneous input. Please enter y (yes) or n (no)");
goto replay;
}
}
while(replay != "n");
}
}
}
using System;
namespace Task4_7
{
public class Craps
{
private Random randy; // define randy as a Random class
public Craps() {
this.randy = new Random ();
}
public int oneThrow() {
return randy.Next(6) + 1; // pick a number from 1 to 6 and return this
}
public int throw2Dice() {
int a, b, c;
a = oneThrow ();
b = oneThrow ();
c = a + b;
Console.WriteLine ("You threw a " + a + " and a " + b + " making " + c);
return c;
}
public void play() {
int result = throw2Dice ();
switch (result) {
case 2:
Console.WriteLine ("You lose! End of game!");
break;
case 3:
Console.WriteLine ("You lose! End of game!");
break;
case 12:
Console.WriteLine ("You lose! End of game!");
break;
case 7:
Console.WriteLine ("You win! End of game!");
break;
case 11:
Console.WriteLine ("You win! End of game!");
break;
case 4:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
case 5:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
case 6:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
case 8:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
case 9:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
default:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
}
}
public void throwPoint(int result) {
Throw:
int a = throw2Dice();
if (a == result) {
Console.WriteLine ("You rolled the same score! You win!");
} else if (a == 7) {
Console.WriteLine ("You rolled a 7! You loose!");
} else {
Console.WriteLine ("You rolled a " + a + ". Rolling again!");
goto Throw;
}
}
}
}
This is your problem:
Craps myCraps = new Craps();
You are hiding variable of class CrapsGame with a local variable of Main method. Simply change it to
myCraps = new Craps();
and it should work.
EDIT
and change myCraps declaration to static, of course.
EDIT2
Scope of variables: C# variable scoping not consistent?
My first suggestion is put your Main method in a seperate file.For example you can use three files: Program.cs, CrapsGame.cs, Craps.cs. To do this just add a new class file,and move your main method to new Class file. Second, never use goto.Instead use while loop like this,
public void throwPoint(int result) {
while(true)
{
int a = throw2Dice();
if (a == result) {
Console.WriteLine ("You rolled the same score! You win!");
break;
} else if (a == 7) {
Console.WriteLine ("You rolled a 7! You loose!");
break;
} else {
Console.WriteLine ("You rolled a " + a + ". Rolling again!");
}
}
}
Many play method:
public void manyPlay() {
string input; // declare local variable
myCraps.play();
while(true) {
Console.Write("Would you like to play again? y/n");
input = Console.ReadLine();
if (input == "y") {
myCraps.play();
}
else if (input == "n") {
break;
}
else {
Console.WriteLine("\n Erroneous input. Please enter y (yes) or n (no)");
}
}
}
The problem looks like you where creating a game for use by the game iterator, but it needs to create a game for each iteration. So I delete some code: all the class variables have to go, variables should be as local as possible.
using System;
namespace Task4_7
{
public class CrapsGame
{
public static void Main()
{
new Craps ().play ();
new CrapsGame().manyPlay ();
}
public void manyPlay() {
string replay;
string input; // declare local variable
do {
new Craps().play();
replay:
Console.Write("Would you like to play again? y/n");
input = Console.ReadLine();
if (input == "y") {
replay = input;
}
else if (input == "n") {
replay = "n";
}
else {
Console.WriteLine("\n Erroneous input. Please enter y (yes) or n (no)");
goto replay;
}
}
while(replay != "n");
}
}
}
Now fix that loop: no gotos. You need a loop in a loop, as you have but don't build your own loops.
Then if Craps.play() returned a score. You could add a class variable to accumulate the score.
Change replay to boolean and make set it to true if input is y and false if input is n.
Then change your main method.
public static void Main()
{
CrapsGame newGame = new CrapsGame();
Craps myCraps = new Craps ();
while (replay == true) {
myCraps.play ();
newGame.manyPlay ();
}
}

Case Switch with a loop

I am not understanding what is going on in my case statement to determine if I want to redo the users input. Should I make another loop outside of my while loop? I attempted such and my case statement becomes unreachable code. Maybe I am not understanding case-switch statements.
class Program
{
static void Main(string[] args)
{
string _a = "";
constructor con = new constructor();
Console.WriteLine("Enter enter exit to end the program...");
Console.WriteLine("Enter C for constructor, M for method, A for an array...");
Console.WriteLine("Please reference source code to have full details and understanding...");
bool control = true;
while (control)
{
_a = Console.ReadLine();
switch (_a.ToUpper())
{
case "EXIT":
Console.WriteLine("Thank you for using AJ's program...");
control = false;
break;
case "C":
Console.WriteLine(con.a);
Console.WriteLine("Would you like to test another scenario?");
Console.ReadLine();
if (_a.ToUpper() == "Y")
{
Console.ReadLine();
return;
}
control = false;
break;
case "M":
control = false;
metroid();
break;
case "A":
control = false;
Array();
break;
default: Console.WriteLine("No match");
break;
}
}
}
public class constructor
{
public string a = "This is a constructor!";
}
static public void metroid()
{
string b = "This is a method!";
Console.WriteLine(b);
}
static public void Array()
{
try
{
Console.WriteLine("This is a random array. Please enter the size.");
string sSize = Console.ReadLine();
int arraySize = Convert.ToInt32(sSize);
int[] size = new int[arraySize];
Random rd = new Random();
Console.WriteLine();
for (int i = 0; i < arraySize; i++)
{
size[i] = rd.Next(arraySize);
Console.WriteLine(size[i].ToString());
}
}
catch (System.FormatException)
{
Console.WriteLine("Not correct format, restarting array process.");
Array();
}
}
}
}
Here's what I came up with. You had too many ways of exiting your loop, so I removed all of the control = false lines except where the user typed "EXIT"
Also, in case "C" you return out of the method if they choose "Y", I changed that to continue so that the loop would continue.
Finally, I moved the 3 instruction statements into the loop, so when the user hit "Y" it would print those again.
static void Main(string[] args)
{
string _a = "";
constructor con = new constructor();
bool control = true;
while (control)
{
Console.WriteLine("Enter enter exit to end the program...");
Console.WriteLine("Enter C for constructor, M for method, A for an array...");
Console.WriteLine("Please reference source code to have full details and understanding...");
_a = Console.ReadLine();
switch (_a.ToUpper())
{
case "EXIT":
Console.WriteLine("Thank you for using AJ's program...");
control = false;
break;
case "C":
Console.WriteLine(con.a);
Console.WriteLine("Would you like to test another scenario?");
_a = Console.ReadLine(); //<==problem #1 you didnt set your var name
if (_a.ToUpper() == "Y")
{
continue; //<==problem #2 return exits the program, continue, just keeps going
}
control = false;
break;
case "M":
metroid();
break;
case "A":
Array();
break;
default:
Console.WriteLine("No match");
break;
}
}
}
I think you should considering goto in this case. Yes you need to put some extra effort, but it will help you overcoming the While loop.
A sample below:
switch (_a.ToUpper())
{
case "EXIT":
Console.WriteLine("Thank you for using AJ's program...");
control = false;
// execute goto when your all line executes successfully
goto case "New";
case "New":
// some logic
}
See working sample here Goto-Switch
string NewInput= Console.ReadLine();
if (NewInput.ToUpper() == "Y")
{
//print some thing with console.writeline
//if after this you want to restart the loop then instead of return use
continue;
}
Try putting the Console.Writeline inside the while loop like this:
static void Main(string[] args)
{
bool control = true;
while (control)
{
Console.WriteLine("Enter enter exit to end the program...");
Console.WriteLine("Enter C for constructor, M for method, A for an array...");
Console.WriteLine("Please reference source code to have full details and understanding...");
string _a = Console.ReadLine();
switch (_a.ToUpper())
{
case "EXIT":
Console.WriteLine("Thank you for using AJ's program...");
control = false;
break;
case "C":
Console.WriteLine("press c");
Console.WriteLine("Would you like to test another scenario?");
Console.ReadLine();
if (_a.ToUpper() == "Y")
{
Console.ReadLine();
return;
}
control = false;
break;
case "M":
control = false;
metroid();
break;
case "A":
control = false;
Array();
break;
default: Console.WriteLine("No match");
break;
}
}
}
Additional reading about switch here and here.
Just add comment for the result, thanks. Hope this helped!
may be you want to change
Console.ReadLine();
if (_a.ToUpper() == "Y")
{
Console.ReadLine();
return;
}
as
_a = Console.ReadLine();
if (_a.ToUpper() == "Y")
{
_a = Console.ReadLine();
continue;
}

Creating a command prompt and then control some string methods to do

I wanted to do my program like a command prompt. I thought that it must perform some string methods.
For example: COM> length "string " must return the length of "string " (the command must be bigger than three characters, that is, len "asdf" is OK). In addition to this I added three methods, "reverse", "ToUpper" and "ToLower" and to escape, "quit", and it is not necessarily adjecent or not (can be any spaces between the command and the string).
I wrote on my way, but I think it is not optimized. So do you have any trick to make it faster and reusable?
(I didn't care about any exception so I know there are some exceptions.)
class Program
{
static void Main(string[] args)
{
string str;
for (; ; )
{
Console.Write("CSD>");
str = Console.ReadLine();
if (str == "quit")
break;
commandControl(str);
}
}
public static void commandControl(string str)
{
string strCom, strString;
int index;
str = str.Trim();
index = str.IndexOf(" ");
strCom = str.Substring(0, index);
str = str.Substring(index);
str = str.Trim();
strString = str.Substring(1, str.Length - 2);
string[] strComArry = { "length", "reverse", "upper", "lower" };
int i;
if (strCom.Length >= 3)
{
for (i = 0; i < strComArry.Length; i++)
if (strCom.Length <= strComArry[i].Length)
if (strCom == strComArry[i].Substring(0, strCom.Length))
break;
switch (i)
{
case 0:
Console.WriteLine(strString.Length);
break;
case 1:
for (int j = strString.Length - 1; j >= 0; --j)
System.Console.Write(strString[j]);
Console.WriteLine();
break;
case 2:
Console.WriteLine(strString.ToUpper());
break;
case 3:
Console.WriteLine(strString.ToLower());
break;
}
}
else
Console.WriteLine("Command must be more than 3 characters !...");
}
}
I'm not going to provide a full working example, but take a look at the snippet below. This idea is to use a dictionary of actions to store what to do with commands. That way, you can add new functionality to the interpreter by adding to the "Methods" dictionary.
The idea is call InitializeFunctions to register all of the functions you want available in the interpreter, and then call command control to interpret one.
(I gave two examples on how to add functions, a lambda syntax and referencing a normal function. Also those functions assume you have already parsed what is a command and what is a parameter, which you have done already in your example.)
static Dictionary<string, Action<string>> Methods = new Dictionary<string, Action<string>>();
public static void InitializeFunctions()
{
Methods.Add("ToLower", a => Console.WriteLine(a.ToLower()));
Methods.Add("ToUpper", ToUpper);
}
static void ToUpper(string str)
{
Console.WriteLine(str.ToUpper());
}
public static void commandControl(string str, string param)
{
if(str.Length < 4)
Console.WriteLine("Command must be more than 3 characters !...");
if (Methods.ContainsKey(str))
Methods[str].Invoke(param);
else
Console.WriteLine("Invalid Command");
}

Command to close an application of console?

I need to close the console when the user selects a menu option.
I tried using close() but it did not work..
how can I do this?
Environment.Exit and Application.Exit
Environment.Exit(0) is cleaner.
http://geekswithblogs.net/mtreadwell/archive/2004/06/06/6123.aspx
By close, do you mean you want the current instance of the console app to close, or do you want the application process, to terminate? Missed that all important exit code:
Environment.Exit(0);
Or to close the current instance of the form:
this.Close();
Useful link.
You can Try This
Application.Exit();
//How to start another application from the current application
Process runProg = new Process();
runProg.StartInfo.FileName = pathToFile; //the path of the application
runProg.StartInfo.Arguments = genArgs; //any arguments you want to pass
runProg.StartInfo.CreateNoWindow = true;
runProg.Start();
//How to end the same application from the current application
int IDstring = System.Convert.ToInt32(runProg.Id.ToString());
Process tempProc = Process.GetProcessById(IDstring);
tempProc.CloseMainWindow();
tempProc.WaitForExit();
return; will exit a method in C#.
See code snippet below
using System;
namespace Exercise_strings
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Input string separated by -");
var stringInput = Console.ReadLine();
if (string.IsNullOrWhiteSpace(stringInput))
{
Console.WriteLine("Nothing entered");
return;
}
}
So in this case if a user enters a null string or whitespace, the use of the return method terminates the Main method elegantly.
So you didn't say you wanted the application to quit or exit abruptly, so as another option, perhaps just have the response loop end out elegantly. (I am assuming you have a while loop waiting for user instructions. This is some code from a project I just wrote today.
Console.WriteLine("College File Processor");
Console.WriteLine("*************************************");
Console.WriteLine("(H)elp");
Console.WriteLine("Process (W)orkouts");
Console.WriteLine("Process (I)nterviews");
Console.WriteLine("Process (P)ro Days");
Console.WriteLine("(S)tart Processing");
Console.WriteLine("E(x)it");
Console.WriteLine("*************************************");
string response = "";
string videotype = "";
bool starting = false;
bool exiting = false;
response = Console.ReadLine();
while ( response != "" )
{
switch ( response )
{
case "H":
case "h":
DisplayHelp();
break;
case "W":
case "w":
Console.WriteLine("Video Type set to Workout");
videotype = "W";
break;
case "I":
case "i":
Console.WriteLine("Video Type set to Interview");
videotype = "I";
break;
case "P":
case "p":
Console.WriteLine("Video Type set to Pro Day");
videotype = "P";
break;
case "S":
case "s":
if ( videotype == "" )
{
Console.WriteLine("Please Select Video Type Before Starting");
}
else
{
Console.WriteLine("Starting...");
starting = true;
}
break;
case "E":
case "e":
Console.WriteLine("Good Bye!");
System.Threading.Thread.Sleep(100);
exiting = true;
break;
}
if ( starting || exiting)
{
break;
}
else
{
response = Console.ReadLine();
}
}
if ( starting )
{
ProcessFiles();
}

Categories