I need to ask the user for his name, surname and other details and I wan't to verify them, basically checking if the string is empty, is an integer, or contains an integer. The problem with this code is let's say I type in "a" it works. And if I type in a2 it shows the correct error message but when I go to type in "a" on its own it keeps repeating the same error message. Any help would be appreciated and a cleaner way to write this would also be appreciated as I have to do this for the surname, email and other fields.
bool check = true;
Console.Write("Enter your name:");
string name = Console.ReadLine();
bool isEmpty = string.IsNullOrEmpty(name);
bool isIntString = name.All(char.IsDigit);
bool containsInt = name.Any(char.IsDigit);
while (check == true) {
if (isEmpty)
{
Console.WriteLine("Name cannot be empty");
Console.Write("Enter your name: ");
name = Console.ReadLine();
}
else if(isIntString)
{
Console.WriteLine("Your name cannot be made up of numbers");
Console.Write("Enter your name: ");
name = Console.ReadLine();
}
else if (containsInt)
{
Console.WriteLine("Your name cannot contain numbers");
Console.Write("Enter your name: ");
name = Console.ReadLine();
}
else if(!isEmpty && !isIntString && !containsInt)
{
check = false;
Console.WriteLine("Name filled");
}
}
Console.WriteLine("Your name is: " + name);
Console.ReadKey();
After reading the input, you are checking for null/empty/integers.
bool isEmpty = string.IsNullOrEmpty(name);
bool isIntString = name.All(char.IsDigit);
bool containsInt = name.Any(char.IsDigit);
However, these checks are placed outside the loop. Once evaluated, the 3 verification variables never changes, even after new input has been read.
For fixing the same, you need to place the checks within the loop.
while (check == true) {
bool isEmpty = string.IsNullOrEmpty(name);
bool isIntString = name.All(char.IsDigit);
bool containsInt = name.Any(char.IsDigit);
// rest of code
To clean up code, you could refactor out the expressions and reading input to create a pattern, which could be reused for other inputs. For example,
void Main()
{
bool check = true;
var name = ReadInput("Enter your name:",ValidationExpressionsForName);
// var surname = ReadInput("Enter your SurName :",ValidationExpressionsForSurName);
// so on
Console.WriteLine("Your name is: " + name);
}
public string ReadInput(string inputMessage,Func<string,IEnumerable<EvaluationExpression>> evaluationExpression)
{
while (true)
{
Console.Write(inputMessage);
string term = Console.ReadLine();
if(evaluationExpression(term).Any(x=>x.Expression()))
{
Console.WriteLine(evaluationExpression(term).First(x=>x.Expression()).Message);
}
else
return term;
}
}
public IEnumerable<EvaluationExpression> ValidationExpressionsForName(string message) => new EvaluationExpression[]
{
new EvaluationExpression{ Expression = ()=>String.IsNullOrWhiteSpace(message), Message= "Name cannot be empty"},
new EvaluationExpression{ Expression = ()=>message.All(char.IsDigit),Message ="Your name cannot be made up of numbers"},
new EvaluationExpression{ Expression = ()=>message.Any(char.IsDigit),Message="Your name cannot contain numbers"}
};
public class EvaluationExpression
{
public Func<bool> Expression{get;set;}
public string Message{get;set;}
}
Checking if a string is Null, Empty or WhiteSpace is relatively easy:
https://learn.microsoft.com/en-us/dotnet/api/system.string.isnullorwhitespace
Checking if it is a Number can be done. Just feed it to Int32.TryParse() and see if it can make sense of the input.
If it contains a anumber? Checkable, but not easily. You could itterate over all Characters in the string and check if any of them parse to Int. Note that this cheeck would supersede/make unessesary the previous check too. I made it into a simple function:
public bool IsValidName(String input){
if(String.IsNullOrWhiteSpace(input)){
return false;
}
foreach (char current in input){
int ignore;
//TryPrase will not take Chars, but turning it into a string should be this easy
String currentString = current.ToString();
if(Int32.TryParse(currentString, out ignore))
return false;
}
//You only get here if none of hte false cases was trigerred
return true;
}
All of this might be solveable with a single Regular Expression too, but I am not that good at Regex.
With small changes to your code:
string name;
while (true)
{
Console.Write("Enter your name:");
name = Console.ReadLine();
bool isEmpty = string.IsNullOrEmpty(name);
bool isIntString = name.All(char.IsDigit);
bool containsInt = name.Any(char.IsDigit);
if (isEmpty)
{
Console.WriteLine("Name cannot be empty");
}
else if (isIntString)
{
Console.WriteLine("Your name cannot be made up of numbers");
}
else if (containsInt)
{
Console.WriteLine("Your name cannot contain numbers");
}
else
{
Console.WriteLine("Name filled");
break;
}
}
Console.WriteLine("Your name is: " + name);
Console.ReadKey();
With variable term:
static string GetUserInput(string term)
{
string name;
while (true)
{
Console.Write($"Enter your {term}:");
name = Console.ReadLine();
bool isEmpty = string.IsNullOrEmpty(name);
bool isIntString = name.All(char.IsDigit);
bool containsInt = name.Any(char.IsDigit);
if (isEmpty)
{
Console.WriteLine("Cannot be empty");
}
else if (isIntString)
{
Console.WriteLine("Cannot be made up of numbers");
}
else if (containsInt)
{
Console.WriteLine("Cannot contain numbers");
}
else
{
Console.WriteLine($"Your {term} filled");
break;
}
}
Console.WriteLine($"Your {term} is: {name}");
return name;
}
Your code fails here. It goes into this else block displays the error message and then reads from the console again. while check still being true and isIntString still true it again lands up in this block. You need to correct it for all the three checks you have placed on the the string.
else if(isIntString)
{
Console.WriteLine("Your name cannot be made up of numbers");
isIntString = false; // to prevent going into this block again
Console.Write("Enter your name: ");
name = Console.ReadLine();
}
Related
So I wanted to make a sort of “name checker” that’s always had the first letter be capital and the rest lowercase. I got that to work but whenever I got past the name checker and wanted to use the name in future code, it would always say “string may be null here.” I have tried many things like adding a ? But nothing works. I don’t think it can be null but maybe I’m wrong. Here is my code here:
class Program
{
static void Main()
{
string? name, choice;
bool finishnameingcharacter;
finishnamingcharacter = true;
while(finishingnamingcharacter == false)
{
Console.WriteLine("Enter your name");
name = Console.ReadLine();
name = name?.ToLower();
if(name != null)
{
name = char.ToUpper(name[0]) + name.Substring(1);
}
Console.WriteLine("");
Console.WriteLine("Your name is " +name+ ", is that correct?");
Console.WriteLine("");
Console.WriteLine("1: Yes");
Console.WriteLine("2: No");
choice = Console.ReadLine();
if(choice == "1")
{
finishnamingcharacter = 1;
}
if(choice == "2")
{
Console.WriteLine("");
}
else
{
Console.WriteLine("Invalid Claim")
}
}
Console.WriteLine(name);
}
}
The "name" at the bottom is where the error is. If there's any confusion about my question ask me. I tried my best to explain it.
I could not compile your code, so I made some changes
static void Main()
{
var name = string.Empty;
var choice = string.Empty;
do
{
Console.WriteLine("Enter your name");
name = Console.ReadLine();
name = name?.ToLower();
if (name != null && name.Length>1)
name = char.ToUpper(name[0]) + name.Substring(1);
Console.WriteLine("");
Console.WriteLine("Your name is " + name + ", is that correct?");
Console.WriteLine("");
Console.WriteLine("1: Yes");
Console.WriteLine("2: No");
choice = Console.ReadLine();
if (choice == "1") break;
if (choice == "2")Console.WriteLine("");
else Console.WriteLine("Invalid Claim");
} while (true);
Console.WriteLine(name);
}
Why use a nullable string in this software?
You didn't initialize the name at the beginning, if your loop will never run, then the name output line will be NULL. This is what your error points to.
It is better to initialize variables before their first use, as they can be NULL by default (valid for reference types such as classes). For a string, one option would be String.Empty
string name = String.Empty, choice = String.Empty;
These two lines can be combined:
bool finishnameingcharacter;
finishnamingcharacter = true;
// Replaced by
bool finishnameingcharacter = true;
On the next line in the while loop, you check the condition: finishingnamingcharacter == false. The loop checks the condition and only then executes. To execute the loop, you need the condition to be TRUE, but it will not take this value, because earlier you defined the variable finishnamingcharacter = true. true != false. By default you need to define this variable as false
bool finishnameingcharacter = false;
The user can enter an empty string value, so converting it to lowercase immediately doesn't matter, as long as it checks for an empty string. There is a special method for checking if a string is empty: string.IsNullOrEmpty() - it returns true if the string is empty or null.
If the user entered the wrong name, then we need to ask him to enter again, for this, the continue operator is used.
name = Console.ReadLine();
if(string.IsNullOrEmpty(name) || string.IsNullOrWhiteSpace(name))
{
Console.WriteLine("Sorry, your name is empty. Please enter again.")
continue;
}
//So if name is not empty: jOhN
name = name.ToLower(); //john
name = char.ToUpper(name[0]) + name.Substring(1); //John
For boolean values it is better to use reserved words, i.e. instead of finishnamingcharacter = 1 it is better to write finishnamingcharacter = true
Rest of the code looks good. We all took the first steps :)
Full modified code here:
class Program
{
static void Main()
{
string name = String.Empty choice = String.Empty;
bool finishnameingcharacter = false;
while(finishingnamingcharacter == false)
{
Console.WriteLine("Enter your name");
name = Console.ReadLine();
if(string.IsNullOrEmpty(name) || string.IsNullOrWhiteSpace(name))
{
Console.WriteLine("Sorry, your name is empty. Please enter again.")
continue;
}
//So if name is not empty: jOhN
name = name.ToLower(); //john
name = char.ToUpper(name[0]) + name.Substring(1); //John
Console.WriteLine("");
Console.WriteLine("Your name is " +name+ ", is that correct?");
Console.WriteLine("");
Console.WriteLine("1: Yes");
Console.WriteLine("2: No");
choice = Console.ReadLine();
if(choice == "1")
{
finishnamingcharacter = true;
}
else if(choice == "2")
{
Console.WriteLine("");
}
else
{
Console.WriteLine("Invalid Claim")
}
}
Console.WriteLine(name);
}
}
PS There is a special method TextInfo.ToTitleCase() "wAr aNd pEaCe to titlecase: War And Peace" - I advise you to read
I am working on a simple code that asks for the name, age, and gender of at most 5 patients. After each patient, it should ask to input another patient or return to main menu. Once 5 have been input into an array, there should be a prompt to the user that the array is full.
My problem is the code asks for name,age and gender 5 times upfront, and does not give any indication the array is full. How would I change the code to reflect that and still save the inputs? (Code below).
class MainClass
{
enum Gender { female, male }
struct Record
{
public string _Name;
public int _Age;
public Gender _Gender;
}
public static void Main(string[] args)
{
//title
Console.Write("\t\t\t\t\tPatient Records\n");
string selection = "";
Record[] patients = new Record[5];
GetRecords(patients);
Console.Write("a. Add\n d.Display\ns. Stats\nq. Quit");
Console.Write("Your selection: ");
selection = Console.ReadLine();
switch (selection)
{
case "a":
GetRecords(patients);
break;
case "d":
break;
case "s":
Stats(patients);
break;
case "q":
//CUtility.Pause();
break;
}
}
static void GetRecords(Record[] patient_rec)
{
for (int i = 0; i < patient_rec.Length; i++)
{
Console.Write("Enter your age: ");
int.TryParse(Console.ReadLine(), out patient_rec[i]._Age);
Console.Write("Enter your name: ");
patient_rec[i]._Name = Console.ReadLine();
Console.Write("Enter your gender (female or male): ");
Gender.TryParse(Console.ReadLine(), out patient_rec[i]._Gender);
}
}
static void Stats(Record[]patient_rec)
{
}
}
I would suggest trying to make your code a little easier to read - and more robust.
Try this:
static void GetRecords(Record[] patient_rec)
{
for (int i = 0; i < patient_rec.Length; i++)
{
Console.WriteLine("Record {0} of {1} entry", i + 1, patient_rec.Length);
patient_rec[i] = new Record()
{
_Age = AskInteger("Enter your age: "),
_Name = AskString("Enter your name: "),
_Gender = AskGender("Enter your gender (female or male): "),
};
string ask = "";
while (string.IsNullOrEmpty(ask) || (ask.ToLower()[0] != 'y' && ask.ToLower()[0] != 'n'))
{
Console.WriteLine("Continue? yes or no (then hit enter)");
ask = Console.ReadLine();
}
if (ask.ToLower()[0] == 'y')
{
continue;
}
break;
}
Console.WriteLine("Thank you. Input completed.");
}
To make this work you need these three input functions:
private static int AskInteger(string message)
{
int result;
Console.WriteLine(message);
string input = Console.ReadLine();
while (!int.TryParse(input, out result))
{
Console.WriteLine("Invalid input.");
Console.WriteLine(message);
input = Console.ReadLine();
}
return result;
}
private static string AskString(string message)
{
Console.WriteLine(message);
string input = Console.ReadLine();
while (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("Invalid input.");
Console.WriteLine(message);
input = Console.ReadLine();
}
return input;
}
private static Gender AskGender(string message)
{
Gender result;
Console.WriteLine(message);
string input = Console.ReadLine();
while (!Gender.TryParse(input, out result))
{
Console.WriteLine("Invalid input.");
Console.WriteLine(message);
input = Console.ReadLine();
}
return result;
}
Your loop is only set to go to the size of the array, so logically you could show a message after the loop (this will get hit when the loop finishes).
If you were controlling your array access in a while loop then just compare your indexer i to the length of the array (patient_rec.Length), if it equals or exceeds the length then show the message.
I would do it in a simpler way:
enum Gender { female, male }
struct Record
{
public string _Name;
public int _Age;
public Gender _Gender;
}
static void Main(string[] args)
{
//title
Console.Write("\t\t\t\t\tPatient Records\n");
IList<Record> patients = GetRecords(5);
SchedulePatients(patients);
}
static void SchedulePatients(IList<Record> patients)
{
Console.Write("a. Add\n d.Display\ns. Stats\nq. Quit");
Console.Write("Your selection: ");
string selection = Console.ReadLine();
switch (selection)
{
case "a":
patients.Add(GetRecord());
SchedulePatients(patients);
break;
case "d":
break;
case "s":
Stats(patients);
break;
case "q":
//CUtility.Pause();
break;
}
}
static IList<Record> GetRecords(int amount)
{
IList<Record> patients = new List<Record>();
for (int i = 0; i < amount; i++)
{
patients.Add(GetRecord());
}
return patients;
}
static Record GetRecord()
{
Record patient = new Record();
Console.Write("Enter your age: ");
int.TryParse(Console.ReadLine(), out patient._Age);
Console.Write("Enter your name: ");
patient._Name = Console.ReadLine();
Console.Write("Enter your gender (female or male): ");
Enum.TryParse(Console.ReadLine(), out patient._Gender);
return patient;
}
static void Stats(IList<Record> patients)
{
foreach (var patient in patients)
{
Console.WriteLine(string.Concat("Name: ", patient._Name, " Age: ", patient._Age, " Gender: ", patient._Gender));
}
Console.ReadLine();
}
}
If you would like to meet the requirements with the smallest change possible, you just need to add the bit about prompting the user.
static void GetRecords(Record[] patient_rec)
{
for (int i = 0; i < patient_rec.Length; i++)
{
Console.Write("Enter your age: ");
int.TryParse(Console.ReadLine(), out patient_rec[i]._Age);
Console.Write("Enter your name: ");
patient_rec[i]._Name = Console.ReadLine();
Console.Write("Enter your gender (female or male): ");
Gender.TryParse(Console.ReadLine(), out patient_rec[i]._Gender);
Console.Write("Enter another (Y/N)? ");
var s = Console.ReadLine();
if (s.ToUpper() != "Y") return;
}
Console.WriteLine("You've entered the maximum number of records.");
}
Trying to complete a stock system in a console application and thus I am stuck on this part, to make sure that a user can't have a duplicate 8 digit long ID number, my issue is as follows.
Basically I am unsure why this code will not work, I'm probably missing a very obvious piece of code here, help would be appreciated, have tried changing values around already so have more than likely overlooked a value.
static int checkIDNumber(int ID)
{
// Check the number passed in & then loop through all the lines...
// If number is taken then output error, because id exists already
// Else allow the value to be used in the stock system.
int IDNumber = ID;
using (StreamReader sr = new StreamReader("Stockfile.txt"))
{
string lineValues;
while (sr.EndOfStream == false)
{
lineValues = sr.ReadLine();
if (lineValues.Contains(IDNumber.ToString()))
{
Console.WriteLine("Id number is currently already taken.");
}
else
{
return IDNumber;
}
}
}
}
I pass in my value from this line in another procedure where it is defined in the local scope.
stockID = checkIDNumber(stockID);
Here is the full code:
class Program
{
static void Main(string[] args)
{
char menuOption = '0';
while (menuOption != '3')
{
DisplayMenuOption();
menuOption = GetMenuOption();
switch (menuOption)
{
case '1':
AddStock();
break;
case '2':
CheckStock();
break;
case '3':
Console.WriteLine("Goodbye");
break;
default:
Console.WriteLine("That is not a valid option");
break;
}
}
// Keep it all happy for a screenshot ;)
Console.ReadLine();
}
static void DisplayMenuOption()
{
Console.WriteLine("Do you wish to Add Stock(1) or Check Stock(2) or Exit(3)?");
}
static void DisplayStockOption()
{
Console.WriteLine("Do you want to search by ID(1) or by Name(2), Delete current stock(3) or Exit(4)?");
}
static char GetMenuOption()
{
char userChoice = '0';
userChoice = Convert.ToChar(Console.ReadLine());
return userChoice;
}
static void CheckStock()
{
char menuOption = 'a';
while (menuOption != '4')
{
DisplayStockOption();
menuOption = GetMenuOption();
switch (menuOption)
{
case '1':
SearchID();
break;
case '2':
SearchName();
break;
case '3':
RemoveStock();
break;
case '4':
Console.WriteLine("Goodbye");
break;
default:
Console.WriteLine("That is not a valid option");
break;
}
}
}
static void RemoveStock()
{
List<string> tempList = new List<string>();
string lineValues = "";
bool found = false;
int ID = 0;
using (StreamReader sr = new StreamReader("Stockfile.txt"))
{
Console.Write("Please enter the ID number to delete: ");
ID = Convert.ToInt32(Console.ReadLine());
while (sr.EndOfStream == false)
{
lineValues = sr.ReadLine();
if (lineValues.Contains(ID.ToString()) == false)
{
tempList.Add(lineValues);
}
else
{
found = true;
}
}
}
if (found == true)
{
using (StreamWriter sw = new StreamWriter("Stockfile.txt", false))
{
for (int i=0; i < tempList.Count; i++)
{
sw.Write(tempList[i]);
sw.WriteLine();
}
}
}
}
static void SearchName()
{
using (StreamReader sr = new StreamReader("Stockfile.txt"))
{
string name;
Console.Write("Please enter the name: ");
name = Console.ReadLine();
while (sr.EndOfStream == false)
{
string lineValues = sr.ReadLine();
if (lineValues.Contains(name))
{
Console.WriteLine("{0}", lineValues);
}
else
{
Console.WriteLine("{0} does not exist in this stock system!",name); // Could try to match a similar string incase of spelling errors here, although after looking at it it may be a bit far for what is being required now, but in the real world application this would be a must else people would mistype words thus not having an exact match.
}
}
}
}
static void SearchID()
{
using (StreamReader sr = new StreamReader("Stockfile.txt"))
{
int IDNumber;
string lineValues;
Console.Write("Please enter the ID number: ");
IDNumber = Convert.ToInt32(Console.ReadLine());
while (sr.EndOfStream == false)
{
lineValues = sr.ReadLine();
if (lineValues.Contains(IDNumber.ToString()))
{
Console.WriteLine("{0}", lineValues);
}
else
{
Console.WriteLine("{0} does not exist in this stock system!", IDNumber); // Could try to match a similar string incase of spelling errors here, although after looking at it it may be a bit far for what is being required now, but in the real world application this would be a must else people would mistype words thus not having an exact match.
}
}
}
}
static int checkIDNumber(int ID)
{
// Check the number passed in & then loop through all the lines...
// If number is taken then output error, becuase id exists already
// Else allow the value to be used in the stock system.
using (StreamReader sr = new StreamReader("Stockfile.txt"))
{
int IDNumber;
string lineValues;
Console.Write("Please enter the ID number: ");
IDNumber = Convert.ToInt32(Console.ReadLine());
while (sr.EndOfStream == false)
{
lineValues = sr.ReadLine();
if (lineValues.Contains(IDNumber.ToString()))
{
Console.WriteLine("Id number is currently already taken.");
}
else
{
ID = IDNumber;
return ID;
}
}
}
}
static void AddStock(int IDNumber)
{
using (StreamWriter sw = new StreamWriter("Stockfile.txt", true))
{
int stockID = 0;
int stockQuantity = 0;
double stockPrice = 0.00;
string stockName = "";
string s = ""; // Being Lazy here, to convert to when needed.
while (stockID.ToString().Length != 8)
{
Console.Write("Please enter the stock ID number: ");
stockID = Convert.ToInt32(Console.ReadLine());
}
s = stockID.ToString();
sw.Write(s + "\t"); // Will only accept an 8 figure digit so is safe to have a single value here.
while (stockName.Length <= 2) // No fancy brands here......
{
Console.Write("Please enter the name of the stock: ");
stockName = Console.ReadLine();
}
s = stockName;
sw.Write(s + "\t");
while (stockQuantity < 1) // Running a small shop here...
{
Console.Write("Please enter the quanity of stock: ");
stockQuantity = Convert.ToInt32(Console.ReadLine());
}
s = stockQuantity.ToString();
sw.Write(s + "\t");
while (stockPrice < 0.01) // Running a very small shop....
{
Console.Write("Please enter the price of the stock: ");
stockPrice = Convert.ToDouble(Console.ReadLine());
}
s = stockPrice.ToString();
sw.Write(s + "\t");
sw.WriteLine(); // TO create the new line.....
}
}
}
}
The problem is that you're only returning a value from inside the else block.
Your method needs to return a value regardless of which path the program takes through your code. You can fix this in any number of ways, depending on your requirements. For instance, you can have a "catch-all" return value at the bottom of the method so that if it passes through all your tests (i.e. if blocks) and reaches the bottom, as long as that's a meaningful result, it will return the catch-all value.
Alternatively, you could just make sure you put a return statement inside each of the code paths. For that, you'd need to add a return in the if portion of your if block, but you'd likely also still need a return outside of your while loop since that may never execute.
Again, it all depends on your needs.
It's at least logically possible that the file contains nothing but the ID. For example, if I enter "10" as an ID and the file is:
10
10
10
10
...
It might be the case that you know that that'll never actually happen, but the compiler can't really prove that it won't. From the compiler's "perspective," there's not really a difference between "might happen" and "can't prove that it won't happen."
Also, your logic is wrong. If you know that the user requested a duplicate ID, you don't need to check the rest of the file - you already know it's a duplicate.
Right now, if the first line of the file isn't the ID they requested, it'll allow the user to take it. For example, if the user requested "9" as an ID and the file is as follows:
3 -- It only actually checks this line
5
9 -- Obviously the ID is already taken here but it'll never check this line
2
1
See my comments below:
// I'd suggest making this "bool" - they already know what the ID number is,
// so there's no point in returning it back to them
static int checkIDNumber(int ID)
{
// Check the number passed in & then loop through all the lines...
// If number is taken then output error, because id exists already
// Else allow the value to be used in the stock system.
int IDNumber = ID;
using (StreamReader sr = new StreamReader("Stockfile.txt"))
{
string lineValues;
// In general, you shouldn't explicitly compare to "true" or "false."
// Just write this as "!sr.EndOfStream"
while (sr.EndOfStream == false)
{
lineValues = sr.ReadLine();
if (lineValues.Contains(IDNumber.ToString()))
{
// In this case, you don't have to bother checking the rest of the file
// since you already know that the ID is taken
Console.WriteLine("Id number is currently already taken.");
}
else
{
// You actually can't return that at this point - you need to check
// the *entire* file before you conclude that it's not a duplicate
return IDNumber;
}
}
}
}
I have a few problems with the code below. I'm still learning and I don't know how to fix it.
1 .-What I'm trying to do is create a method (GetInt) to store variables like I'm trying to do in the second method (GetTrack) that will go into my main method.
2.-I can't get the GetInt method to loop when theres an invalid input, I'm guessing there's something wrong with the try/catch and boolean thingy
Thank you
//Get int Method
static public void GetInt(string sPrompt, int iMin, int iMax)
{
int iNum;
bool bError = false;
do
{
bError = true;
try
{
Console.Write(sPrompt);
iNum = int.Parse(Console.ReadLine());
if ((iNum < iMin) || (iNum > iMax))
{
Console.WriteLine("The value is out of range.");
bError = true;
}
}
catch (ArgumentException)
{
Console.WriteLine("An invalid number was entered, please try again.");
bError = true;
}
}
while (bError == false);
}
//Get Track Method
static public void GetTrack()
{
int iMin;
int iSec;
iMin = GetInt("Enter the minutes: ", 0, 10);
iSec = GetInt("Enter the seconds: ", 0, 59);
}
Immediately in the beginning of GetInt you set bError to true. This most likely should be false so you would actually loop since nowhere do you set it to false.
Also you don't return anything from the method so you don't get anything back. You have to change the method to return int and actually return the value when you get it.
The declaration of your GetInt method should be changed to the following:
//Get int Method
static public int GetInt(string sPrompt, int iMin, int iMax)
Remove the bError = true; statement from the beginning of your do...while loop.
After your do...while loop, add the following statement:
return iNum;
Also, your while condition should be changed from bError == false to bError == true or simply to bError, which means the same thing, if your intent is to keep prompting the user until the input is acceptable.
Here is how I "get" user input from the console:
string choice = string.Empty;
bool goodChoice = false;
while (!goodChoice)
{
Console.Clear();
Console.WriteLine(string.Empty);
Console.WriteLine("Do you really want to hurt me?");
Console.WriteLine(string.Empty);
Console.WriteLine(string.Empty);
Console.WriteLine("Please Y or N (or 0 to exit)");
choice = Console.ReadLine().Trim();
if (choice.Equals("Y", StringComparison.OrdinalIgnoreCase))
{
goodChoice = true;
}
if (choice.Equals("N", StringComparison.OrdinalIgnoreCase))
{
goodChoice = true;
}
if (choice.Equals("0"))
{
goodChoice = true;
return; /* exist the routine */
}
}
Modified for your case
string choice = string.Empty;
bool goodChoice = false;
while (!goodChoice)
{
Console.Clear();
Console.WriteLine(string.Empty);
Console.WriteLine("Enter an Integer between {0} and {1}", minValue, maxValue);
Console.WriteLine(string.Empty);
Console.WriteLine(string.Empty);
Console.WriteLine("Please enter an integer (or X to exit)");
choice = Console.ReadLine().Trim();
int intParseResult = 0;
bool intParseAttempt = int.TryParse(choice, out intParseResult);
if(!intParseAttempt)
{
goodChoice = false;
}
else
{
if ((intParseResult < minValue) || (intParseResult > maxValue))
{
Console.WriteLine("Out of Range");
}
else
{
goodChoice = true;
}
}
if (choice.Equals("X"))
{
goodChoice = true;
return -99999; /* you'll have to figure out how to handle exits on your own */
}
}
This is a simple begginer program with setter and getter concept
now i have to make it to first enter user name and password to get welcomed
and IF I ENTER WRONG INFO IT SHOULD DISPLAY INVALID AND 5 TRIES LEFT THEN if i again enter wrong info it should display 4 tries left and so on and finally when all tries are over it should hang the program or lock the screen or so
using System;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
demo obj = new demo();
string uname, pass;
Console.ForegroundColor = ConsoleColor.Green;
label1:
Console.Clear();
Console.WriteLine("Enter username");
uname = Console.ReadLine();
Console.WriteLine("Enter Password");
pass = Console.ReadLine();
obj.setName(uname);
obj.setPass(pass);
if (obj.getName() == "niit")
{
if (obj.getPass() == "1234")
{
Console.WriteLine("welcome");
}
}
else
{
Console.Clear();
Console.WriteLine("Invalid");
Console.WriteLine("\n \n \n To try again enter y");
int n = 5;
string yes = Console.ReadLine();
if (yes == "y")
{
while (n >= 1)
{
Console.Write(n + " Tries left");
goto label1;
n = --n;
}
}
}
Console.ReadKey();
}
}
class demo
{
private string name, pass;
public void setName(string name)
{
this.name = name;
}
public string getName()
{
return name;
}
public void setPass(string pass)
{
this.pass = pass;
}
public string getPass()
{
return pass;
}
}
}
Please suggest a simple begginers code to make the loop work and make the count down
A while loop should suffice. Using a boolean to detect successful password entry.
When entered, it will break out of the loop.
invalid attempts will decrement the AttemptsLeft int.
Note: I haven't tried this in Visual Studio, the logic should be sound, but I recommend debugging and stepping through it to test if it meets your criteria.
static void Main(string[] args)
{
demo obj = new demo();
string uname, pass;
Console.ForegroundColor = ConsoleColor.Green;
label1:
Console.Clear();
Console.WriteLine("Enter username");
uname = Console.ReadLine();
Console.WriteLine("Enter Password");
bool SuccessfulPassword = false;
int AttemptsLeft = 5;
while(!SuccessfulPassword && AttemptsLeft > 0){
pass = Console.ReadLine();
obj.setName(uname);
obj.setPass(pass);
if (obj.getName() == "niit")
{
if (obj.getPass() == "1234")
{
Console.WriteLine("welcome");
SuccessfulPassword = true;
}
}
else
{
AttemptsLeft--;
Console.Clear();
Console.WriteLine("Invalid");
Console.WriteLine("\n \n \n To try again enter y");
int n = 5;
string yes = Console.ReadLine();
if (yes == "y")
{
Console.Write(AttemptsLeft + " Tries left");
}
}
Console.ReadKey();
}
}
try this updated main method:
static void Main(string[] args)
{
demo obj = new demo();
int n = 5;
string uname, pass;
Console.ForegroundColor = ConsoleColor.Green;
//Console.Clear();
label1:
Console.WriteLine("\n");
Console.WriteLine("Enter username");
uname = Console.ReadLine();
Console.WriteLine("Enter Password");
pass = Console.ReadLine();
obj.setName(uname);
obj.setPass(pass);
if (obj.getName() == "niit" && obj.getPass() == "1234")
{
Console.WriteLine("welcome");
}
else
{
//Console.Clear();
if (n < 1)
{
//Add ur screenlock n hang prog code
Console.Clear();
Console.WriteLine("ScreenLock");
}
else
{
Console.WriteLine("\n Invalid");
Console.WriteLine("\n To try again enter y");
string yes = Console.ReadLine();
Console.WriteLine("\n");
if (yes == "y")
{
while (n >= 1)
{
Console.Write(n + " Tries left");
n = --n;
goto label1;
}
}
}
}
Console.ReadKey();
}
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
demo obj = new demo();
string uname, pass;
boolean successful = false;
int32 tries = 5;
Console.ForegroundColor = ConsoleColor.Green;
label1:
Do
{
Console.Clear();
Console.WriteLine("Enter username");
uname = Console.ReadLine();
Console.WriteLine("Enter Password");
pass = Console.ReadLine();
obj.setName(uname);
obj.setPass(pass);
if (obj.getName() == "niit")
{
if (obj.getPass() == "1234")
{
Console.WriteLine("welcome");
successful = true;
}
}
if (!successful)
{
tries--;
Console.Clear();
Console.WriteLine("Invalid");
if (tries > 1)
{
Console.WriteLine("Have " + tries + " attempts left");
}
ElseIf (tries == 1)
{
Console.WriteLine("Have only one more attempt left");
}
Else
{
Console.WriteLine("Maximum number of tries exceed");
Console.WriteLine("Goodbye");
}
}
} While(!successful && Tries > 0);
}
}
Everytime you get the wrong input, you remaking your count int n = 5;
so everytime you have 5 tries left.
What you can do is to declare your count outside of the static void Main(string args[]) method
just like:
int n =5;
static void Main(string args[])
{
}
you problems are the following nested if-contitions
if (obj.getName() == "niit")
{
if (obj.getPass() == "1234")
{
Console.WriteLine("welcome");
}
}
else
{
\\...
}
If the username is correct and the pass not, it wont enter the else branch.
a better solution to ask for input until it is valid id a do ... while loop
Following example has a lot of improvements over yours.
static void Main(string[] args)
{
demo obj = new demo();
string uname, pass;
Console.ForegroundColor = ConsoleColor.Green;
int maxTries;
int tries = maxTries = 5;
do
{
if (tries != maxTries)//second and more
{
Console.Clear();
Console.WriteLine("Invalid");
Console.Write("\n\t" + tries + " Tries left");
Console.WriteLine("\n\n\n\tTry again? (y/n)");
string input;
do
{
input = Console.ReadLine();
} while (input != "y" && input != "n");
if (input == "n")
{
return; // exit the program
}
}
Console.Clear();
Console.WriteLine("Enter username");
uname = Console.ReadLine();
Console.WriteLine("Enter Password");
pass = Console.ReadLine();
obj.setName(uname);
obj.setPass(pass);
tries--;
} while (obj.getName() != "niit" || obj.getPass() != "1234");
Console.WriteLine("Wellcome");
}
PS: Classes should start with a capital letter.
goto is a relict of old times, it will mess with your programm structure and make things more complicated than they are. The only propper use i know is for fallthrough in switches, which also is needed only in rare cases.
A madeup one would be:
string vehicleType = "car";
switch(vehicleType)
{
case "truck":
Console.WriteLine("two wheeles and");
goto case "car";
case "car":
Console.WriteLine("two wheeles and");
goto case "motor cycle";
case "motor cycle":
Console.WriteLine("two wheeles");
break;
case "boat":
Console.WriteLine("no wheeles");
break;
}