I'm new to C# and programming all together and am trying to get this to run. I have spent the entire day reading about Static and non Static and cant seem to get it right. Any and all help would be appreciated as I need this code working by tomorrow evening. The following is the Main and Course Class:
using System;
namespace Lab4
{
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("Welcome to the Course Monitoring System v1.0");
Course.Menu ();
Course.Choice ();
}
}
}
This is the Course Class:
using System;
using System.Collections.Generic;
namespace Lab4
{
public class Course
{
private string courseNumber;
private string courseName;
private int courseHours;
private string descript;
private string prefix;
public List<Course> school = new List<Course> ();
private int howmany=0;
private int totalcourse=0;
//This section is for returning and adjusting values of private data through the main program.
public string cn{
get {return courseNumber; }
set {if (value != null)
cn = value;
}
}
public string name{
get{ return courseName; }
set{if (value!="")
name=courseName;
}
}
public int hours{
get {return courseHours; }
set {if (value != 0)
hours = value;
}
}
public string script {
get {return descript; }
set {
if (value != "")
script = value;
}
}
public string pfix {
get {return prefix; }
set {if (value != "")
pfix = value;
}
}
public Course (string pfix, string name, string cn, int hours, string script)
{
courseNumber = cn;
courseName = name;
courseHours = hours;
descript= script;
prefix = pfix;
}
//This portion of code overrides the string and allows it to output the information held within the constructor.
public override string ToString ()
{
return prefix + " " + courseName+" " + courseNumber + " " + descript + " It is a " + courseHours + " hour course.";
}
//The menu application for my program
public static void Menu()
{
Console.WriteLine ("Please choose from one of the following options: ");
Console.WriteLine ("......................................................................");
Console.WriteLine ("1.)Start a new Course List.");
Console.WriteLine ("2.)Delete Course from Current List.");
Console.WriteLine ("3.)Print Current Course List.");
Console.WriteLine ("4.)Add Course to Current List.");
Console.WriteLine ("5.)Shutdown Program");
}
//This is the controller for the menu. It allows for functionality to control the tasks requested by the user.
public void Choice()
{
int selection=int.Parse(Console.ReadLine());
while (selection >5 || selection < 1) {
Console.WriteLine ("Choice invalid. Please choose between 1 and 5.");
selection = int.Parse (Console.ReadLine ());
}
if (selection == 4) {
Add ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 2) {
Delete ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 3) {
Print ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 1) {
New ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 5) {
Console.WriteLine ();
Console.WriteLine ("Thank you for using this program for your scheduling needs.");
}
}
//This method when called will print a numbered list of courses refrenced by the created List
public void Print()
{
Console.WriteLine ();
Console.WriteLine ("Course Name.........Course Number.........Course Description........Course Hours");
Console.WriteLine ("********************************************************************************");
for (int i = 0; i < totalcourse; i++) {
int place = i + 1;
Console.WriteLine (place+".)"+school [i]);
}
Console.WriteLine ();
}
//This method will add an item to the end of the current list.
public void Add()
{
Console.WriteLine ();
Console.Write ("How many courses would you like to add at the end of your index?");
int numberAdded = int.Parse(Console.ReadLine ());
for (int i = 0; i < numberAdded; i++) {
Console.WriteLine ("Please use the following templet for your entries...");
Console.WriteLine ("Course Prefix, Course Name, Course Number, Course Hours, Course Description ");
school.Add (new Course (prefix = Console.ReadLine (), courseName = Console.ReadLine (),
courseNumber = Console.ReadLine (), courseHours = int.Parse (Console.ReadLine ()), descript = Console.ReadLine ()));
}
totalcourse = totalcourse + numberAdded;
Console.WriteLine ();
}
//This method will delete an Item from the list based on the position 0-x based on x-1, the output that is seen by the user. After each iteration it will
//also create a list so that further deletions can be managed approiatly.
public void Delete()
{
if (totalcourse < 1) {
Console.WriteLine ();
Console.WriteLine ("There is nothing to delete!");
Console.WriteLine ();
}else{
Console.WriteLine ();
Console.Write ("How many entries do you wish to remove?");
int removed = int.Parse (Console.ReadLine ());
for (int i = 0; i < removed; i++) {
Console.WriteLine ("Please type the index line number of the item you wish to remove.");
int delete = int.Parse (Console.ReadLine ());
school.RemoveAt (delete - 1);
totalcourse = totalcourse - 1;
Print ();
}
}
Console.WriteLine ();
}
//This method is called to create a new list of Courses to be created by the user.
public void New()
{
Console.WriteLine ();
if (howmany > 0) {
Clear ();
} else {
Console.Write ("How many courses do you want to create? ");
howmany = int.Parse (Console.ReadLine ());
Console.WriteLine ();
for (int i = 0; i < howmany; i++) {
Console.WriteLine ();
school.Add (new Course (prefix = Console.ReadLine (), courseName = Console.ReadLine (), courseNumber = Console.ReadLine (), courseHours = int.Parse (Console.ReadLine ()), descript = Console.ReadLine ()));
}
totalcourse = totalcourse + howmany;
Console.WriteLine ();
}
}
//If there is already a list in place this method will be called and you will be asked if you wish to delete and start new.
public void Clear()
{
Console.WriteLine ();
Console.Write ("You want to discard old work and start a new list? Enter True or False...:");
bool clean=bool.Parse(Console.ReadLine());
if (clean == true) {
school.Clear ();
totalcourse = 0;
howmany = 0;
New ();
} else
Console.WriteLine ("No changes will be made. Exiting to Main Menu...");
Console.WriteLine ();
}
/* public static void Myfour ()
{
Console.WriteLine ();
Console.WriteLine ("These are four pre loaded courses.");
Course c1 = new Course ("MISSILE", 84, 3, "The Course is for missiles", "CRN");
Console.WriteLine (c1);
Console.WriteLine ();
}*/
}
}
Your Course class needs to be static:
public class Course
and so does your choice method:
public static void Choice()
Static means you can use members (e.g. a method) of a class without having to create an instance of the class using 'new'. This is what you're trying to do, so the method and container class both need the static modifier. You'll need to make all the other methods in your 'Course' class static as well though.
Or, why don't you just create an instance of your Course class in your Main method:
Course myCourse = new Course();
myCourse.Menu();
myCourse.Choice();
Then your code will work
This should get you started. What I have done is
Made the constructor without arguments
Created instance of Course in main method and invoke its methods
This is by no means complete but should get you started.
using System;
using System.Collections.Generic;
namespace Lab4
{
public class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("Welcome to the Course Monitoring System v1.0");
var c = new Course();
c.Menu();
c.Choice();
}
}
public class Course
{
private string courseNumber;
private string courseName;
private int courseHours;
private string descript;
private string prefix;
public List<Course> school = new List<Course> ();
private int howmany=0;
private int totalcourse=0;
//This section is for returning and adjusting values of private data through the main program.
public string cn{
get {return courseNumber; }
set {if (value != null)
cn = value;
}
}
public string name{
get{ return courseName; }
set{if (value!="")
name=courseName;
}
}
public int hours{
get {return courseHours; }
set {if (value != 0)
hours = value;
}
}
public string script {
get {return descript; }
set {
if (value != "")
script = value;
}
}
public string pfix {
get {return prefix; }
set {if (value != "")
pfix = value;
}
}
public Course()
{
}
public Course (string pfix, string name, string cn, int hours, string script)
{
courseNumber = cn;
courseName = name;
courseHours = hours;
descript= script;
prefix = pfix;
}
//This portion of code overrides the string and allows it to output the information held within the constructor.
public override string ToString ()
{
return prefix + " " + courseName+" " + courseNumber + " " + descript + " It is a " + courseHours + " hour course.";
}
//The menu application for my program
public void Menu()
{
Console.WriteLine ("Please choose from one of the following options: ");
Console.WriteLine ("......................................................................");
Console.WriteLine ("1.)Start a new Course List.");
Console.WriteLine ("2.)Delete Course from Current List.");
Console.WriteLine ("3.)Print Current Course List.");
Console.WriteLine ("4.)Add Course to Current List.");
Console.WriteLine ("5.)Shutdown Program");
}
//This is the controller for the menu. It allows for functionality to control the tasks requested by the user.
public void Choice()
{
int selection=int.Parse(Console.ReadLine());
while (selection >5 || selection < 1) {
Console.WriteLine ("Choice invalid. Please choose between 1 and 5.");
selection = int.Parse (Console.ReadLine ());
}
if (selection == 4) {
Add ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 2) {
Delete ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 3) {
Print ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 1) {
New ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 5) {
Console.WriteLine ();
Console.WriteLine ("Thank you for using this program for your scheduling needs.");
}
}
//This method when called will print a numbered list of courses refrenced by the created List
public void Print()
{
Console.WriteLine ();
Console.WriteLine ("Course Name.........Course Number.........Course Description........Course Hours");
Console.WriteLine ("********************************************************************************");
for (int i = 0; i < totalcourse; i++) {
int place = i + 1;
Console.WriteLine (place+".)"+school [i]);
}
Console.WriteLine ();
}
//This method will add an item to the end of the current list.
public void Add()
{
Console.WriteLine ();
Console.Write ("How many courses would you like to add at the end of your index?");
int numberAdded = int.Parse(Console.ReadLine ());
for (int i = 0; i < numberAdded; i++) {
Console.WriteLine ("Please use the following templet for your entries...");
Console.WriteLine ("Course Prefix, Course Name, Course Number, Course Hours, Course Description ");
school.Add (new Course (prefix = Console.ReadLine (), courseName = Console.ReadLine (),
courseNumber = Console.ReadLine (), courseHours = int.Parse (Console.ReadLine ()), descript = Console.ReadLine ()));
}
totalcourse = totalcourse + numberAdded;
Console.WriteLine ();
}
//This method will delete an Item from the list based on the position 0-x based on x-1, the output that is seen by the user. After each iteration it will
//also create a list so that further deletions can be managed approiatly.
public void Delete()
{
if (totalcourse < 1) {
Console.WriteLine ();
Console.WriteLine ("There is nothing to delete!");
Console.WriteLine ();
}else{
Console.WriteLine ();
Console.Write ("How many entries do you wish to remove?");
int removed = int.Parse (Console.ReadLine ());
for (int i = 0; i < removed; i++) {
Console.WriteLine ("Please type the index line number of the item you wish to remove.");
int delete = int.Parse (Console.ReadLine ());
school.RemoveAt (delete - 1);
totalcourse = totalcourse - 1;
Print ();
}
}
Console.WriteLine ();
}
//This method is called to create a new list of Courses to be created by the user.
public void New()
{
Console.WriteLine ();
if (howmany > 0) {
Clear ();
} else {
Console.Write ("How many courses do you want to create? ");
howmany = int.Parse (Console.ReadLine ());
Console.WriteLine ();
for (int i = 0; i < howmany; i++) {
Console.WriteLine ();
school.Add (new Course (prefix = Console.ReadLine (), courseName = Console.ReadLine (), courseNumber = Console.ReadLine (), courseHours = int.Parse (Console.ReadLine ()), descript = Console.ReadLine ()));
}
totalcourse = totalcourse + howmany;
Console.WriteLine ();
}
}
//If there is already a list in place this method will be called and you will be asked if you wish to delete and start new.
public void Clear()
{
Console.WriteLine ();
Console.Write ("You want to discard old work and start a new list? Enter True or False...:");
bool clean=bool.Parse(Console.ReadLine());
if (clean == true) {
school.Clear ();
totalcourse = 0;
howmany = 0;
New ();
} else
Console.WriteLine ("No changes will be made. Exiting to Main Menu...");
Console.WriteLine ();
}
/* public static void Myfour ()
{
Console.WriteLine ();
Console.WriteLine ("These are four pre loaded courses.");
Course c1 = new Course ("MISSILE", 84, 3, "The Course is for missiles", "CRN");
Console.WriteLine (c1);
Console.WriteLine ();
}*/
}
}
The first problem with your class is that the Course class contains a List<Course> school variable. A School is another logical entity and should be in another class. I think the Course class should be a class on it's own, without any static members. All the Console related functions and the school variable should be enclosed in a (maybe static, if that's a requirement) School class.
Your main function would then call
School.Menu();
School.Choice();
The way you called Course.Choice() which is a className.methoddName() is meant for accessing a static method. That means you will need to change your
public void Choice() { }
public void Menu() { }
to
public static void Choice() { }
public static void Menu() { }
However, like I said before, since Choice() and Menu() are now static, therefore everything that is called within these methods have to be static as well, such as Add(), Delete(), Print().
So what does it mean to be a static method? - You don't (and can't) instantiate them to access them. The other approach to this, is to simply create an instance of class Course using the new keyword:
Course cr = new Course();
//This works because Course and MainClass are under the same namespace
//Or else, you will need to do this:
OtherNamespace.Class x = new OtherNamespace.Class() ;
and now you can access all the non-static methods in Course class! Like this:
cr.Menu();
cr.Choice();
Create an instance would seem to be an easier approach to solve your problem, because all of your methods are instance. But you should really understand when is more appropriate to use which. You can read more about that here.
Even though you only asked about calling non-static. I really think you have a lot of improvement to do on Course class. You clump too many things inside the class. For example, you can create a new class just to store all the properties like cn, name, hours, etc. Here it will be a good idea to set them as static property, then you can simply access them anywhere using TheNewClass.hours.
Related
its my first time doing unit tests/integration tests and I have a question. So I started doing unit tests for my code, but I have a method, which is actually the logic of the whole application, where multiple methods are called, and user input is required. How can I test that method? Here is the method:
public async Task RunAsync()
{
var watch = System.Diagnostics.Stopwatch.StartNew();
var playAgain = 'y';
do
{
var attempts = 1;
var foundNumber = false;
while (attempts < 10 && foundNumber == false)
{
try
{
var inputNumber = int.Parse(GetInput());
if (inputNumber == _randomNumber)
{
foundNumber = true;
OnSuccesfulGuess(watch, attempts);
}
else if (attempts < 10)
{
OnWrongGuessWithinAttempts(inputNumber);
}
else
{
Console.WriteLine("Oops, maybe next time.");
}
}
catch (Exception ex)
{
Console.WriteLine("Please enter a number");
}
attempts++;
}
playAgain = PlayAgain(playAgain);
_randomNumber = await GetRandomNumber(1, 100);
Log.Information("User wants to play again");
}
while (playAgain == 'y' || playAgain == 'Y');
}
This is the method where i run in my Program class in order to start the application.
Your code is essentially untestable.
The method does too much work. It should be splitted into several smaller ones that can be tested separately.
You should get rid of static methods. Because you can't get them fake.
Getting data over the network (I see using WebSocket), as well as from the database or file system, should be brought out. You should pass ready-made data to this method.
Here is the modified code, broken down into small methods. Logging and events are removed from the code so as not to complicate the explanation.
public class App
{
private readonly Random _random = new Random();
private Task<int> GetRandomNumber(int min, int max)
{
return Task.FromResult(_random.Next(min, max));
}
internal int GetInput()
{
Console.WriteLine("Please guess a number between 1 and 100");
int value;
while (true)
{
string input = Console.ReadLine();
bool result = int.TryParse(input, out value);
if (!result)
Console.WriteLine("Not a number");
else if (value < 1 || value > 100)
Console.WriteLine("Must be between 1 and 100");
else
break;
}
return value;
}
internal bool PlayAgain()
{
Console.WriteLine("Do you want to play again?");
string input = Console.ReadLine();
return input == "Y" || input == "y";
}
internal void Guessing(int randomNumber)
{
int attempts = 1;
while (attempts < 10)
{
var inputNumber = GetInput();
// logging
if (inputNumber == randomNumber)
{
// OnSuccesfulGuess
return;
}
else
{
// OnWrongGuessWithinAttempts
}
attempts++;
}
Console.WriteLine("Oops, maybe next time.");
// logging
}
public async Task RunAsync()
{
do
{
int randomNumber = await GetRandomNumber(1, 100);
Guessing(randomNumber);
}
while (PlayAgain());
}
}
Now we have the ability to test individual methods.
I use MSTest.
[DataTestMethod]
[DataRow("Y")]
[DataRow("y")]
public void PlayAgain_InputY_ReturnsTrue(string value)
{
using (var reader = new StringReader(value))
{
Console.SetIn(reader);
var app = new App();
bool result = app.PlayAgain();
Assert.IsTrue(result);
}
}
[DataTestMethod]
[DataRow("N")]
[DataRow("boo")]
[DataRow("")]
public void PlayAgain_InputNotY_ReturnsFalse(string value)
{
using (var reader = new StringReader(value))
{
Console.SetIn(reader);
var app = new App();
bool result = app.PlayAgain();
Assert.IsFalse(result);
}
}
We do the same with the other methods.
Here are the tests for the GetInput method.
Since there is a loop inside that runs indefinitely when incorrect values are entered, we must interrupt it by entering the correct value. This is done by passing two values via a line feed: "0\n50". Entering an incorrect value is a test of the output string, then interrupting the loop with the correct value.
[DataTestMethod]
[DataRow("1")]
[DataRow("50")]
[DataRow("100")]
public void GetInput_InputCorrectString_ReturnsNumber(string value)
{
using (var reader = new StringReader(value))
{
Console.SetIn(reader);
var app = new App();
int actual = app.GetInput();
int expected = int.Parse(value);
Assert.AreEqual(expected, actual);
}
}
[DataTestMethod]
[DataRow("0\n50")]
[DataRow("101\n50")]
public void GetInput_InputSmallerOrGreaterValue_WritesMessage(string value)
{
using (var reader = new StringReader(value))
using (var writer = new StringWriter())
{
Console.SetIn(reader);
Console.SetOut(writer);
var app = new App();
_ = app.GetInput();
string actualMessage = writer.ToString();
string expectedMessage = "Must be between 1 and 100";
Assert.IsTrue(actualMessage.Contains(expectedMessage));
}
}
[DataTestMethod]
[DataRow("x\n50")]
[DataRow("qwerty\n50")]
public void GetInput_InputNotNumber_WritesMessage(string value)
{
using (var reader = new StringReader(value))
using (var writer = new StringWriter())
{
Console.SetIn(reader);
Console.SetOut(writer);
var app = new App();
_ = app.GetInput();
string actualMessage = writer.ToString();
string expectedMessage = "Not a number";
Assert.IsTrue(actualMessage.Contains(expectedMessage));
}
}
Normally the unit testing methods are made regarding the different results that may return. You can create an interface to handle this method and communicate giving values depending of the output expected (Mocking). Check this post maybe would help!:
How do I apply unit testing to C# function which requires user input dynamically?
Hoping someone can help. I'm still learning a lot each day as beginner. But have a few issues with the below.
The use of goto is a no-no from the research I have seen but I can't figure out an alternative loop to add while maybe? Or do?
When I enter text that I know will not return a result e.g. dsfgfhg and press enter I receive "Resource Not found " three times in the results. I assume this is because out of the list there are three entries and none match. How do I get one result instead of three when a resource is not found?
If I press enter twice in the console window without entering any text it returns everything in the list. Again I can't see a way to stop this. I guess I need to change the code to be explicit in some way?
Thanks again for your help.
using System;
using System.Collections.Generic;
class JunkList
{
public string Resource { get; set; }
public string Junk { get; set; }
public int Amount { get; set; }
public JunkList(string r, string j, int a)
{
this.Resource = r;
this.Junk = j;
this.Amount = a;
}
}
class Program
{
static void Main(string[] args) // this is a method called "Main" . It is called when the program starts.
{
start:
string searchName;
List<JunkList> infoList = new List<JunkList>();
infoList.Add(new JunkList("Screw", "Type Writer", 2));
infoList.Add(new JunkList("Screw", "Clip Board", 1));
infoList.Add(new JunkList("Screw", "Toy Car", 3));
Console.WriteLine("Which resource do you want to search for?? \n");
searchName = Console.ReadLine();
for (int i = 0; i < infoList.Count; i++)
{
if (infoList[i].Resource.ToLowerInvariant().Contains(searchName.ToLowerInvariant()))
{
Console.WriteLine("Resource : " + infoList[i].Resource + "\n");
Console.WriteLine("Junk : " + infoList[i].Junk + "\n");
Console.WriteLine("Resource Amount : " + infoList[i].Amount + "\n");
}
else {
Console.WriteLine("Resource Not found <Press Enter to perform a new search>");
}
}
// wait for user to press a key. Then make an empty space and start over.
Console.ReadKey();
Console.WriteLine();
goto start; // go to start and run again
}
}
I recommend you to use 'single responsibility principle'. In your case that means that you should split your Main method into smaller methods. These methods do one simple action, i.e. responsibility.
Well, it will help:
You are right goto quite often is a bad practice (but not always). Put your code into while(true) and it would do the same but more clear. However, to close your application correctly receiving some char or key to exit would be better, e.g.
bool _runApplication = true;
while (_runApplication)
{
// code between "start:" and "goto start;"
if (Console.Read() == 'x')
{
_runApplication = false;
}
}
To solve this multiple Resource Not found output you can separate searching by name and printing searching results, e.g.
string searchName = Console.ReadLine();
List<JunkList> searchResult = GetJunkListsBySearchName(infoList, searchName);
if (searchResult.Count != 0)
{
foreach (var junkList in searchResult)
{
Console.WriteLine("Resource : " + junkList.Resource + "\n");
Console.WriteLine("Junk : " + junkList.Junk + "\n");
Console.WriteLine("Resource Amount : " + junkList.Amount + "\n");
}
}
else
{
Console.WriteLine("Resource Not found <Press Enter to perform a new search>");
}
where new method is:
private static List<JunkList> GetJunkListsBySearchName(List<JunkList> infoList, string searchName)
{
List<JunkList> output = new List<JunkList>();
foreach (var junkList in infoList)
{
if (junkList.Resource.ToLowerInvariant().Contains(searchName.ToLowerInvariant()))
{
output.Add(junkList);
}
}
return output;
}
It is because of searchName is equal to en empty string. Add a simple if to solve it.
if (searchName.Length > 0 &&
junkList.Resource.ToLowerInvariant().Contains(searchName.ToLowerInvariant()))
{
output.Add(junkList);
}
Applying all these points you will get code like this (only Program class modified):
class Program
{
static void Main(string[] args)
{
bool _runApplication = true;
while (_runApplication)
{
List<JunkList> infoList = CreateJunkList();
Console.WriteLine("Which resource do you want to search for?? \n");
string searchName = Console.ReadLine();
List<JunkList> searchResult = GetJunkListsBySearchName(infoList, searchName);
if (searchResult.Count != 0)
{
PrintJunkLists(searchResult);
}
else
{
Console.WriteLine("Resource Not found <Press Enter to perform a new search>");
}
Console.WriteLine();
if (Console.Read() == 'x')
{
_runApplication = false;
}
}
}
private static List<JunkList> CreateJunkList()
{
List<JunkList> infoList = new List<JunkList>();
infoList.Add(new JunkList("Screw", "Type Writer", 2));
infoList.Add(new JunkList("Screw", "Clip Board", 1));
infoList.Add(new JunkList("Screw", "Toy Car", 3));
return infoList;
}
private static void PrintJunkLists(List<JunkList> junkLists)
{
foreach (var junkList in junkLists)
{
PrintJunkList(junkList);
}
}
private static void PrintJunkList(JunkList junkList)
{
Console.WriteLine("Resource : " + junkList.Resource + "\n");
Console.WriteLine("Junk : " + junkList.Junk + "\n");
Console.WriteLine("Resource Amount : " + junkList.Amount + "\n");
}
private static List<JunkList> GetJunkListsBySearchName(List<JunkList> infoList, string searchName)
{
List<JunkList> output = new List<JunkList>();
foreach (var junkList in infoList)
{
if (searchName.Length > 0 &&
junkList.Resource.ToLowerInvariant().Contains(searchName.ToLowerInvariant()))
{
output.Add(junkList);
}
}
return output;
}
}
I hope it helped)
I have my code for linked list here I have attached below, In this all methods are declared in a single class, now I am refactoring my code so I am moving my methods to separate class, after moving my data to separate class my data is not getting passed which so my data is not getting displayed, I think my way of passing the data through the variables to other classes is where the problem occurs, I don't know how to rectify this..here I have attached my code..
here is my code:
//My node class:
public class Node
{
public int info;
public Node link;
public Node(int i)
{
info = i;
link = null;
}
}
// My class to print the data:
public class Display
{
public void DispalyList()//list to display the items
{
Node p;
SingleLinkedList lst = new SingleLinkedList();
if (lst.start == null) // I have a doubt whether calling the start variable using that object is not correct., If data is being passed here I can proceed further
{
Console.WriteLine("List is empty");
return;
}
Console.Write("list is: ");
p = lst.start; //The way of calling the start object is wrong I guess
while (p != null) // p value is null here
{
Console.Write(p.info + " ");
p = p.link;
}
Console.WriteLine();
}
}
// My Single Linked list class://for time being i have two methods in this class
public class SingleLinkedList
{
public Node start;
public SingleLinkedList()//constructor
{
start = null;
}
public void CreateList() //Method where I am inserting the data
{
int i, n, data;//variable declaration
Console.Write("enter the number of nodes");
n = Convert.ToInt32(Console.ReadLine());
if (n == 0)
return;
for (i = 1; i <= n; i++)
{
Console.WriteLine("enter the element to be inserted");
data = Convert.ToInt32(Console.ReadLine());
InsertAtEnd(data);
}
}
public void InsertAtEnd(int data)//Method to insert the data into the list
{
Node p;
Node temp = new Node(data);
if (start == null)
{
start = temp;
return;
}
p = start;
while (p.link != null)
p = p.link;
p.link = temp;
}
}
}
//Main class using switch case:// I am just calling the display method alone for time being
public class Program
{
static void Main(string[] args)//Main program calling the methods
{
int choice;
SingleLinkedList list = new SingleLinkedList();
list.CreateList();// calling the createlist method
while (true)
{
Console.WriteLine("1.Display List");
Console.WriteLine("Enter your choice");
choice = Convert.ToInt32(Console.ReadLine());
if (choice == 13) //I have 13 cases for time being I have shown only one below
break;
switch(choice)//Switch case calling the methods
{
case 1:
Display dis = new Display();
dis.DispalyList();//calling display method which prints the data
break;
default://default case
Console.WriteLine("Wrong Choice");
}
}
}
}
Here is my above code, in which the value of the start in the[ DisplayList()] method is assigning null.If the data is being passed to it in this method i can follow the same for my other classes too. I don't know how to assign the data here..
I would suggest using ReadAllLines() instead, which will return a collection of strings, one per line in your input:
public class ReadingTextFile: IReadingTextFile {
public IEnumerable<string> content() { // change the return type
string path = # "C:\Users\s\Desktop\Datas\Data Input.txt";
var data = File.ReadAllLines(path); // and this
return data;
}
}
Then you can either just use the file.content() if all you need is a list:
IReadingTextFile file = new ReadingTextFile();
LinkedList < string > data = new LinkedList < string > ();
IEnumerable<string> inp = file.content(); // this is a collection of strings, one per line of your input
// ...
Or if you still want a linked list, you can just use the LinkedList constructor that takes a collection:
public class Readingtolist {
public void Input() {
IReadingTextFile file = new ReadingTextFile();
Stopwatch sw = new Stopwatch();
sw.Start();
IEnumerable<string> inp = file.content(); // the reading the file is probably what you really want to time.
sw.Stop();
var data = new LinkedList<string>(inp); // note the use of (inp) here
Console.Write("\n time Taken For Read Data: {0} ms",
sw.Elapsed.TotalMilliseconds);
Console.WriteLine("\n The items are{0}", inp);
}
}
I have a short question about timers. In my code I want to create a crop farming game, with a timer that shows if the plant is finished.
Why does this:
public static string currentPlant;
public static Timer growTimer;
public static void InitGrowTimer( int time, string name )
{
growTimer = new Timer();
growTimer.Tick += new EventHandler(growTimer_Finished);
growTimer.Interval = time;
currentPlant = name;
}
public static void plantCrop(string crop)
{
if (plantActive == false)
{
if (plants.Contains(crop.ToLower()))
{
// growTimer.Interval = <plant>Time;
// proceed plants
switch (crop.ToLower())
{
case "wheat":
InitGrowTimer(wheatTime, wheatName);
growTimer.Start();
break;
default:
MessageBox.Show("FATAL ERROR\nThe plant is contained in the definition list but not in the plant menu!", "Civilisation", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
}
else
{
MessageBox.Show("This plant is not available!", "Civilisation", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("There is already a plant in progress! Current plant: {0}", currentPlant);
}
}
private static void growTimer_Finished (object sender, EventArgs e)
{
growTimer.Stop();
MessageBox.Show("Your " + currentPlant + " is finished!", "Civilisation", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
not start the timer, or just doesnt show the messagebox at the end. What am I doing wrong at creating the timer or creating the tick event?
EDIT: This is my main method:
static void Main(string[] args)
{
InitializeLists();
// game begin
Farm.plantCrop("wheat");
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("Please enter your desired name: ");
QC.resetColors();
name = Console.ReadLine();
Console.WriteLine(/*Introduction*/"Welcome to the world of Civilisation. In this world it is your choice what\n" +
"you are up to. You can be a farmer, miner or fighter, whatever you want, the\n" +
"world is yours to explore! Have fun!"
);
Console.ReadKey();
Console.Clear();
while (true) // run game
{
// menu
Console.Write(" What do you want to do?\n" +
"Farm Mine Explore Go to the city\n"
);
input = Console.ReadLine();
if (menuContent.Contains(input.ToLower()))
{
if (input.ToLower() == menuContent.ElementAt(0))
{
// farm
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("-- Farm --\nSelect a crop to plant:");
Console.ForegroundColor = ConsoleColor.DarkGreen;
int icount = 0;
for ( int i = 0; i < Farm.plants.Count; i++)
{
if (icount < 3)
{
Console.Write(Farm.plants.ElementAt(i));
Console.Write("\t\t");
icount++;
}
else
{
Console.Write("\n");
icount = 0;
Console.Write(Farm.plants.ElementAt(i));
Console.Write("\t\t");
icount++;
}
}
Console.WriteLine();
QC.resetColors();
string crop = Console.ReadLine();
Farm.plantCrop(crop);
}
if (input.ToLower() == menuContent.ElementAt(1))
{
// miner
}
if (input.ToLower() == menuContent.ElementAt(2))
{
// fight
}
}
}
}
The System.Windows.Forms.Timer timer is made for a Windows Form app with a single UI thread.
You need to use the System.Threading.Timer timer instead for your console application.
It's creation and the parameters of the callback are a little different:
public static void InitGrowTimer(int time, string name)
{
growTimer = new System.Threading.Timer(GrowTimer_Finished, null, time, Timeout.Infinite);
currentPlant = name;
}
private static void GrowTimer_Finished(object sender)
{
MessageBox.Show("Your " + currentPlant + " is finished!", "Civilisation", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
You do not need any Startmethod, it will be started automatically on creation.
You don't need a Stop either; it will run only once because of the Timeout.Infinite parameter.
You can replace null with the object you want the callback to receive, if needed (i.e. what would have been in EventArgs).
Little side note: I've renamed your callback method in PascalCase. Per convention, the methods in C# should always start with a capital letter.
Because you, as you tell yourself, do not start the timer.
growTimer = new Timer();
growTimer.Tick += new EventHandler(growTimer_Finished);
growTimer.Interval = time;
growTimer.Start();
My error:
Field 'StockManagement.LargeItems1.largeS' is never assigned to, and will always have its default value null
My code:
namespace StockManagement
{
class LargeItems1
{
private Stack<string> largeS;
public LargeItems1()
{
Stack<string> largeS = new Stack<string>();
}
public void LargeItemsAdd()
{
string usersInput2, tempValue;
int tempValueI = 0;
bool attempt = false;//, whichOne = false;
Console.WriteLine("Would you like to remove or add an item to the storage area \n Reply add OR remove");
string usersInput = Console.ReadLine();
usersInput = usersInput.ToLower();
if (usersInput.Contains("remove"))
{
LargeItemsRemove(largeS);
return;
}
else if (usersInput.Contains("add"))
{
Console.WriteLine("Please input (numerically) how many IDs you'd like to add");
tempValue = Console.ReadLine();
attempt = int.TryParse(tempValue, out tempValueI);
while (!attempt)
{
Console.WriteLine("Please input (numerically) how many IDs you'd like to add, you did not input a numeric value last time");
tempValue = Console.ReadLine();
attempt = int.TryParse(tempValue, out tempValueI);
}
for (int i = 0; i < tempValueI; i++)
{
Console.WriteLine("Please input the ID's (one at a time) of the item you would like to add");
usersInput2 = Console.ReadLine();
if (largeS.Contains(usersInput2))
{
Console.WriteLine("That ID has already been stored");
}
else
{
largeS.Push(usersInput2);
}
}
foreach (var item in largeS)
{
Console.WriteLine("Current (large) item ID's: " + item);
}
}
}
public void LargeItemsRemove(Stack<string> largeS)
{
if (largeS.Contains(null))
{
Console.WriteLine("No IDs stored");
}
else
{
string popped = largeS.Pop();
foreach (var item in largeS)
{
Console.WriteLine("Pop: " + item);
}
Console.WriteLine("Removed ID = " + popped);
}
}
}
}
I don't understand how to assign my values to the instances. I'd appreciate any help that can be provided!
Change your constructor to initialize the field instead of the local variable:
public LargeItems1()
{
this.largeS = new Stack<string>();
}
You have to initialize your field largeS, using the this keyword, in this way:
this.largeS = new Stack<string>();
The this keyword is used to refer to the current instance of the class. If you use instead:
Stack<string> largeS = new Stack<string>();
you're just initializing a new local variable that has nothing to do with your private field.
Check the MSDN documentation about this keyword.