I have this code to validate a phone number but it looks a bit awkward. I'm guessing theres a better way to go about this. How can I make this more efficient?
public static bool validTelephoneNo(string telNo)
{
bool condition = false;
while (condition == false)
{
Console.WriteLine("Enter a phone number.");
telNo = Console.ReadLine();
if (telNo.Length > 8)
{
if (telNo.StartsWith("+") == true)
{
char[] arr = telNo.ToCharArray();
for (int a = 1; a < telNo.Length; a++)
{
int temp;
try
{
temp = arr[a];
}
catch
{
break;
}
if (a == telNo.Length - 1)
{
condition = true;
}
}
}
}
}
return true;
}
Don't try and do this yourself, use a library where someone has already done the hard work for you, such as libphonenumber.
Example:
public static bool validTelephoneNo(string telNo)
{
PhoneNumber number;
try
{
number = PhoneNumberUtil.Instance.Parse(telNo, "US"); // Change to your default language, international numbers will still be recognised.
}
catch (NumberParseException e)
{
return false;
}
return number.IsValidNumber;
}
This library will handle parsing and formatting phone numbers from different countries. Not only will this ensure that the number is valid in the relevant country, it will also allow you to filter out premium numbers and "fake" numbers (such as 555 in the US).
Your goal can be easily achieved using regular expressions:
public static bool validTelephoneNo(string telNo)
{
return Regex.Match(telNo, #"^\+\d{1,7}$").Success;
}
This pattern is exactly as stated: consists of integers, is less than 8 digits in length and has a plus at the start, and also this pattern can be modified if conditions somehow more complex.
try
Console.WriteLine("Enter a phone number.");
bool isValid = new System.Text.RegularExpressions.Regex(#"^[+]\d{1,7}$").IsMatch(Console.ReadLine());
Where the regex checks whether there is only a single number (1 to 7 digits) with + in front of them read. The drawback, this way you cannot further processed, you might need to read the line from console to a new variable.
Related
Firstly I understand that there are several ways to do this and I do have some code which runs, but what I just wanted to find out was if anyone else has a recommended way to do this. Say I have a string which I already know that would have contain a specific character (a ‘,’ in this case). Now I just want to validate that this comma is used only once and not more. I know iterating through each character is an option but why go through all that work because I just want to make sure that this special character is not used more than once, I’m not exactly interested in the count per se. The best I could think was to use the split and here is some sample code that works. Just curious to find out if there is a better way to do this.
In summary,
I have a certain string in which I know has a special character (‘,’ in this case)
I want to validate that this special character has only been used once in this string
const char characterToBeEvaluated = ',';
string myStringToBeTested = "HelloWorldLetus,code";
var countOfIdentifiedCharacter = myStringToBeTested.Split(characterToBeEvaluated).Length - 1;
if (countOfIdentifiedCharacter == 1)
{
Console.WriteLine("Used exactly once as expected");
}
else
{
Console.WriteLine("Used either less than or more than once");
}
You can use string's IndexOf methods:
const char characterToBeEvaluated = ',';
string myStringToBeTested = "HelloWorldLetus,code";
string substringToFind = characterToBeEvaluated.ToString();
int firstIdx = myStringToBeTested.IndexOf(substringToFind, StringComparison.Ordinal);
bool foundOnce = firstIdx >= 0;
bool foundTwice = foundOnce && myStringToBeTested.IndexOf(substringToFind, firstIdx + 1, StringComparison.Ordinal) >= 0;
Try it online
You could use the LINQ Count() method:
const char characterToBeEvaluated = ',';
string myStringToBeTested = "HelloWorldLetus,code";
var countOfIdentifiedCharacter = myStringToBeTested.Count(x => x == characterToBeEvaluated);
if (countOfIdentifiedCharacter == 1)
{
Console.WriteLine("Used exactly once as expected");
}
else
{
Console.WriteLine("Used either less than or more than once");
}
This is the most readable and simplest approach and is great if you need to know the exact count but for your specific case #ProgrammingLlama's answer is better in terms of efficiency.
Adding another answer using a custom method:
public static void Main()
{
const char characterToBeEvaluated = ',';
string myStringToBeTested = "HelloWorldLetus,code";
var characterAppearsOnlyOnce = DoesCharacterAppearOnlyOnce(characterToBeEvaluated, myStringToBeTested);
if (characterAppearsOnlyOnce)
{
Console.WriteLine("Used exactly once as expected");
}
else
{
Console.WriteLine("Used either less than or more than once");
}
}
public static bool DoesCharacterAppearOnlyOnce(char characterToBeEvaluated, string stringToBeTested)
{
int count = 0;
for (int i = 0; i < stringToBeTested.Length && count < 2; ++i)
{
if (stringToBeTested[i] == characterToBeEvaluated)
{
++count;
}
}
return count == 1;
}
The custom method DoesCharacterAppearOnlyOnce() performs better than the method using IndexOf() for smaller strings - probably due to the overhead calling IndexOf. As the strings get larger the IndexOf method is better.
I want to ask the user to input a number including an if statement option were if he puts letters the last question will be asked again
I've tried this but seemingly it work only for strings
Console.Write("Write a number:");
int num = Convert.ToInt32(Console.ReadLine());
if (!int.TryParse(age, out num))
while(!int.TryParse(age, out num))
{
Console.WriteLine(...);
// ....
}
Let's extract method for this: we are going to ask user to input valid value until he or she provides it. So we have a loop:
private static int ReadInteger(string question) {
// Keep asking...
while (true) {
if (!string.IsNullOrWhiteSpace(question))
Console.WriteLine(question);
// ... until valid value provided
if (int.TryParse(Console.ReadLine(), out int result))
return result;
Console.WriteLine($"Sorry, not a valid integer value; please, try again.");
}
}
Then you can use it as
int age = ReadInteger("Please, input age");
I have a function that I'm using in my current project that might help you out, it just checks if the input string only contains numbers:
bool isDigitsOnly(string inputString)
{
foreach (char c in inputString)
{
if (c < '0' || c > '9')
return false;
}
return true;
}
You might have to modify it a little bit to fit your needs, but it should work well enough
This question already has answers here:
Parse v. TryParse
(8 answers)
Closed 5 years ago.
I'm trying to handle an exception to avoid my program crash if double.Parse(string) tries parsing invalid values (such as strings instead of numbers). Here's what I've got:
do
{
//asking customer the amount of shirts he would like to buy any shirts they want.
numbershirtString = Console.ReadLine(); // customer types in amount of shirts they want.
numbershirts = double.Parse(numbershirtString);
keepLooping = true;
if (numbershirts < 10)
{
Console.WriteLine("You would be buying " + numbershirts + " shirts");
keepLooping = false;
}
if (numbershirts > 10)
{
Console.WriteLine("You cannot order more than 10 shirts. Please try again.");
keepLooping = true;
}
} while (keepLooping);
I would appreciate your help. Thank you in advance!
Use double.TryParse() instead. It returns true of false depending on the outcome:
double val;
bool success = double.TryParse("red", out val);
if(success)
{
// val contains a parsed value
}
else
{
// could not parse
}
To handle an exception, in C# like similar in other languages, you can use the try..catch block.
Look at the simplest syntax:
try
{
//Try to run some code.
}
catch
{
//Do something if anything excepted.
}
If you're interested to retrieve which exception breaked the code:
try
{
//Try to run some code.
}
catch (Exception ex)
{
//Do something ex was thrown.
}
If you change the type of ex to something inheriting the base class Exception you'll handle only all the exception of that type:
try
{
//Try to run some code.
}
catch (StackOverflowException ex)
{
//Do something ex was thrown because you overflowed the stack.
}
But instead of talking about try..catch block which you can find out more about on Google, I suggest you to use the method double.TryParse(string, out double).
Its syntax is a little bit different than double.Parse, but effectively it does the same in a different way.
It returns true if your input is valid, else it returns false, whereas in the first parameter you have just to pass your string input and in the second one is required an output reference to the result variable:
double x = 0;
string number = "125.3";
if (double.TryParse(number, out x))
Console.WriteLine("Your number is " + x.ToString());
else
Console.WriteLine("Your input isn't valid");
Maybe this is a little advanced for you, but if you are feeling in a clever mood, you can define a class that handles the parsing of user input. That way you can keep that logic separated from your main program (see separation of concerns).
public class UserEntry
{
private readonly string _originalValue;
public UserEntry(string input)
{
_originalValue = input;
}
public bool IsInt
{
get
{
return int.TryParse(_originalValue, out var dummy);
}
}
public int ToInt()
{
return ToInt(default(int));
}
public int ToInt(int defaultValue)
{
int result;
bool ok = int.TryParse(_originalValue, out result);
return ok ? result : defaultValue;
}
public override string ToString()
{
return _originalValue;
}
static public implicit operator UserEntry(string input)
{
return new UserEntry(input);
}
static public implicit operator Int32(UserEntry input)
{
return input.ToInt();
}
}
If we use implicit conversion operators it makes things very simple. For example, all of these are now legal:
UserEntry entry = Console.ReadLine();
if (!entry.IsInt) continue;
if (entry < 10) return entry;
If we apply this to your example, it shortens your code a bit, and arguably makes it a bit clearer as well.
public class Program
{
private const int MaximumOrder = 10;
public static void Main()
{
var n = AskForNumberOfShirts();
Console.WriteLine("OK, I'll order {0} shirts.", n);
}
public static int AskForNumberOfShirts()
{
while (true)
{
Console.WriteLine("Enter the number of shirts to order:");
UserEntry entry = Console.ReadLine();
if (!entry.IsInt)
{
Console.WriteLine("You entered an invalid number.");
continue;
}
if (entry > MaximumOrder)
{
Console.WriteLine("{0} is too many! Please enter {1} or fewer.", entry, MaximumOrder);
continue;
}
return entry;
}
}
}
Notes:
I doubt you can order half a shirt, so I am using an int instead of a double to store the number of shirts.
I refactored the logic branches to use opportunistic return, a.ka. Guard Pattern. See this article for why I do this.
I extracted the constant value 10 to its own symbol, MaximumOrder. This should get you a couple points on the assignment.
Output:
Enter the number of shirts to order:
22
22 is too many! Please enter 10 or fewer.
Enter the number of shirts to order:
sdlfkj
You entered an invalid number.
Enter the number of shirts to order:
9
OK, I'll order 9 shirts.
Working example on DotNetFiddle
I just want to know, whether a String variable contains a parsable positive integer value. I do NOT want to parse the value right now.
Currently I am doing:
int parsedId;
if (
(String.IsNullOrEmpty(myStringVariable) ||
(!uint.TryParse(myStringVariable, out parsedId))
)
{//..show error message}
This is ugly - How to be more concise?
Note: I know about extension methods, but I wonder if there is something built-in.
You could use char.IsDigit:
bool isIntString = "your string".All(char.IsDigit)
Will return true if the string is a number
bool containsInt = "your string".Any(char.IsDigit)
Will return true if the string contains a digit
Assuming you want to check that all characters in the string are digits, you could use the Enumerable.All Extension Method with the Char.IsDigit Method as follows:
bool allCharactersInStringAreDigits = myStringVariable.All(char.IsDigit);
Maybe this can help
string input = "hello123world";
bool isDigitPresent = input.Any(c => char.IsDigit(c));
answer from msdn.
You can check if string contains numbers only:
Regex.IsMatch(myStringVariable, #"^-?\d+$")
But number can be bigger than Int32.MaxValue or less than Int32.MinValue - you should keep that in mind.
Another option - create extension method and move ugly code there:
public static bool IsInteger(this string s)
{
if (String.IsNullOrEmpty(s))
return false;
int i;
return Int32.TryParse(s, out i);
}
That will make your code more clean:
if (myStringVariable.IsInteger())
// ...
This work for me.
("your string goes here").All(char.IsDigit)
Sorry, didn't quite get your question. So something like this?
str.ToCharArray().Any(char.IsDigit);
Or does the value have to be an integer completely, without any additional strings?
if(str.ToCharArray().All(char.IsDigit(c));
string text = Console.ReadLine();
bool isNumber = false;
for (int i = 0; i < text.Length; i++)
{
if (char.IsDigit(text[i]))
{
isNumber = true;
break;
}
}
if (isNumber)
{
Console.WriteLine("Text contains number.");
}
else
{
Console.WriteLine("Text doesn't contain number.");
}
Console.ReadKey();
Or Linq:
string text = Console.ReadLine();
bool isNumberOccurance =text.Any(letter => char.IsDigit(letter));
Console.WriteLine("{0}",isDigitPresent ? "Text contains number." : "Text doesn't contain number.");
Console.ReadKey();
The answer seems to be just no.
Although there are many good other answers, they either just hide the uglyness (which I did not ask for) or introduce new problems (edge cases).
I'm writing some error checking and trying to make use of an boolean array to store true or false in the elements and then my final condition parses through the stored elements to determine if its all true in visual studio 2008. Theres probably a easier way to do the error checking, but might as well learn how to utilize an array. Here's what I have so far
bool[] checker = new bool[1]; // declared array...I think
private void print_button_Click(object sender, EventArgs e)
{
if (authorbox.Text == "")
{
MessageBox.Show("Author field empty", "Required Entry");
}
else
{
checker[0] = true; // assigning element to array correctly?
}
if (titlebox.Text == "")
{
MessageBox.Show("Title field Empty", "Required Entry");
}
else
{
checker[1] = true;
}
// The part I am having trouble with basically if any of my array elements are
// false don't execute printing. Else go ahead and print.
if ()
{
}
else
{
printPreviewDialog1.Document = printDocument1;
printPreviewDialog1.ShowDialog();
}
}
If you are using .NET 3.5 you can use Any and All to see if any of the booleans are true, or if all of them are true:
if (checker.Any(x => x))
or:
if (checker.All(x => x))
Also, if you want an array of two booleans, you should use new bool[2] not new bool[1]. It would be easier to use a List<bool> though.
instead of using the array it would be much easier to simply exit the method as soon as an error is detected:
private void print_button_Click(object sender, EventArgs e) {
if (authorbox.Text == "") {
MessageBox.Show("Author field empty", "Required Entry");
return;
}
if (titlebox.Text == "") {
MessageBox.Show("Title field Empty", "Required Entry");
return;
}
printPreviewDialog1.Document = printDocument1;
printPreviewDialog1.ShowDialog();
}
Well this is not the ideal way for error handling but you can use the .Contains() Method.
if (checker.Contains(false))
{
// Do Something
}
else
{
printPreviewDialog1.Document = printDocument1;
printPreviewDialog1.ShowDialog();
}
Apart from other things, you should say
bool[] checker = new bool[2];
if you want an array consisting of 2 elements ;) In this particular case the array doesn't seem to make too much sense, because it obfuscates things a little bit. You could do the same thing with just one boolean variable.
Using boolean arrays to accumulate a single go/no-go value is overkill. There are more useful things you could play with to get the hang of arrays.
You're better off simply ANDing the results of your intermediate checks into a value and then checking that for true/false:
public bool CheckControls()
{
bool pass = true;
pass &= !string.IsNullOrEmpty(authorbox.Text));
pass &= !string.IsNullOrEmpty(titlebox.Text));
// if any of these are empty then pass is to false and stays that way.
return pass;
}
If you need to keep track of which intermediate test failed, then consider using an integer and predefined constants of powers of two. Here you instead check for zero if all is well. This allows you to mask against the returned value and accumulate any combination of test results. As long as you have less than 32 (or 64) tests.
int AUTHORBOX = 2;
int TITLEBOX = 4;
int ISBNBOX = 8;
int PRICEBOX = 16;
public int AlternateCheck()
{
int temp = 0;
temp += string.IsNullOrEmpty(authorbox.Text) ? AUTHORBOX : 0;
temp += string.IsNullOrEmpty(titlebox.Text) ? TITLEBOX : 0;
temp += string.IsNullOrEmpty(isbnbox.Text) ? ISBNBOX : 0;
temp += string.IsNullOrEmpty(pricebox.Text) ? PRICEBOX : 0;
return temp;
}
I'm pretty sure the Contains method suggested by NebuSoft is a LINQ extension and therefore not available in .NET 2.0. You could however use the Array.IndexOf<T> method, like this:
if (Array.IndexOf<bool>(checker, false) != -1)
{
// some element in the array is false
}
else
{
// no false in the array
}
However, NebuSoft is right in asserting that this isn't the best approach. If you're curious to know more, I'll be happy to discuss it further.