I need to find a node with input from a customer in the linked list but I have an error CS1503. How can I solve a problem?
In this code, I create the LinkList name "customerList" to collect string data such as name, contact number, and payment from the user. After that, I need to find the contact number which input from the user to show data in the node and delete it. In code show that input in "searchCustomerDetail" cannot convert 'string' to ....
Error Message: Argument 1: cannot convert from 'string' to 'IFN564.Customer' [IFN564]csharp(CS1503)
public class Customer {
public string Name { get; set; }
public string Phone { get; set; }
public string Payment { get; set; }
public int[] Screening { get; set; }
public static LinkedList<Customer> customerList = new LinkedList<Customer>();
public static string input;
public static void addCustomerDetail() {
Console.WriteLine("Please enter your information detail");
Console.WriteLine("");
Console.Write("Full Name: ");
string inputName = Console.ReadLine();
Console.Write("Contact Number: ");
string inputPhone = Console.ReadLine();
Console.Write("Payment Method: ");
string inputPayment = Console.ReadLine();
Console.Clear();
Console.WriteLine("");
Console.WriteLine("Please check your information detail!!");
Console.WriteLine("");
Console.WriteLine($"Full Name: {inputName}");
Console.WriteLine($"Contact Number: {inputPhone}");
Console.WriteLine($"Payment Method: {inputPayment}");
Console.WriteLine("");
Console.WriteLine("Please 1 to confirm or 0 to cancel");
int input = Convert.ToInt32(Console.ReadLine());
switch (input) {
case 1:
insert(inputName, inputPhone, inputPayment);
break;
case 2:
Program.Main();
break;
}
}
public static void insert(string name, string phone, string payment) {
Console.WriteLine("");
Console.WriteLine("Please 1 to confirm buy ticket or 0 to cancel");
int input = Convert.ToInt32(Console.ReadLine());
Customer customerDetail = new Customer() {
Name = name,
Phone = phone,
Payment = payment,
};
switch (input) {
case 0: Program.Main(); break;
case 1:
customerList.AddLast(customerDetail);
Program.Main();
break;
}
}
public static void searchCunstomerDetail() {
Console.WriteLine("Please enter contact number!!");
Console.WriteLine("");
Console.Write("Contact number: ");
input = Console.ReadLine();
LinkedListNode<Customer> node = customerList.Find(input);
Console.WriteLine(node);
}
}
I try to use LinkListNode to find but It show error with input CS1503
you need to use LINQ where
var node = customerList.Where(c=>c.Phone == input).First();
The error is with this statement:
LinkedListNode<Customer> node = customerList.Find(input);
customerList.Find searches the customerList for an element (in this case, a Customer) that equals the argument provided to Find (in this case, the var, input). input is a string, not Customer, so it can't be used in Find here.
What you seemingly intend to do here is to find the Customer in customerList that has a Customer.Phone that equals the input string. To do so, you can use LINQ, as others have suggested:
LinkedListNode<Customer> node = customerList.FirstOrDefault(c => c.Phone == input);
The above expression will find the first element in the list that returns true for the provided function (predicate), and will return null if none match.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am making a console application and I have a "Menu" where the user can enter information to create a new Person object. The following is inside a method.
Write("Please enter the first name: ", false);
string fName = Console.ReadLine().ToUpper();
Write("Please enter the middle initial: ", false);
string mInitial = Console.ReadLine().ToUpper();
Write("Please enter the last name: ", false);
string lName = Console.ReadLine().ToUpper();
like so. I want the user to be able to exit the method at anytime if they decide they don't want to be making a new person. So I'd like to make a new method called "CheckExit" and if they type "EXIT" it will leave the "CreatePerson" method. So I want the "CheckExit" to return a return. Otherwise I have to add an "if" statement after every input and that gets clutter-y.
Is this possible? Does return have a return type? What would be the proper way to do this?
return is not a type that you can return, it's a keyword for returning a result. So unfortunately what you are trying to do is not possible.
However, you can make your code much more readable and extendable by using an array of queries and getting the results for each inside of a loop. This has the bonus effect of being able to add more queries with ease.
// you can put these queries somewhere outside the function
string[] queries = {"Please enter the first name: ", ...}
var results = new List<string>();
foreach (string query in queries) {
Write(query, false);
var result = Console.ReadLine().ToUpper();
if (result.Equals("EXIT") {
return;
}
results.Add(result);
}
// handle your inputs from the results list here ...
You could create a method to read from console to automate this process, something like
internal class StopCreatingPersonException : Exception
{}
public static string ReadFromConsole(string prompt)
{
Write(prompt, false);
var v = Console.ReadLine().ToUpper();
if (v == "EXIT") { throw new StopCreatingPerson (); }
return v;
}
Then your code would look like:
try {
string fName = ReadFromConsole("Please enter the first name: ");
....
}
catch (StopCreatingPersonException)
{ }
Return statements are used to return a value from a method that has a return type. When you write a method with void as the return type, you can use the return; to exit the method.
e.g, following method uses a string as the return type,
public string ReturnString() { return "thisString"; }
If you are writing a method that creates the object and returns it to the calling method, then the return type would be the Person (unless you intend do something else). If you check the user input and decide not to create a Person, you can use return null;.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Initial { get; set; }
}
public static Person CreatePerson()
{
Person person = new Person();
Console.Write("Please enter the first name: ", false);
string fName = Console.ReadLine().ToUpper();
if (string.IsNullOrEmpty(fName) || fName.ToLower().Equals("exit"))
return null;
person.FirstName = fName;
Console.Write("Please enter the middle initial: ", false);
string mInitial = Console.ReadLine().ToUpper();
if (string.IsNullOrEmpty(mInitial) || mInitial.ToLower().Equals("exit"))
return null;
person.Initial = mInitial;
Console.Write("Please enter the last name: ", false);
string lName = Console.ReadLine().ToUpper();
if (string.IsNullOrEmpty(lName) || lName.ToLower().Equals("exit"))
return null;
person.LastName = lName;
return person;
}
And you can use this method in the Main,
public static void Main(string[] args)
{
Person person = CreatePerson();
if (person == null) {
Console.WriteLine("User Exited.");
}
else
{
// Do Something with person.
}
}
The only way is to use return if you want to terminate method. But you can shorten your code some thing like this:
static void Main(string[] args)
{
createPerson();
Console.WriteLine("Some display goes here...");
}
static void createPerson()
{
Console.WriteLine("Please enter the first name: ");
string fName = getInput();
if (isExit(fName))
{
return;
}
Console.WriteLine("Please enter the middle initial: ");
string mInitial = getInput();
if (isExit(mInitial))
{
return;
}
Console.WriteLine("Please enter the last name: ");
string lName = getInput();
if (isExit(lName))
{
return;
}
}
static string getInput()
{
return Console.ReadLine().ToUpper();
}
static bool isExit(string value)
{
if (value == "EXIT")
{
Console.WriteLine("Create person has been canceled by the user.");
return true;
}
return false;
}
I have a library class that has a Serve() method. What it does is dequeue a person from a queue and Pop a book from a stack. A Book is associated to a Borrower when it is borrowed, that way the method ReturnBook() can accept a string value that corresponds to the name of the person who borrowed the book.
How can I create an association between the Book and the Borrower? It's my first time encountering associations in C#. Here is a sample input and output
INPUT
Lineup("Joker")
Add("Shelter", "Yung Jun", "9781250075611")
Add("The Paper Menagerie and Other Stories", "Liu, Ken", "9781481442541")
Serve()
Joker lined up.
Added Shelter (Yung Jun) to the stack.
Added The Paper Menagerie and Other Stories (Liu, Ken) to the stack.
Joker borrowed Shelter (Yung Jun)
One way to do this is to create a property of one item that is of the type of the other item. For example, a Borrower may have a Book property. Then, when the borrower borrows a book, you just set the value of the Book property to the book they just borrowed.
Following is an illustrative example of how this might work:
To start with, you should create some classes to represent the objects. Here's an example:
class Reader
{
public string Name { get; set; }
public Book BorrowedBook { get; set; }
}
class Book
{
public string Title { get; set; }
public string Author { get; set; }
public string ISBN { get; set; }
}
And it looks like you have a Queue of Readers (called borrowers) and a Stack of Books. I also created a Queue of Readers called returners, which will represent the people who want to return a book:
class Program
{
private static Queue<Reader> borrowers = new Queue<Reader>();
private static Queue<Reader> returners = new Queue<Reader>();
private static Stack<Book> books = new Stack<Book>();
Now, it looks like you have some helper methods that will add a reader to the queue or a book to the stack. Since I can see that these may need to be used to add new items OR existing items (like when a reader returns a book, the existing book will get added back to the library), I create two versions of them - one with no arguments (which will then get the details of the object from the user), and one with an argument (which will add that object to the queue or stack):
private static void Lineup()
{
var newReader = new Reader();
Console.Write("Enter the name of the new reader: ");
newReader.Name = Console.ReadLine();
// Now that we have a reader object, call the
// other version of this method to add it
Lineup(newReader);
}
private static void Lineup(Reader borrower)
{
borrowers.Enqueue(borrower);
Console.WriteLine($"{borrower.Name} lined up to borrow a book.");
}
private static void Add()
{
var newBook = new Book();
Console.Write("Enter the book title: ");
newBook.Title = Console.ReadLine();
Console.Write("Enter the book author: ");
newBook.Author = Console.ReadLine();
Console.Write("Enter the book ISBN: ");
newBook.ISBN = Console.ReadLine();
// Now that we have a book object, call the
// other version of this method to add it
Add(newBook);
}
private static void Add(Book book)
{
books.Push(book);
Console.WriteLine($"Added '{book.Title}' to the library.");
}
Finally, we need some methods to service our borrowers (Dequeue a borrower and Pop a book, then give the book to the borrower) and our returners (Push the book back to the library, and, if the person wants to borrow another one, Enqueue them back in the borrowers line):
private static void ServiceBorrower()
{
if (borrowers.Count == 0)
{
Console.WriteLine($"There are no more borrowers waiting in line.");
}
else if (books.Count == 0)
{
Console.WriteLine($"There are no more books to loan.");
if (returners.Count > 0)
{
Console.WriteLine(" - Hint: There are people waiting to return books.");
}
}
else
{
var borrower = borrowers.Dequeue();
var book = books.Pop();
borrower.BorrowedBook = book;
Console.WriteLine($"{borrower.Name} borrowed {book.Title}");
returners.Enqueue(borrower);
}
}
private static void ServiceReturner()
{
if (returners.Count == 0)
{
Console.WriteLine($"There are no more returners waiting in line.");
}
else
{
var returner = returners.Dequeue();
var book = returner.BorrowedBook;
returner.BorrowedBook = null;
Add(book);
Console.WriteLine($"{returner.Name} has returned {book.Title}.");
Console.Write("Do they want to borrow another one (Y/N)?: ");
var input = Console.ReadKey();
Console.WriteLine();
if (input.Key == ConsoleKey.Y)
{
Lineup(returner);
}
}
}
Now, we just need to give our user some options as to what they want the program to do, and continue looping on their input until they decide to quit:
static void Main()
{
bool exit = false;
Console.WriteLine("Please choose an option:");
Console.WriteLine("1. Enter a new reader");
Console.WriteLine("2. Enter a new book");
Console.WriteLine("3. Service the next borrower");
Console.WriteLine("4. Service the next returner");
Console.WriteLine("5. Exit the program");
while (!exit)
{
Console.Write("\nEnter choice (1-5): ");
int input;
while (!int.TryParse(Console.ReadLine(), out input) || input < 1 || input > 5)
{
Console.Write("Invalid input. Enter a number from 1-5: ");
}
switch(input)
{
case 1:
Lineup();
break;
case 2:
Add();
break;
case 3:
ServiceBorrower();
break;
case 4:
ServiceReturner();
break;
case 5:
exit = true;
break;
}
}
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
Output:
I have an app which allows you to add student and lecturer details, and search them, and display them, etc. This is for a college assignment, and I have to test five of the methods I have created. Firstly, I'm not sure how to test a method involving strings, as all the testing methods I have seen involved a bank account app, and testing withdrawal and deposit methods seems easy as you just have to add and subtract numbers. I'm not sure at all how to test my, (for example) AddLecturer() method. I've tried to get one of the methods to throw an exception if a Status class that I created is entered correctly, but the program seems to still consider it an unhandled exception. How do I fix the exception so it's handled correctly, and how do I test these other methods?
Here's the main entry point to the app with all the methods.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DBSManagement
{
public class College: Staff
{
public static List<Student> students = new List<Student>();
public static List<Lecturer> lecturers = new List<Lecturer>();
public static void Main()
{
int choice;
bool seeAgain = true;
do
{
Console.WriteLine("Press");
Console.WriteLine("1: To add a student");
Console.WriteLine("2: To add a lecturer");
Console.WriteLine("3: To search for a lecturer or student");
Console.WriteLine("4: To show the details of all enrolled students");
Console.WriteLine("5: To show the names of all lecturers");
Console.WriteLine("6: To show payroll details for a lecturer");
Console.WriteLine("7: To quit");
int.TryParse(Console.ReadLine(), out choice);
switch (choice)
{
case 1:
AddStudent();
break;
case 2:
AddLecturer();
break;
case 3:
SearchPerson();
break;
case 4:
ShowStudents();
break;
case 5:
ShowLecturers();
break;
case 6:
ShowPayrollDetails();
break;
case 7:
seeAgain = false;
break;
default:
Console.WriteLine("Invalid option selected");
break;
}
} while (seeAgain);
}
public static void AddStudent()
{
Student student = new Student();
Console.WriteLine("Enter student name:");
if (Console.ReadLine() != null)
{
student.Name = Console.ReadLine();
}
else throw new ArgumentNullException("Please enter a name");
Console.WriteLine("Enter student address:");
student.Address = Console.ReadLine();
Console.WriteLine("Enter student phone number:");
student.Phone = Console.ReadLine();
Console.WriteLine("Enter student email:");
student.Email = Console.ReadLine();
Console.WriteLine("Enter student PPSN:");
student.PPSN = Console.ReadLine();
Console.WriteLine("Enter student status (postgrad or undergrad):");
EnterStat:
string stat = Console.ReadLine().ToLower();
if (stat == "postgrad" || stat == "undergrad")
{
student.Status = (Status)Enum.Parse(typeof(Status), stat);
}
else
{
Console.WriteLine("Please enter either postgrad or undergrad:");
goto EnterStat;
}
Console.WriteLine("Enter student ID:");
int inStudentID;
int.TryParse(Console.ReadLine(), out inStudentID);
student.StudentID = inStudentID;
students.Add(student);
}
public static void AddLecturer()
{
Lecturer lecturer = new Lecturer();
Console.WriteLine("Enter lecturer name:");
lecturer.Name = Console.ReadLine();
Console.WriteLine("Enter lecturer address:");
lecturer.Address = Console.ReadLine();
Console.WriteLine("Enter lecturer phone number:");
lecturer.Phone = Console.ReadLine();
Console.WriteLine("Enter lecturer email:");
lecturer.Email = Console.ReadLine();
Console.WriteLine("Enter lecturer PPSN:");
lecturer.PPSN = Console.ReadLine();
Console.WriteLine("Enter lecturer ID:");
lecturer.ID = Console.ReadLine();
Console.WriteLine("Enter salary:");
lecturer.Salary = decimal.Parse(Console.ReadLine());
Console.WriteLine("Enter subject taught:");
lecturer.SubjectTaught = Console.ReadLine().ToLower();
lecturers.Add(lecturer);
}
public static void SearchPerson()
{
int searchChoice = 0;
int studentSearch = 0;
int lecturerSearch = 0;
Console.WriteLine("Press:");
Console.WriteLine("1 to search for a student");
Console.WriteLine("2 to search for a lecturer");
int.TryParse(Console.ReadLine(), out searchChoice);
switch (searchChoice)
{
//search students
case 1:
Console.WriteLine("Press:");
Console.WriteLine("1 to search by name");
Console.WriteLine("2 to search by student number");
int.TryParse(Console.ReadLine(), out studentSearch);
switch (studentSearch)
{
case 1:
Console.WriteLine("Enter student name:");
string studentNameSearch = Console.ReadLine();
bool sFound = false;
foreach (Student student in students)
{
if (student.Name.Contains(studentNameSearch))
{
Console.WriteLine(student.ToString());
sFound = true;
break;
}
}
if (sFound == false)
{
Console.WriteLine("Student name not found");
}
break;
case 2:
int studentIDSearch;
bool IDFound = false;
Console.WriteLine("Enter student number:");
int.TryParse(Console.ReadLine(), out studentIDSearch);
foreach (Student student in students)
{
if (student.StudentID.Equals(studentIDSearch))
{
Console.WriteLine(student.ToString());
IDFound = true;
break;
}
}
if (IDFound == false)
{
Console.WriteLine("Student name not found");
}
break;
default:
Console.WriteLine("Invalid option selected");
break;
}
break;
//search lecturers
case 2:
Console.WriteLine("Press:");
Console.WriteLine("1 to search by name");
Console.WriteLine("2 to search by course taught");
int.TryParse(Console.ReadLine(), out lecturerSearch);
switch (lecturerSearch)
{
case 1:
Console.WriteLine("Enter lecturer name:");
string lecturerNameSearch = Console.ReadLine();
bool lFound = false;
foreach (Lecturer lecturer in lecturers)
{
if (lecturer.Name.Contains(lecturerNameSearch))
{
Console.WriteLine(lecturer.ToString());
lFound = true;
break;
}
}
if (lFound == false)
{
Console.WriteLine("Lecturer name not found");
}
break;
case 2:
Console.WriteLine("Enter course taught:");
string lecturerSubjectSearch = Console.ReadLine().ToLower();
bool subjectFound = false;
foreach (Lecturer lecturer in lecturers)
{
if (lecturer.SubjectTaught.Contains(lecturerSubjectSearch))
{
Console.WriteLine(lecturer.ToString());
subjectFound = true;
break;
}
}
if (subjectFound == false)
{
Console.WriteLine("Subject not found");
}
break;
default:
Console.WriteLine("Invalid option selected");
break;
}
break;
default:
Console.WriteLine("Invalid option selected");
break;
}
}
public static void ShowStudents()
{
//sort list by name
List<Student> SortedStudents = students.OrderBy(o => o.Name).ToList();
foreach (Student student in SortedStudents)
{
Console.WriteLine(student);
}
}
public static void ShowLecturers()
{
//sort list by name
List<Lecturer> SortedLecturers = lecturers.OrderBy(o => o.Name).ToList();
foreach (Lecturer lecturer in SortedLecturers)
{
Console.WriteLine(lecturer.Name);
}
}
public static void ShowPayrollDetails()
{
Console.WriteLine("Enter lecturer name:");
string lecturerNameSearch = Console.ReadLine();
for (int i = 0; i < lecturers.Count; i++)
{
if (lecturers[i].Name == lecturerNameSearch)
{
Console.WriteLine(lecturers[i].PayrollDetails());
}
else
{
Console.WriteLine("Lecturer name not found");
}
}
}
}
}
Here are the test methods I have created so far.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using DBSManagement;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DBSManagement.Tests
{
[TestClass()]
public class CollegeTests
{
[TestMethod()]
[ExpectedException(typeof(ArgumentException))]
public void AddStudentTest()
{
//arrange
string s = "student";
Status status = (Status)Enum.Parse(typeof(Status), s);
//act
Student student1 = new Student("Name", "123 Fake St", "0851234567", "fake#address.com", "7895459R", status, 12345678);
//assert
//handled by exception
}
[TestMethod()]
public void AddLecturerTest()
{
Assert.Fail();
}
[TestMethod()]
public void SearchPersonTest()
{
Assert.Fail();
}
[TestMethod()]
public void ShowStudentsTest()
{
Assert.Fail();
}
[TestMethod()]
public void ShowLecturersTest()
{
Assert.Fail();
}
[TestMethod()]
public void ShowPayrollDetailsTest()
{
Assert.
This is the student class. I'm attempting to make it throw an exception if anyone enters a status other than postgrad or undergrad. These are enums.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DBSManagement
{
public class Student : Person
{
private Status status;
//auto-implemented properties
public Status Status
{
get
{
return status;
}
set
{
if (value == Status.undergrad || value == Status.postgrad)
{
status = value;
}
else throw new ArgumentException("Error: please select undergrad or postgrad");
}
}
public int StudentID { get; set; }
//empty constructor
public Student() { }
//constructor with parameters
public Student(string name, string address, string phone, string email, string ppsn, Status status, int studentId)
:base(name, address, phone, email, ppsn)
{
Status = status;
StudentID = studentId;
}
//overridden ToString() method
public override string ToString()
{
return string.Format("Name: {0}\nStudent Number: {1}\nAddress: {2}\nPhone: {3}\nEmail: {4}\nStatus: {5}",
Name, StudentID, Address, Phone, Email, Status);
}
}
}
You can test your code, but these tests will be very fragile (and, as #Scott Chamberlain noted, it won't be clear what they will be proving).
What you need to do is to "hide" that ugly Console.ReadLine() behind something you have "programmatic" control over. Func<string> would be ideal:
public static void AddStudent(Func<string> consoleReader)
{
Student student = new Student();
Console.WriteLine("Enter student name:");
student.Name = Console.ReadLine();
// ...
}
With this, your tests become something like:
[Test]
void TestAddStudent()
{
var n = 0;
var strings = new[] {
"Name",
"123 Fake St",
"0851234567",
"fake#address.com",
"7895459R",
// ...
};
Func<string> consoleReader = () => strings[n++];
var student = AddStudent(consoleReader);
Assert.AreEqual(strings[0], student.Name);
// ...
}
If you want to do testing it would be easier if you separate your UI from the logic. You could for instance adopt a MVC pattern or something like that. Start by building all your data objects like Lecturer, Student, etc. These objects would be your data model. Then add the logic, or controls, which manipulate these data objects. There could be a AddLecturer(..) method in the control component. Finally make a UI, or view, which interacts with them without being fully intertwined like in your code. With regard to testing, you'll mainly be writing tests for methods in the control components and maybe the model. There are plenty of things to test. Take your add lecturer method:
Is the name longer than 3 characters?
Is there at least two names? (Maybe this is a too strong assumption?)
Is the phone number correctly formatted?
Is the e-mail correctly formatted?
Is the lecturer ID only numbers? (Although, I'd expect the lecturer ID is something generated by your system)
Is the PPSN well formatted?
Is the salary positive?
Is the salary under a ludicrously large amount?
Is the salary even a number?`
When adding a new lecturer to lecturers did it really get added? (Typically you'd never check this. We trust the basic collections, unless you wrote it yourself.)
etc.
I am working on a small C# program that will store student records in a list. I need to use a class to hold each student record, which is the top class in my code sample below.
If the user chooses to create a new record, I place their input into a studentRecord variable and then add it to the recordList. However, when I attempt to display the number of student records currently available using Count(), the program does nothing except re-display the menu, as if totally ignoring my command to display. I think something is wrong with how/where I declared the list, or with how I create a new StudentRecord object each time the menu is run.
Also, all three methods must stay in the first class. Is there any way to fix this?
public class StudentRecord
{
//Declare the various fields of the class
private string strFirstName;
private string strLastName;
private int intCourses;
private int intCreditHours;
List<StudentRecord> lstRecords = new List<StudentRecord>();
//Declare the properties of the class, since the fields are private
public string StrFirstName
{
get
{
return strFirstName;
}
set
{
strFirstName = value;
}
}
public string StrLastName
{
get
{
return strLastName;
}
set
{
strLastName = value;
}
}
public int IntCourses
{
get
{
return intCourses;
}
set
{
intCourses = value;
}
}
public int IntCreditHours
{
get
{
return intCreditHours;
}
set
{
intCreditHours = value;
}
}
//Declare a default constructor
public StudentRecord()
{
}
//Declare a constructor that takes the four necessary parameters, and set the class
// properties equal to the respective parameters
public StudentRecord(string firstName, string lastName, int courses, int creditHours)
{
strFirstName = firstName;
strLastName = lastName;
intCourses = courses;
intCreditHours = creditHours;
}
//Declare a method to perform the adding a student record function
public void mtdAddStudentRecord()
{
//These variables temporarily hold the various user inputs
string strInputFirstName;
string strInputLastName;
int intInputCourses;
int intInputCreditHours;
//Prompt the user to enter the student's first name
Console.Write("Please enter the first name: ");
strInputFirstName = Console.ReadLine();
//Prompt the user to enter the student's last name
Console.Write("Please enter the last name: ");
strInputLastName = Console.ReadLine();
//Prompt the user to enter the student's number of courses
Console.Write("Please enter the number of courses: ");
intInputCourses = int.Parse(Console.ReadLine());
//Prompt the user to enter the student's completed credit hours
Console.Write("Please enter the number of completed credit hours: ");
intInputCreditHours = int.Parse(Console.ReadLine());
//Add the new student record to the list, using the paramaters of the second
// class constructor
lstRecords.Add(new StudentRecord(strInputFirstName, strInputLastName,
intInputCourses, intInputCreditHours));
}
//Declare a method to perform the display student information option
public void mtdDisplayStudentInformation()
{
Console.WriteLine("Capacity: {0}", lstRecords.Count);
}
//Declare a method to perform the edit student information option
public void mtdEditStudentInformation()
{
//TODO
}
}
public class Program
{
public static void Main(string[] args)
{
//Declare and initialize a variable to store the user menu choice
string strMenuChoice;
strMenuChoice = "";
//Perform the necessary menu option while the user has NOT chosen to exit
do
{
//Call the reset method to clear the screen and display the header
mtdResetConsole();
//Display a menu to the user
Console.Write("Please choose an option to perform:" +
"\n - A) Display a list of existing students" +
"\n - B) Add a new student record" +
"\n - C) Edit an existing student record" +
"\n - D) Exit the program" + "\n\n" + " ");
//Store the user reply
strMenuChoice = Console.ReadLine().ToLower();
//Create a new StudentRecord object, and use it to call the various methods
// as chosen by the user
StudentRecord studentRecord = new StudentRecord();
//Determine which option was chosen, and take the appropriate action
switch (strMenuChoice)
{
case "a":
//TODO - Necessary code for option A
mtdResetConsole();
//Perform the "view student records" method
studentRecord.mtdDisplayStudentInformation();
break;
case "b":
//TODO - Necessary code for option B
mtdResetConsole();
//Perform the "add student record" method
studentRecord.mtdAddStudentRecord();
break;
case "c":
//TODO - Necessary code for option C
break;
case "d":
//Exit the program
Environment.Exit(0);
break;
default:
mtdResetConsole();
Console.WriteLine("Error" + "\n" +
" - Please choose a valid option from the list");
//Pause the code from executing for 2.5 seconds, so that the error
// message will be displayed
System.Threading.Thread.Sleep(2500);
break;
}
}
while (strMenuChoice.ToLower() != "d");
}
//Declare a method to reset the console with a blank screen and header
public static void mtdResetConsole()
{
Console.Clear();
Console.WriteLine("CONESTOGA STUDENT RECORDS" + "\n");
}
}
First, put this outside do while
StudentRecord studentRecord = new StudentRecord();
Putting this inside do while means that the object will reset in every loop.
2nd, try to put something like Console.ReadLine() on mtdDisplayStudentInformation method to hold the screen.
public void mtdDisplayStudentInformation()
{
Console.WriteLine("Capacity: {0}", lstRecords.Count);
Console.ReadLine();
}
Kendall, try to separate the logic of your "Records" and your "List of records".
In the case bellow, you have a "list of records" for each record you create.
Suggestions are you create a static variable to make sure it is always the same list on all "Records" or you separate as bellow:
public class StudentRecord
{
//Declare the various fields of the class
private string strFirstName;
private string strLastName;
private int intCourses;
private int intCreditHours;
...
}
public class Program
{
private List<StudentRecord> records = new List<StudentRecord>();
public static void Main(string[] args)
{
...
}
}
Coming from a procedural background, I'm running into a conceptual block while designing a menu-based console application and user input validation. My goal is to display a menu that launches other processes. I want to limit user input to 1, 2, or 3 at the menu.
In a procedural language, I would do something like this pseudocode:
10 print "Make a choice"
20 choice = [dataFromKeyboard]
30 if choice < 4 && choice > 0
40 then 10
50 else 60
60 process valid choices
and no matter what I try, I can't get that out of my head while designing an OO program. Consider (simplified to include only 3 menu items):
class Menu
{
public static void Main(String[] args)
{
DisplayMenu thisdm = new DisplayMenu;
int menuChoice = thisdm.displayMenu();
ProcessMenu thispm = new ProcessMenu();
thispm.processMenu(menuChoice);
}
}
class DisplayMenu
{
public int displayMenu()
{
Console.WriteLine("1 - foo3");
Console.WriteLine("2 - foo2");
Console.WriteLine("3 - foo3");
Console.WriteLine("choose");
String choice = Console.ReadLine();
int intChoice = Convert.ToInt32(choice);
return intChoice;
}
}
class ProcessMenu
{
public void processMenu(int choice)
{
switch(choice)
{
case 1:
foo1();
break;
case 2:
foo2();
break;
case 3:
foo3();;
break;
default:
Console.WriteLine("Invalid selection. Please select 1, 2, or 3.");
break;
}
}
}
So here's where I'm stuck. I just can't wrap my head around a simple and elegant way validate my user input that's from an OO rather than procedural standpoint.
Assuming I do the validation in the DisplayMenu, I would be validating after the input is read. But if it turns out to be invalid, how do I re-ask for valid input, since I've already called displayMenu method from Main?
I've been playing with while loops for about an hour, something like this:
intChoice = 0;
[print the menu]
while ((intChoice<1) || (intChoice>3))
Console.WriteLine("Please make a valid choice from the menu");
choice = Console.ReadLine();
etc.
but can't seem to find the sweet spot where I can control user input.
I suspect it's because I'm thinking to procedurally, and not object-oriented enough. Anyone have any tips or input to help me wrap my head around this?
Expanding on #AlexeiLevenkov's suggestion of "turning your classes 90 degrees", I went a step further and created this example of a "Modular" console Application:
class Program
{
static void Main(string[] args)
{
//Retrieve all Module types in the current Assembly.
var moduletypes = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(x => x.IsSubclassOf(typeof(ConsoleModule)));
//Create an instance of each module
var modules = moduletypes.Select(Activator.CreateInstance)
.OfType<ConsoleModule>()
.OrderBy(x => x.Id)
.ToList();
int SelectedOption = -1;
while (SelectedOption != 0)
{
//Show Main Menu
Console.Clear();
Console.WriteLine("Please Select An Option:\n");
modules.ForEach(x => Console.WriteLine(string.Format("{0} - {1}", x.Id, x.DisplayName)));
Console.WriteLine("0 - Exit\n");
int.TryParse(Console.ReadLine(), out SelectedOption);
//Find Module by Id based on user input
var module = modules.FirstOrDefault(x => x.Id == SelectedOption);
if (module != null)
{
//Execute Module
Console.Clear();
module.Execute();
Console.WriteLine("Press Enter to Continue...");
Console.ReadLine();
}
}
}
ConsoleModule class:
public abstract class ConsoleModule
{
public int Id { get; set; }
public string DisplayName { get; set; }
public abstract void Execute();
}
Some sample Modules:
public class EnterUserNameModule : ConsoleModule
{
public EnterUserNameModule()
{
Id = 2;
DisplayName = "User Name";
}
public static string UserName { get; set; }
public override void Execute()
{
Console.WriteLine("Please Enter Your Name: ");
UserName = Console.ReadLine();
}
}
public class HelloWorldModule: ConsoleModule
{
public HelloWorldModule()
{
Id = 1;
DisplayName = "Hello, World!";
}
public override void Execute()
{
Console.WriteLine("Hello, " + (EnterUserNameModule.UserName ?? "World") + "!");
}
}
public class SumModule: ConsoleModule
{
public SumModule()
{
Id = 3;
DisplayName = "Sum";
}
public override void Execute()
{
int number = 0;
Console.Write("Enter A Number: ");
if (int.TryParse(Console.ReadLine(), out number))
Console.WriteLine("Your number plus 10 is: " + (number + 10));
else
Console.WriteLine("Could not read your number.");
}
}
Result:
It uses a little bit of reflexion to find all types deriving from ConsoleModule in the current assembly, then shows a menu with all these options (which are actually properties in this class), and calls the Execute() method when an appropiate option is selected. Much more towards OO way of thinking.
Make your processMenu function return some kind of indicator. You could use exceptions for this instead, but that's overkill.
public bool processMenu(int choice)
{
....
}
If the choice was acceptable, then return true, otherwise return false. Then:
public static void Main(String[] args)
{
DisplayMenu thisdm = new DisplayMenu;
ProcessMenu thispm = new ProcessMenu();
int menuChoice;
do {
menuChoice = thisdm.displayMenu();
} while( !thispm.processMenu(menuChoice) );
}
The way you are doing should be changed. Anyhow, for the same as your question, this works out:
DisplayMenu thisdm = new DisplayMenu();
int menuChoice = -1;
while (menuChoice < 1 || menuChoice > 3)
{
Console.WriteLine("enter valid choice");
menuChoice = thisdm.displayMenu();
}
ProcessMenu thispm = new ProcessMenu();
thispm.processMenu(menuChoice);
the code like:
class Program
{
static void Main(string[] args)
{
DisplayMenu thisdm = new DisplayMenu();
ProcessMenu thispm = new ProcessMenu();
thisdm.displayMenu();
int menuChoice = thispm.GetChoice();
thispm.processMenu(menuChoice);
Console.Read();
}
}
class DisplayMenu
{
public void displayMenu()
{
Console.WriteLine("1 - foo3");
Console.WriteLine("2 - foo2");
Console.WriteLine("3 - foo3");
Console.WriteLine("choose");
}
}
class ProcessMenu
{
public int GetChoice()
{
String choice = Console.ReadLine();
int intChoice = Convert.ToInt32(choice);
while (!Validate(intChoice))
{
Console.WriteLine("Invalid selection. Please select 1, 2, or 3.");
choice = Console.ReadLine();
intChoice = Convert.ToInt32(choice);
}
return intChoice;
}
public void processMenu(int choice)
{
switch (choice)
{
case 1:
//foo1();
break;
case 2:
//foo2();
break;
case 3:
//foo3(); ;
break;
default:
//Console.WriteLine("Invalid selection. Please select 1, 2, or 3.");
break;
}
}
private int[] forChoices=new int[]{1,2,3};
private bool Validate(int choice)
{
if(forChoices.Contains(choice))
{
return true;
}
return false;
}
}