I'm trying to finish a project, but the conditions I set in the if statement are fulfilled and not running the linked code. basically, I type null and it keeps running, even though it should set running to false, and it doesn't print the answer at the bottom. it's supposed to be a random number generator with variables linked to each number. I'm still new to C#, So I'm probably just using things wrong, as usual.
edit: added some fixes. also the line at the end, Console.WriteLine(answer) on line 99, is being considered unreachable, and it is the main way for me to know if my code works. if someone could let me know how to fix that, it would be great. also, could someone tell me some alternatives to the goto statement? edit 2: thanks for the help, It works now.
using System.Collections;
internal class Program
{
private static void Main(string[] args)
{
string item1;
string item2;
string item3;
string item4;
string item5;
string answer;
item1 = "";
item2 = "";
item3 = "";
item4 = "";
item5 = "";
answer = "";
bool Running = true;
while (Running)
{
Console.Write("Enter item 1: ");
item1 = Console.ReadLine();
Console.WriteLine("Enter item 2: ");
item2 = Console.ReadLine();
Console.WriteLine("Enter item 3, or type null: ");
item3 = Console.ReadLine();
if (item3 == "null" )
{
Running = false;
item3 = "";
}
Console.WriteLine("Enter item 4, or type null: ");
item4 = Console.ReadLine();
if (item4 == "null")
{
Running = false;
item4 = "";
}
Console.WriteLine("Enter item 5: ");
item5 = Console.ReadLine();
if (item5 == "null")
{
Running = false;
item5 = "";
}
}
reroll:
Random random = new Random();
switch (random.Next(1, 6))
{
case 1:
{
answer = item1;
break;
}
case 2:
{
answer = item2;
break ;
}
case 3:
{
if (item3 == "")
{
goto reroll;
}
answer = item3;
break;
}
case 4:
{
if (item4 == "")
{
goto reroll;
}
answer = item4;
break;
}
case 5:
{
if (item5 == "")
{
goto reroll;
}
answer = item5;
break;
}
Console.WriteLine(answer);
}
}
}
As far as your code is concerned I have several issues to bring up
When you feel the need to define variables like item1, item2, item3, etc then it is time to consider arrays and collections. You are learning bad habits otherwise. A fixed size array string[] items would suffice here, although a better solution would be to use a variable size List<string> items.
Try to divide up your code into functional parts, and use functions in order to minimize any possible side effects. This way you control the flow of information better.
If it all possible avoid goto, unless you absolutely need to. It makes code much harder to trace out and bugs are harder to catch. Alternatively use either a fixed count iteration like a for() loop, or a general while() statement and use the keyword break to exit the loop (or continue to move to the next iteration).
A lot of other smaller issues are a matter of experience with programming.
The way I read the code you are trying to do something like this
Enter Item 1
aaa
Enter Item 2
bbb
Enter Item 3
ccc
Enter Item 4 or press [ENTER] or type null to end.
ddd
Enter Item 5 or press [ENTER] or type null to end.
null
User List:
aaa
bbb
ccc
ddd
Randomly Selected Item: ddd
Here is one way of getting there using the principles laid out above. The code below is intended for learning purposes, with the hope that you are going to be able to follow along and understand what does what.
class Program
{
static readonly Random rng = new Random();
static void Main(string[] args)
{
// Get user inputs
string[] items = AskItemsFromUser(minItems:3, maxItems:5);
// Show what was entered as a list
Console.WriteLine("User List:");
Console.WriteLine(string.Join(Environment.NewLine, items));
Console.WriteLine();
// Show random item from list
string item = PickRandom(items);
Console.WriteLine($"Randomly Selected Item: {item}");
}
public static string[] AskItemsFromUser(int minItems, int maxItems)
{
List<string> items = new List<string>();
while (items.Count < maxItems)
{
// Change the prompt depending on the number of items entered.
if (items.Count >= minItems)
{
Console.WriteLine($"Enter Item {items.Count + 1} or press [ENTER] or type null to end.");
}
else
{
Console.WriteLine($"Enter Item {items.Count + 1}");
}
// get user input
string input = Console.ReadLine();
// if input=="null" or an empty string
if (input.Equals(string.Empty) || input.Equals("null"))
{
// and min # of items already reached
if (items.Count >= minItems)
{
// the exit loop
break;
}
}
else
{
// add user input to list
items.Add(input);
}
}
Console.WriteLine();
return items.ToArray();
}
public static string PickRandom(params string[] items)
{
// Use a random number generator to pick an item
// index = 0..count-1
int index = rng.Next(0, items.Length);
return items[index];
}
}
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
Here is my code.The first and third points of the program work properly, but the second does not.
If you press the "2" key, the data from the text should be transferred to the list, and the entered line should be deleted in the list,but for reasons I do not understand, the program crashes when entering a value into a string.
using System;
using System.IO;
using System.Collections;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
String line;
List<String> list = new List<String>();
String writePath = #"C:\Work\X\hta.txt";
for (; ; )
{
Console.WriteLine("1.Add An Employee");
Console.WriteLine("2.Delete An Employee");
Console.WriteLine("3.Save Database");
Console.WriteLine("4.Exit");
int choice = Convert.ToInt32(Console.ReadLine());
if (choice == 4)
{
break;
}
switch (choice)
{
case 1:
for (; ; )
{
Console.WriteLine("1.Add A Manager");
Console.WriteLine("2.Add An Engineer");
Console.WriteLine("3.Exit");
int choice1 = Convert.ToInt32(Console.ReadLine());
if (choice1 == 3)
{
break;
}
switch (choice)
{
case 1:
line = Console.ReadLine();
list.Add(line);
break;
case 2:
line = Console.ReadLine();
list.Add(line);
break;
}
}
break;
case 2:
list.Clear();
using (StreamReader sr = new StreamReader(writePath))
{
while (!sr.EndOfStream)
{
list.Add(sr.ReadLine());
}
}
foreach(var item1 in list)
{
String linex = Console.ReadLine();
if (item1.Equals(linex))
{
list.Remove(linex);
}
}
break;
case 3:
Console.WriteLine("Do you want to continue?");
String x = Console.ReadLine();
if (x.Equals("yes")){
using (StreamWriter sw = new StreamWriter(writePath))
{
foreach (var item in list)
{
sw.WriteLine(item);
}
}
}
else
{
break;
}
break;
}
Console.ReadLine();
}
}
}
}
In this loop:
foreach(var item1 in list)
{
String linex = Console.ReadLine();
if (item1.Equals(linex))
{
list.Remove(linex);
}
}
You are reading input from the console for every item in the list. This would possibly look like a crash or not quite infinite loop as it's probably not what you're expecting. Instead you should read the input once then loop around the list. However, you should note that if you remove an item from the list while looping through it, you may also get strange behavior. Try just removing the string without the loop:
String linex = Console.ReadLine();
if (list.Contains(linex))
{
list.Remove(linex);
}
may be you writePath of value [C:\Work\X\hta.txt] file do not exists,so you should create an empty text file on you disk.
I am a beginner at coding - I just started a week ago. I am trying to develop a program where the user can either see all of the names in a list or add a name to a list. When the user prompts to see the names in the list, and then decides to take another action, they are stuck in an endless loop where they can only see the names again. I want them to be able to go back to the start and choose to either see the names or add a name.
I've tried reorganizing and looking things up, but I'm still at a loss.
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
List<string> names = new List<string>();
names.Add("Vasti");
names.Add("Cameron");
names.Add("Ezra");
names.Add("Tilly");
bool program = false;
bool program2 = false;
Console.WriteLine("Welcome to the names lost! If you wish to add
a name to the list, type 1. If you want to see current names in
the list,
type 2.");
string userChoice = Console.ReadLine();
do
{
switch (userChoice)
{
case "1":
Console.WriteLine("Add a name to the squad.");
string userAddName = Console.ReadLine();
names.Add(userAddName);
break;
case "2":
Console.WriteLine("Here's the list:");
foreach (string name in names)
{
Console.WriteLine(name);
}
Console.WriteLine("Wanna do that again? Type yes or
no.");
do
{
string userContinue = Console.ReadLine();
switch (userContinue)
{
case "yes":
program = true;
program2 = false;
break;
case "Yes":
program = true;
program2 = false;
break;
case "no":
program = false;
program2 = false;
break;
case "No":
program = false;
program2 = false;
break;
default:
Console.WriteLine("Please enter either
yes or no");
userContinue = Console.ReadLine();
program2 = true;
break;
}
}
while (program2 == true);
break;
default:
Console.WriteLine("Please type either 1 or 2 to
select an option.");
break;
}
}
while (program == true);
}
}
I expect the user to return to the beginning prompt, but they are stuck in the same prompt over and over. There are no error messages.
Two major things to cover your difficulties.
First, the input hint should be in the loop so it can show when each loop begin.
Second, do while loop decide if the loop should continue at the end and in your design; it depends on what user input which should be directly utilized as while condition.
Therefore, your code could be simplified as
public static void Main()
{
List<string> names = new List<string>() { "Vasti", "Cameron", "Ezra", "Tilly" };
string userChoice = "";
do
{
Console.WriteLine($#"Welcome to the names lost!{Environment.NewLine} If you wish to add a name to the list, type 1.{Environment.NewLine} If you want to see current names in the list, type 2.");
userChoice = Console.ReadLine();
switch (userChoice)
{
case "1":
Console.WriteLine("Add a name to the squad.");
string userAddName = Console.ReadLine();
names.Add(userAddName);
break;
case "2":
Console.WriteLine("Here's the list:");
foreach (string name in names)
{
Console.WriteLine(name);
}
break;
default:
Console.WriteLine("Please type either 1 or 2 to select an option.");
break;
}
Console.WriteLine(#"Wanna do that again? Type yes or no.");
userChoice = Console.ReadLine();
}
while (userChoice.Equals("yes", StringComparison.OrdinalIgnoreCase));
Console.WriteLine("Program finished");
Console.ReadLine();
}
Change the do{}while() loops to regular while(){} loops.Move string userChoice = Cosole.ReadLine(); inside of the top while loop or you will never ask for other options. . . Also set the ((bool program=true; and bool program=true;)) at the beginning. Do{}while() loops do everything inside the {} first then check to see if the while statement is still true.
So I want to make a list of names. I want this list to go on until user inputs 0 to quit, after user types 0 I want all names to be displayed. You probably see what I'm trying to do from the code below...that "typedName" is there just so you see what I'm trying to do.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<string> names = new List<string>();
Console.WriteLine("Type in 0 to end.");
bool over = false;
while (over != true)
{
names.Add(Console.ReadLine());
if(typedName == "0")
{
over = true;
}
}
Console.WriteLine("Entered names : ");
names.ForEach(Console.WriteLine);
Console.ReadLine();
}
}
}
First you need the typedName to be captured and then check if it is equal to 0.
if it is not add it to the list
List<string> names = new List<string>();
Console.WriteLine("Type in 0 to end.");
while (true)
{
var typedName = Console.ReadLine();
if (typedName.Equals("0"))
{
break;
}
names.Add(typedName);
}
Console.WriteLine("Entered names : ");
foreach(var name in names)
{
Console.WriteLine(name);
}
Console.ReadLine();
if(typedName == "0")
Well, what is typedName? Or what should it be? I suspect it should be the input entered by the user, something like this:
var typedName = Console.ReadLine();
You can then add it to the list by using that variable:
names.Add(typedName);
And compare it with "0" as you already do, etc.
your code is not complete that is why is not working...
you are missing the most important part:
populate the list if and only if typedName != "0"
while (!over)
{
var typedName =Console.ReadLine();
if(typedName == "0")
{
over = true;
}else
{
Console.WriteLine("Enter a name... ");
names.Add(Console.ReadLine());
}
...
}
So sorry for this vague question... its doing my head in...
Basically just a test project, use the [+] key to add a bunch of values into the List.... The arrow keys need to go up and down the List values...
When a new value is added to the list the "historySelected" is reset, so that the 'Up Arrow'.. always selects the last item added in the List first, and then if you keep pressing it, it goes back through the List values. At anytime if the 'Down Arrow' key is pressed it needs to go back to the previous value in the List of values. At no point should a Up Arrow key followed by a Down Arrow key show the same List value, and vice versa..
The behavior I'm looking for is much like a developer console with a command history, where Up arrow goes further back in history, and Down arrow the opposite.
Again apologies for the code, its been through so many test changes, currently this works going Up arrow to the start of the List value, and then using the Down arrow to go all the back to the highest List index... but the problem is if you go half way through the List (or inbetween anyway), and switch from Up arrow.. to Down arrow.. the values increment/decrement don't act accordingly... I can't seem to get the right codelogic for it.
Any help or suggestions thanks.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ArrowKeys {
class Program {
//public static List<string> cmdHistory = new List<string>() { "1", "2", "3", "4", "5" };
public static List<string> cmdHistory = new List<string>();
public static int cmdHistoryCount = 0;
public static int historySelected = 0;
public static int num = 0;
public static string current = "";
public enum UpDown {
reset,
up,
down
};
public static UpDown LastUpDown;
static void Main(string[] args) {
bool running = true;
while (running) {
ConsoleKeyInfo kb = Console.ReadKey();
switch (kb.Key) {
case ConsoleKey.Escape:
Console.WriteLine("Exit");
running = false;
return;
case ConsoleKey.Add:
cmdHistory.Add(num.ToString());
cmdHistoryCount++;
historySelected= cmdHistoryCount;
LastUpDown = UpDown.reset;
Console.WriteLine(string.Join(" ", cmdHistory.Cast<string>().ToArray()));
num++;
break;
case ConsoleKey.UpArrow:
UpArrow();
LastUpDown = UpDown.up;
Console.WriteLine("UpArrow pressed");
Console.WriteLine(current);
break;
case ConsoleKey.DownArrow:
DownArrow();
LastUpDown = UpDown.down;
Console.WriteLine("DownArrow pressed");
Console.WriteLine(current);
break;
}
}
}
public static int Clamp(int value, int min, int max) {
return (value < min) ? min : (value > max) ? max : value;
}
public static void UpArrow() {
if (cmdHistoryCount != 0) {
if (LastUpDown == UpDown.down) {
if (historySelected - 1 == 0) {
return;
}
}
current = cmdHistory[historySelected - 1];
if (historySelected - 1 == 0) {
return;
}
historySelected--;
}
}
public static void DownArrow() {
if (cmdHistoryCount != 0) {
if (LastUpDown == UpDown.up) {
if (historySelected + 1 > cmdHistoryCount) {
return;
}
}
current = cmdHistory[historySelected - 1];
if (historySelected + 1 > cmdHistoryCount) {
return;
}
historySelected++;
}
}
}
}
It sounds like you simply need to stop your index going out of range. It's not clear what the existing code was intended to do, but your clarification seems to imply it's not necessary. Try this:
public static void UpArrow()
{
historySelected = Math.Max(0, historySelected - 1);
current = cmdHistory[historySelected];
}
public static void DownArrow()
{
var maxIndex = cmdHistory.Count - 1;
historySelected = Math.Min(maxIndex, historySelected + 1);
current = cmdHistory[historySelected];
}
If I'm understanding what you're looking for correctly, a pair of dueling stacks might work for your case. They're going to give you the FILO/LIFO style item access you're looking for. Drop the List and do something like:
var UpStack = new Stack<string>();
var DownStack = new Stack<string>();
On "new item"
UpStack.Push(newItem);
On "Up"
DownStack.Push(UpStack.Pop());
On "Down"
UpStack.Push(DownStack.Pop());
If you wanted a "buffer" item that isn't in either of the stacks, that's easy enough to do by just Popping into the buffer item. It's a little more management, because you'd have to push it onto one stack, then pop the other each time, but it's whatever. There's also the Peek() method, which gets the item on top of a Stack without Popping it, so you use that for your display item, as well.
I am having a problem constructing a loop WHICH will COMPARE a VAR(userSelection) against the name ITEMS in my LIST(Listings). The goal is that if userSelection MATCHES name, getDescription will Console.WriteLine the GetDefinition and display the definition of the word in the list matched. Most of my code is working, and i've been working on this assignment for a week.
I'm very much a newb, please assume I know nothing. All help is appreciated. I think this would be a while loop, but i've played with all the loops now and am lost and confused. I'm a newb, please use small words and be as detailed as you can afford to be. It's greatly appreciated. Thank you.
My C# Program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;// Needed for Streaming...
using System.IO;// Needed for Streaming...
namespace a090___StreamReader_DictionarySearch
{
class Program
{
private const String FILE_NAME = "dictionary.txt";//establish text file instance
public void Play()
{
do
{
DisplayTitle();
List<Listing> items = LoadListings();//create a list of WordDef objects
Console.Write(string.Join(" | ", items.Select(x => x.GetName()))); //Console.Write("\b \b");// Backspace would also of worked
DisplayText("\n\nPlease enter a word from the selections about to see it's definition");// Nice use of PROMPT
String userSelection = Console.ReadLine().ToLower();//Capture input
//loop through all of the listings, and compare each one to userSelection
//Then once it equals print definition
bool found = false;
foreach (Listing item in items)
{
if (userSelection == item.GetName())
{
Console.WriteLine("You selected: " + userSelection +
"\nWhich Means: " + item.GetDefinition());
found = true;
break;
}
}
if (!found)
{ Console.WriteLine("I'm sorry, I don't have a match for that."); }
} while (PlayAgain());
Salutation();
}
//ToolBox -- my program specific tools
public List<Listing> LoadListings()//load entries display as list
{
StreamReader fileIn = new StreamReader(FILE_NAME);
List<Listing> entry = new List<Listing>();
//loop through every line of the file
while (!fileIn.EndOfStream)
{
String line = fileIn.ReadLine();
String[] pieces = line.Split(':');
if (pieces.Length < 1) continue;//error handling - set to length of text items
Listing myListing = new Listing(pieces[0], pieces[1]);
entry.Add(myListing);
}
fileIn.Close(); return entry;
}
//MaxBox -- my useful tools
public void DisplayText(String StringNameIs)
{ Console.WriteLine(StringNameIs); }//Where are we?
public Boolean PlayAgain()
{
Console.Write("\n\nDo you select again? (y)es or (n)o: ");
String command = Console.ReadLine().ToLower();
if (command == "y" || command == "yes") return true;
return false;
}
public void Salutation()
{ Console.Clear(); Console.WriteLine("Ti Do - oh - oh Ti Do -- So Do!"); } //The last line from the 'do-re-mi' song from the Sound of Music
public void DisplayTitle()
{ Console.Clear(); Console.WriteLine(">>>-- A Dictionary of Sounds --<<< \n"); } //Announce Our Program
static void Main(string[] args)
{
Program DictionaryLookup = new Program();
DictionaryLookup.Play();
Console.Read();
}
}
}
My Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace a090___StreamReader_DictionarySearch
{
class Listing
{
private String name;
private String definition;
public Listing(String name, String definition)
{ this.name = name;
this.definition = definition;}
public String GetName() {return name;}
public String GetDefinition() {return definition; }
}
}
My Text File
Doe: a deer, a female deer
Ray: a drop of golden sun
Me: a name I call myself
Far: a long, long way to run
Sew: a needle pulling thread
La: a note to follow Sew
Tea: a drink with jam and bread
This is untested, but should work, using your existing code.
Assuming each "name" (doe, ray, etc) only occurs once (which they do), then you can use Linq's "SingleOrDefault", which will return null if no match is found.
var selection = items.SingleOrDefault(x => x.GetName() == userSelection);
if (selection == null)
Console.WriteLine("I'm sorry, I don't have a match for that.");
else
Console.WriteLine("You selected: " + userSelection +
"\nWhich Means: " + selection.GetDefinition());
To ignore case during comparison, try modifying the above:
... items.SingleOrDefault(x => String.Compare(x.GetName(), userSelection, true));
There are a number of other things you could change here, but perhaps it won't matter for your assignment. For example, I'd eliminate the private variables in your Listing class and change the public "get" methods into properties:
public String Name { get; private set; }
public String Definition { get; private set; }
Substitute the code
while (true)
{
if (userSelection == name)
{Console.WriteLine("You selected: " + Listing.userSelection() +
"\nWhich Means: " + Listing.items.GetDefinition());}
}
else { Console.WriteLine("I'm sorry, I don't have a match for that."); }
with this
bool found = false;
foreach (Listing item in items)
{
if (userSelection == item.GetName().ToLower())
{
Console.WriteLine("You selected: " + userSelection +
"\nWhich Means: " + item.GetDefinition());
found = true;
break;
}
}
if (!found)
{ Console.WriteLine("I'm sorry, I don't have a match for that."); }
I have use the foreach statement; with this statement you can iterate all items of your collection.
Inside the foreach loop I check if the element Name is equal with the user input, if match I set a bool variable indicating element found.
After the loop if element not found print the message.
NB Obviously this code can be written more concisely with LINQ.