C
C#16mo ago
Krzak

❔ Quitting to main menu in console app

The app is used to monitor a habit with saving the data to a database. The user has to insert a date and one number (for example how many glasses of water they drank that day) and I wanted to make it so writing 0 in the console would result in quitting to main menu, but with the way I did it first, it kind of "opens" another menu in that menu? I read that usually these kinds of apps are done with a "while" loop but they don't mention going back, only closing. How to untangle this mess? (I'll post code snippets in a second)
26 Replies
phaseshift
phaseshift16mo ago
All you have to do to go back is... Nothing. When a function ends control automatically goes back to where it was
Krzak
Krzak16mo ago
so I overcomplicated this probably 😅
phaseshift
phaseshift16mo ago
Beginners typically keep calling 'menu()' thinking they're going back to the beginning, but in reality they're going deeper and deeper into a maze
Krzak
Krzak16mo ago
haha that's what I did lol but with this I can't just do nothing?
case "2": //add new
Console.WriteLine("How many glasses of water did you drink?");
GetQuantity();
Console.Clear();
GetDate();
var newDocument = new HabitModel(VerifiedDate, VerifiedQuantity);
var bsonDocument = newDocument.ToBsonDocument();
dbOperations.CreateRecord(MongoCollection, bsonDocument);
Console.WriteLine("New record created, press any key to return to menu.");
Console.ReadKey();
break;
case "2": //add new
Console.WriteLine("How many glasses of water did you drink?");
GetQuantity();
Console.Clear();
GetDate();
var newDocument = new HabitModel(VerifiedDate, VerifiedQuantity);
var bsonDocument = newDocument.ToBsonDocument();
dbOperations.CreateRecord(MongoCollection, bsonDocument);
Console.WriteLine("New record created, press any key to return to menu.");
Console.ReadKey();
break;
which probably means I have to kind-of-start-over I don't know how much to paste here so it makes sense
phaseshift
phaseshift16mo ago
Depends what is around this code, I guess Basically all you need is While not quitting Show menu Do action And you can use the same pattern for sub-menus etc as well.
Krzak
Krzak16mo ago
this is above
public void MainMenu()
{
Console.WriteLine("1 - view all records");
Console.WriteLine("2 - add new record");
Console.WriteLine("3 - edit a record");
Console.WriteLine("4 - delete a record");
Console.WriteLine("0 - quit");


string chosenOption = Console.ReadLine();
Console.Clear();
switch (chosenOption)
{
case "0": //quit
IsRunning = false;
break;

case "1": //view all
dbOperations.ReadAllRecords(MongoCollection);
Console.WriteLine("\nAll documents in the collection are listed. Press any key to return to main menu.");
Console.ReadLine();
break;

case "2": //add new...
public void MainMenu()
{
Console.WriteLine("1 - view all records");
Console.WriteLine("2 - add new record");
Console.WriteLine("3 - edit a record");
Console.WriteLine("4 - delete a record");
Console.WriteLine("0 - quit");


string chosenOption = Console.ReadLine();
Console.Clear();
switch (chosenOption)
{
case "0": //quit
IsRunning = false;
break;

case "1": //view all
dbOperations.ReadAllRecords(MongoCollection);
Console.WriteLine("\nAll documents in the collection are listed. Press any key to return to main menu.");
Console.ReadLine();
break;

case "2": //add new...
and this in Program.cs
while (habitsApp.IsRunning)
{
habitsApp.MainMenu();
}
while (habitsApp.IsRunning)
{
habitsApp.MainMenu();
}
told you, tangled mess XD
phaseshift
phaseshift16mo ago
It's not too bad. Does 0 option set IsRunning to false?
Krzak
Krzak16mo ago
yes and no it returns false when 0 is written in the main menu but not in the "submenus"/"options"
phaseshift
phaseshift16mo ago
Ok. So is your problem specifically when you're in sub menus? From your earlier question asking about doing nothing in option 2, yes, doing nothing should be fine afaict
Krzak
Krzak16mo ago
yeah and it's because of this:
private int GetQuantity()
{
Console.WriteLine("Use only integers. Write 0 to return to main menu.");
string userQuantity = Console.ReadLine();
while (true)
{
if (IsInputZero(userQuantity))
{
QuitToMainMenu();
}
else if (!IsQuantityInteger(userQuantity))
{
Console.WriteLine("The value wasn't an integer, try again. Write 0 to return to main menu.");
userQuantity = Console.ReadLine();
}
else
{
break;
}
}
return VerifiedQuantity;
}


private bool IsInputZero(string consoleInput)
{
if (consoleInput == "0")
{
QuitToMainMenu();
}
return false;
}
private void QuitToMainMenu()
{
Console.WriteLine("Returning to main menu...");
Console.Clear();
MainMenu();
}
private int GetQuantity()
{
Console.WriteLine("Use only integers. Write 0 to return to main menu.");
string userQuantity = Console.ReadLine();
while (true)
{
if (IsInputZero(userQuantity))
{
QuitToMainMenu();
}
else if (!IsQuantityInteger(userQuantity))
{
Console.WriteLine("The value wasn't an integer, try again. Write 0 to return to main menu.");
userQuantity = Console.ReadLine();
}
else
{
break;
}
}
return VerifiedQuantity;
}


private bool IsInputZero(string consoleInput)
{
if (consoleInput == "0")
{
QuitToMainMenu();
}
return false;
}
private void QuitToMainMenu()
{
Console.WriteLine("Returning to main menu...");
Console.Clear();
MainMenu();
}
quitting runs a menu again hahaaa
phaseshift
phaseshift16mo ago
Yeah ok. That's the problem
Krzak
Krzak16mo ago
I don't know what to do about it so it probably means there's quite a bit to do again
phaseshift
phaseshift16mo ago
Two tips. Try to make functionality do just one thing. E.g why is getting a quantity mixed with quitting to main menu. The other is you can have a function indicate whether to keep going or not by returning a bool Like bool TryGetInt(out int number)
Krzak
Krzak16mo ago
How to define "one thing"? It's always an issue for me
phaseshift
phaseshift16mo ago
Yeah it can be ambiguous But getting a number is a different thing to a decision about menu navigation
Krzak
Krzak16mo ago
hmm okay makes sense
phaseshift
phaseshift16mo ago
Like, how should a small utility to ask for a number have the power to move through menus No, they're completely separate concepts
Krzak
Krzak16mo ago
So for the 0 to work as exit I should construct the procedures in a way that would lead to leaving the method (for example getting a date)? A sort of shortcut to "break;"?
phaseshift
phaseshift16mo ago
Yes. For utilities getting data, they should always return something. If you want the option for it to fail, or be cancelled, then it still needs to return, but you use the "try get" pattern So int getint() or bool TryGetInt(out int number)
Krzak
Krzak16mo ago
ooh alright that's so clever This proved to be more tricky than I anticipated >.> for the 0 to work all that procedure for adding has to, in the end, become 1 function? I'd think so if it has to react immediately for that 0 on any stage 🤔
phaseshift
phaseshift16mo ago
I don't really understand what youre saying
Krzak
Krzak16mo ago
I'm not entirely sure myself okay so um if the only thing that changed was changing GetQuantity/GetDate to returning bool then it wouldn't stop the rest from executing even if it returned false unless I got it wrong?
phaseshift
phaseshift16mo ago
well something reacts according to the bool. if true, then do something with data, if false then... whatever you want and 'whatever you want' includes returning from the method, ie not doing anything else
Krzak
Krzak16mo ago
that didn't work out :x whoops I came up with this but it doesn't work for the date part because 0 isn't a valid dd-mm-yyyy format
case "2": //add new

while(true)
{
Console.WriteLine("How many glasses of water did you drink?");


if (GetQuantity() != 0)
{


if(GetDate() != "0")
{
var newDocument = new HabitModel(VerifiedDate, VerifiedQuantity);
var bsonDocument = newDocument.ToBsonDocument();
dbOperations.CreateRecord(MongoCollection, bsonDocument);
Console.WriteLine("New record created, press any key to return to menu.");
Console.ReadKey();
}

}
break;
}
break;
case "2": //add new

while(true)
{
Console.WriteLine("How many glasses of water did you drink?");


if (GetQuantity() != 0)
{


if(GetDate() != "0")
{
var newDocument = new HabitModel(VerifiedDate, VerifiedQuantity);
var bsonDocument = newDocument.ToBsonDocument();
dbOperations.CreateRecord(MongoCollection, bsonDocument);
Console.WriteLine("New record created, press any key to return to menu.");
Console.ReadKey();
}

}
break;
}
break;
it looks weird
phaseshift
phaseshift16mo ago
why are they even returning a value that you dont use for anything Seems like you save the data to VerifiedDate/Quantity, so GetQuantity should return a bool to say whether it worked or not
if (GetQuantity() && GetDate())
{
// do something
}
if (GetQuantity() && GetDate())
{
// do something
}
The while (true) is pointless as well
Accord
Accord16mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.