Using a for loop inside switch/case - c#

Can I use a for loop inside a switch/case?
Example code:
String[,] drinks = new String[,] { { "Cola", "20" }, { "Fanta", "20" }, { "Sprite", "20" }, { "Tuborg", "25" }, { "Carlsberg", "25" } };
switch (menuChoice)
{
case 0:
Console.WriteLine("Goodbye!");
Thread.Sleep(500);
Environment.Exit(0);
break;
for (int i = 0; i < drinksCount; i++)
{
case i+1:
buyDrink(drinks[i,0];
break;
}
(More code and methods is in between these)
Basically, I create an array with the drinks this machine sells, and then I want to create a menu where to chose these drinks, but also the ability to add more drinks within the GUI.
Is this even possible?

You can use loops inside switch statement but not the way you are using it currently. Try to replace your code with below code:
if (menuChoice == 0)
{
Console.WriteLine("Goodbye!");
Thread.Sleep(500);
Environment.Exit(0);
}
else if (menuChoice > 0 && menuChoice < drinksCount)
{
buyDrink(drinks[menuChoice, 0]);
}
ADDED:
As per valuable comments, why don't you just use -1 as menuChoice for Exit, this way:
if (menuChoice == -1)
{
Console.WriteLine("Goodbye!");
Thread.Sleep(500);
Environment.Exit(0);
}
else if (menuChoice > 0 && menuChoice <= drinksCount)
{
buyDrink(drinks[menuChoice - 1, 0], Convert.ToDouble(drinks[menuChoice - 1, 1]));
}
This way you can call your static method as shown:
static void buyDrink(String drink, double drinkPrice)

A better title for this question might be: Is it possible to have variable case statements?
case i+1:
This is an invalid case statement. A the value of a case statement must be a constant. If i were a constant in this case, it would be allowed. However, i isn't, and therefore the case statement will not compile.
Having said that, although the answer to the title question is yes, as shown by other answers, the real answer here is: Not the way you're trying to do it.

It doesn't make sense to have code after break.
You break from the case how do you expect it to execute?
case 0:
{
break;//If you break here, it exits the block.. your loop never executes
for (int i = 0; i < drinksCount; i++)
{
case i+1:
buyDrink(drinks[i,0];
break;
}
}
And even if it is possible I fail to see the point.
You will execute the case as long as it is greater than 0 right?
So why not just use an if statement, help yourself and others?
if(menuChoice ==0)
{
//dosomething
}
else if(menuChoice >0)
{
//buy drink
}

if(menuChoice == 0) {
Console.WriteLine("Goodbye!");
Thread.Sleep(500);
Environment.Exit(0);
} else if(menuChoice > 0 && menuChoice <= drinksCount) {
buyDrink(drinks[menuChoice - 1, 0]);
}

That code could not work at all.
A break is the final (and required) statement of a case.
Looking at your example you could simply write
if(menuChoice == 0)
{
Console.WriteLine("Goodbye!");
Thread.Sleep(500);
Environment.Exit(0);
}
else
{
buyDrink(drinks[menuChoice-1,0]);
}
EDIT: Seeing your comment about buyDrink as static method and the parameters required then you should change the call to buyDrink prepending the class name where the buyDrink method is defined and add the parameter for the price (as double value)
.......
else
{
BeverageClass.buyDrink(drinks[menuChoice-1,0], Convert.ToDouble(drinks[menuChoice-1,1]));
}

Related

switch while won't loop

This is part of a program I'm writting. My main porblem is that once it goes trough one of the cases, tit won't loop so it's useless as it is. Any help? (Sorry for the variables in Spanish, also a couple of functions i created appear in the cose which are in the program and work just fine so I don't thin they have anything to do with the problem).
static void Main(string[] args)
{
int minutos_restantes = 480;
int opcion;
int valorComercial = 0;
Tarea[] listado_tareas = new Tarea[10];
CrearTareas(ref listado_tareas);
Console.WriteLine("1. Mostrar tareas. \n2. Asignar tarea \n3. Salir, \n Elige opción: ");
opcion = Convert.ToInt32(Console.ReadLine());
switch (opcion)
{
case 1:
Imprimirtareas(listado_tareas);
break;
case 2:
Console.WriteLine("Seleccionar número de tarea: ");
int n = Convert.ToInt32(Console.ReadLine())-1;
if (n < 0 || n > 10)
{
Console.WriteLine("TAREA INEXISTENTE");
}
else if (listado_tareas[n].realizada == true)
{
Console.WriteLine("TAREA YA REALIZADA");
}
else if((minutos_restantes - listado_tareas[n].tiempo) <= 0)
{
Console.WriteLine("TIEMPO INSUFICIENTE");
}
else
{
listado_tareas[n].realizada = true;
minutos_restantes -= listado_tareas[n].tiempo;
}
break;
} while (opcion != 3) ;
}
I don't think you can loop over a switch like this.
Try doing the while separate:
do
{
switch (opcion)
{
case 1:
Imprimirtareas(listado_tareas);
break;
case 2:
Console.WriteLine("Seleccionar número de tarea: ");
int n = Convert.ToInt32(Console.ReadLine())-1;
if (n < 0 || n > 10)
{
Console.WriteLine("TAREA INEXISTENTE");
}
else if (listado_tareas[n].realizada == true)
{
Console.WriteLine("TAREA YA REALIZADA");
}
else if((minutos_restantes - listado_tareas[n].tiempo) <= 0)
{
Console.WriteLine("TIEMPO INSUFICIENTE");
}
else
{
listado_tareas[n].realizada = true;
minutos_restantes -= listado_tareas[n].tiempo;
}
break;
}
}while (opcion != 3) ;
There's no such construct:
switch
{
} while (...);
In C#. What you've actually written is:
switch
{
}
while (...);
Which is another way of writing
switch
{
}
while (...)
{
}
I suspect you want to put your switch statement inside a while or a do...while loop.
Go for something like this:
int opcion = 0;
do
{
opcion = Convert.ToInt32(Console.ReadLine());
switch (opcion)
{
...
}
} while (opcion != 3);
Check this one too: While Loop in C# with Switch Statement
This is broken code.
You have a switch() {} statement (without default and those breaks cause you to fall out of its scope) and a while (condition) /*do nothing*/; statement.
The intention is do{switch(){}}while() ?
Time to do some reading...
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/switch
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/while
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/do
You should do :-
while (condition)
{
switch
{
}
}

Need to validate a set of user input before triggering a method c#

I need to check a set of user Input from my console application before triggering my method and store data into my database.
The program compiles and rund without exceptions. But in case of one wrong Input it still runs through for the other three.
Although, what I really need is to make sure the 4 user's entries are correct before triggering the method and in case just one is wrong the whole program should stop and exit.
using System;
using System.Threading;
namespace BarcodeValidation
{
class Program
{
static void Main(string[] args)
{
ReadBarcode();
}
static void ReadBarcode()
{
var barcodes = GetInput();
foreach (var item in barcodes)
{
// something
CheckUserInput(item);
}
}
static string[] GetInput()
{
Console.WriteLine("Please enter 4 products ID, Barcodes, MPN or EAN code:");
string[] barcode = new string[4];
for (int i = 0; i < barcode.Length; i++)
{
barcode[i] = Console.ReadLine();
}
return barcode;
} // end of method here
static void CheckUserInput(string userInput)
{
int msec = 5000;
try
{
if (!(userInput == "F5121" || userInput == "F3111" || userInput == "F8331" || userInput == "F5321"))
{
Console.WriteLine("Enter a valid MPN codes for your products");
Thread.Sleep(msec);
Environment.Exit(0);
}
else
{
switch (userInput)
{
case "F5121":
Console.WriteLine("barcode 1 is =", userInput);
Thread.Sleep(msec);
break;
case "F3111":
Console.WriteLine("barcode 2 is =", userInput);
Thread.Sleep(msec);
break;
case "F8331":
Console.WriteLine("barcode 3 is =", userInput);
Thread.Sleep(msec);
break;
case "F5321":
Console.WriteLine("barcode 4 is =", userInput);
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
Since you have a method that actually tests your user input use it's return value:
static bool CheckUserInput(string userInput) // true : valid | false : invalid
{
int msec = 5000;
try
{
if (!(userInput == "F5121" ||
userInput == "F3111" ||
userInput == "F8331" ||
userInput == "F5321"))
{
Console.WriteLine("Enter a valid MPN codes for your products");
return false;
}
else
{
switch (userInput)
{
case "F5121":
Console.WriteLine("barcode 1 is =", userInput);
Thread.Sleep(msec);
return true;
case "F3111":
Console.WriteLine("barcode 2 is =", userInput);
Thread.Sleep(msec);
return true;
case "F8331":
Console.WriteLine("barcode 3 is =", userInput);
Thread.Sleep(msec);
return true;
case "F5321":
Console.WriteLine("barcode 4 is =", userInput);
return true;
default:
return false;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
ReadBarcodes could look like this:
static void ReadBarcode()
{
var barcodes = GetInput();
bool errorOccured = false;
foreach (var item in barcodes)
{
// something
if(!CheckUserInput(item))
{
errorOccured = true; // keep track of that error
break; //Break for if 1 input is invalid
}
}
//Further execution....
if(errorOccured)
{
return; //Do not continue ...
}
//Do other things you want to do. Your input is valid at this point !
}
or shorter like Default quoted:
static void ReadBarcode()
{
if(!GetInput().All(CheckUserInput))
{
return;
}
//Your stuff goes here. Input is valid at this point
}
One option you could employ is create your own class that derives from System.Exception, and in cases where one of the inputs is found to be invalid, you could throw an instance of your exception class.
You could wrap your code in a try-catch block, and then put the remediation code within the catch block.
You need to break the checking code and the "output" code into different places. You need to check if all the values are valid values. and AFTER you have checked all the values, then do your console.writelines (Which is the part you dont want to happen). At the moment it checks one and executes the code if that one is valid, and then moves on to the next one. CheckUserInput should really ONLY check the users input, it should not do something else you want to restrict based on that methods result. You should have CheckUserInput and a ExecuteBarcodeStuff for example, and only if all CheckUserInputs return true, should you run the new (as yet unimplemented) ExecuteBarcodeStuff
Mixing this approach with other peoples answers that do Linq queries or such to ensure all the results were positive matches will get you the result you desire.

use And with multiple variables in switch-case statements?

I have a code like this :
if(x==1 && y==2){
something...
}
else if(x==4 && y==6){
something...
}
else{
something...
}
Can I convert it to a switch case statement
You can't since switch is taking only one variable; and you have two variables.
You can always refactor your code a little bit though.
Like:
if (x==1 && y==2) {
//something...
return;
}
if (x==4 && y==6) {
//something...
return;
}
//something...
Much more readable (imho).
EDIT
This is crazy :) but since your variables are integer you can combine them into one long variable and use the switch.
Like:
switch ((((long)x) << 32) + y) {
case ((1L << 32) + 2):
break;
case ((4L << 32) + 6):
break;
default:
break;
}
Well.... if you have to this would work: WARNING - HACK CODE
int x;
int y;
var #switch= new Dictionary<Func<bool> statement, Action doIfTrue>
{
{() => x == 1 && y == 2, something},
{() => x == 4 && y == 6, somethingElse}
{() => true, () = {} } // fallback action
};
#switch.Where(pair => pair.Key()).Select(pair => pair.Value).First()();
This could probably be written a bit more terse.
It does depend a bit on how the bigger picture code looks, but I've used the following technique occasionally.
switch (x*100+y) {
case 102:
// something...
break;
case 406:
// something...
break;
default:
// something...
}
It's pretty readable, but can get out of hand.

C# console random number guess game

I'm working on a random number guessing game as a c# console program. It's done with the code and working. However, there is a part that I want to make better:
I declared an instance of a Guess class I created, now how to make this part more efficient?
int counter = 0;
do
{
myGuess.UserGuess = GetUserGuess(); //read user guess
if (myGuess.Compair() == "match")
{
Console.WriteLine("\n\t Correct!You WIN !");
}
else if (myGuess.Compair() == "high")
{
if (counter < 3)
Console.WriteLine("\n\tTry a lower number,");
else
Console.WriteLine("\n\tSorry you LOSE !, The right number is " + myGuess.RndNum);
counter++;
}
else if (myGuess.Compair() == "low")
{
if (counter < 3)
Console.WriteLine("\n\tTry a higher number,");
else
Console.WriteLine("\n\tSorry you LOSE !, The right number is " + myGuess.RndNum);
counter++;
}
} while (myGuess.Compair() != "match" && counter < 4);
Thanks in advance.
What does "Compair()" function look like? It seems like that could return an integer rather than a string for a simpler function. An example of that looks like:
// just an example implementation
public int Compair() {
if (UserGuess < actualValue) return -1;
if (UserGuess > actualValue) return 1;
return 0;
}
And then your routine becomes:
int counter = 0;
bool success = false;
do
{
myGuess.UserGuess = GetUserGuess();
int compair= myGuess.Compair()
switch (compair) {
case 0:
Console.WriteLine("\n\t Correct!You WIN !");
success = true;
break;
case 1:
case -1:
if (counter < 3) Console.WriteLine("\n\tTry a {0} number,", compair == -1 ? "lower" : "higher");
break;
}
counter++;
if (counter >= 3 && !success)
Console.WriteLine("\n\tSorry you LOSE !, The right number is " + myGuess.RndNum);
} while (!success && counter < 4);
That should do it! This should be faster because it isn't using string comparisons, it might be a bit easier to read and it should have fixed a few logical issues.
Note - I made a few assumptions about the use of properties so this example might not compile out of the get but it should get you most of the way there. Best of luck!

Break inside switch Cannot Terminate FOR Loop [duplicate]

This question already has answers here:
Break out of a while loop that contains a switch statement
(15 answers)
Closed 9 years ago.
I have a code snippet :
int n = 0;
for (int i = 0; i < 50;i++)
{
n = checkStatus();
switch (n)
{
case 1:
break;
break;//This is unreachable and so i cannot Terminate the For Loop within the SWITCH
}
}
As described in a comment I cannot terminate the For Loop directly from the Switch, only if I declare a boolean and at the End of Switch test
if(LoopShouldTerminate)
break;
PS : or maybe I'm very confused!
[POST]
I got the message ,and the problem is Solved ,but i would like to asume that using Switch within a for loop isn't a god idea ,because i heard from lot of developer's i should break from loop in the moment when i get the desired result ,so using switch need's extra boolean or push the Int i value to 50 direclty , but what would happen if we're using while loop ?
Solution 1: Move the loop and the switch to different methods:
for(int i = 0; i < 50; ++i)
{
if (DoCheckStatus(i)) break;
}
...
bool DoCheckStatus(int i)
{
switch(CheckStatus(i))
{
case 1 : return true;
default: return false;
}
}
Solution 2: Adapt the above to eliminate the loop with an eager extension method:
static void DoWhile<T>(this IEnumerable<T> sequence, Func<T, bool> predicate)
{
foreach(T item in sequence)
if (!predicate(item)) return;
}
...
Enumerable.Range(0, 50).DoWhile(DoCheckStatus)
Solution 3: Adapt the above to eliminate the loop and the helper method:
Enumerable.Range(0, 50).DoWhile(i=>
{
switch(CheckStatus(i))
{
case 1 : return true;
default: return false;
}
});
You can use goto in order to break out of the loop within the switch.
int n = 0;
for (int i = 0; i < 50;i++)
{
n = checkStatus();
switch (n)
{
case 1:
goto outofloop;
}
}
:outofloop
// more code
One of the few good uses of goto...
Just change the value of i:
int n = 0;
for (int i = 0; i < 50;i++)
{
n = checkStatus();
switch (n)
{
case 1:
i += 50;
break;
}
}
If there is no other code after the switch you can just check in the for loop itself whether to continue looping:
bool doContinue = true;
for (int i = 0; i < 50 && doContinue; i++)
{
n = checkStatus();
switch (n)
{
case 1:
doContinue = false;
}
}
Can you place the loop inside of a method and just use return?
Example:
myLoopingMethod()
{
int n = 0;
for (int i = 0; i < 50;i++)
{
n = checkStatus();
switch (n)
{
case 1:
return;
}
}
}
Another option would be to use a traditional if/else instead of a switch/case. Then you can just use break and it will jump out of your for loop
You could use a boolean.
int n = 0;
for (int i = 0; i < 50; i++)
{
bool shouldBreak = false;
n = checkStatus();
switch (n)
{
case 1:
shouldBreak = true;
break;
}
if (shouldBreak)
break;
}
I don't know if there's other logic that needs to be performed after the loop is finished, but you could try using return instead. The other option is to set a boolean flag, and exit after the switch.
switch (n)
{
case 1:
return;
}
This smells of bad design; there are a couple of ways you could fix this:
If only one condition of your switch would break the outer loop, then simply check for that before entering the switch:
if(n == 1)
break;
switch(n) { }
If multiple conditions can break the loop, refactor to a more linq style query:
Enumerable.Range(0, 50).FirstOrDefault(x => listOfBreakCodes.Contains(checkStatus());
That should call checkStatus up to 50 times until it encounters a 1 (or other break codes), and then doesnt continue evaluating elements.

Categories

Resources