Unexpected results for checking if a character is a symbol - c#

I am creating a string extension to check if a string is all symbols or not however it is not working as I would expect it to, so far I have the following:
// Class for: String extensions
public static class StringExtension
{
// Method for: Determining if a string contains only symbols
public static bool ContainsOnlySymbols(this String inputString)
{
// Identifiers used are:
bool containsMore = false;
// Go through the characters of the input string checking for symbols
foreach (char character in inputString.ToCharArray())
{
// This line needs || Char.IsPunctuation(character) also
// Credit: #asantaballa
containsMore = Char.IsSymbol(character) ? false : true;
if (containsMore)
{
return containsMore;
}
}
// Return the results
return containsMore; // Edited after answer: <-- mistake here
}
}
Now if I use this extension on the following two strings I get the opposite of what I expect to see:
string testString = "!=";
I expect this to be all symbols, but
I expect: testString.ContainsOnlySymbols() => true
I get: testString.ContainsOnlySymbols() => false
Now if I use the next test string:
string testString = "Starts with";
I expect this to have no symbols
I expect: testString.ContainsOnlySymbols() => false
I get: testString.ContainsOnlySymbols() => true

A couple problems:
In your loop, you are really only getting the option related to the last character. And or clause should take care of it.
containsMore = containsMore || !(Char.IsSymbol(character) || Char.IsPunctuation(character));
Then, you need a not at the end. If it doesn't contain more, then its only symbols
return ! containsMore;
You might want a special case for how to handle empty strings too. Not sure how you want to handle that. That will be your choice if an empty string should return true or false.
You can accomplish this with a one-liner. See these examples.
string x = "##=";
string z = "1234";
string w = "1234#";
bool b = Array.TrueForAll(x.ToCharArray(), y => (Char.IsSymbol(y) || Char.IsPunctuation(y))); // true
bool c = Array.TrueForAll(z.ToCharArray(), y => (Char.IsSymbol(y) || Char.IsPunctuation(y))); // false
bool e = Array.TrueForAll(w.ToCharArray(), y => (Char.IsSymbol(y) || Char.IsPunctuation(y))); // false

Checking all chars if all isSymbol or Punctuation. we return true here.
public static bool ContainsOnlySymbols(this String inputString)
{
return inputString.ToCharArray().All(x => Char.IsSymbol(x) || Char.IsPunctuation(x));
}
Test:
string testString = "Starts with"; // => false
string testString = "!="; // => true
string testString = "##"; // => true
string testString = "!Starts with"; // => false

I believe the IsSymbol method checks for a very specific set of character. You may want to do:
containsMore = (Char.IsSymbol(character) || Char.IsPunctuation(character)) ? false : true;
Wrote a quick program to show results for character and does show symptom. Might even be that all you need for your app is IsPunctuation.
33/!: IsSymbol=False, IsPunctuation=True
Program
using System;
namespace csharptestchis
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i <= 255; i++)
{
char ch = (char)i;
bool isSymbol = Char.IsSymbol(ch);
bool isPunctuation = Char.IsPunctuation(ch);
Console.WriteLine($"{i}/{ch}: IsSymbol={isSymbol}, IsPunctuation={isPunctuation} ");
}
}
}
}

Firstly, the idea is simple: you loop your string, if you meet a character non-symbol, return false. Until the end of string and you don't meet a character non-symbol. Voilà, return true.
public static bool ContainsOnlySymbols(string inputString)
{
// Identifiers used are:
bool containsMore = false;
// Go through the characters of the input string checking for symbols
foreach (char character in inputString)
{
containsMore = Char.IsSymbol(character) ? false : true;
if(!containsMore)
return false;
}
// Return the results
return true;
}
Secondly, there is a problem with your code, IsSymbol returns true only if your character is in these groups
MathSymbol, CurrencySymbol, ModifierSymbol, and OtherSymbol.
And fortunately, ! don't be in these groups. That means "!=" returns false.
So you must include others conditions like:
public static bool ContainsOnlySymbols(string inputString)
{
// Go through the characters of the input string checking for symbols
return inputString.All(c => Char.IsSymbol(c) || Char.IsPunctuation(c));
}
Or you have to write your own method to determine what symbol is acceptable and what is not.
Or if a string doesn't contain digit and letter, it can be considered symbol. You can do
public static bool ContainsOnlySymbols(string inputString)
{
// Go through the characters of the input string checking for symbols
return !inputString.Any(c => Char.IsLetterOrDigit(c));
}

Related

Why is this c# Palindrome Program not working?

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace Palindrome
{
class Program
{
static void Main(string[] args)
{
string filePath = #"C:\Users\Me\Desktop\Palindromes\palindromes.txt";
//This gets the file we need
var meStack = new Stack<string>();
//this creates the stack
foreach (var item in File.ReadLines(filePath))
{
meStack.Push(item.ToUpper());
}
//for every item in the file, push onto the stack and make it upper case
while (meStack.TryPop(out string Line))
{
reverseMe(Line);
}
//While every line in the stack is popped out, every line goes to the fucntion reverseMe
static bool reverseMe(string Line)
{
return
Line == Line.Reverse();
}
//return true if line is the same as the line backwards or false if its not.
}
}
}
How do I get output?
I have written comments to try and understand... but I am not getting a console output. I want the code to take in the file, put all the strings into a stack, and send every line in that stack to the reverseMe() function, which is a bool. The bool will see if the string is the same forward as it is backwards and if so it will return true or false. Basically my console is empty when I try to run this code.. What do I do?
There is a problem in the method reverseMe, The function Reverse gives you collection of char if applied on string, then you need to convert IEnumerable<char> to string by new string() or string.Concat(), like the following code:
static bool reverseMe(string Line)
{
//deleting whitespaces, tabs
Line = Regex.Replace(Line, #"\s+", "");
return Line == new string(Line.Reverse().ToArray());
//or
//return Line == string.Concat(Line.Reverse());
//or like Dmitry comment
//return Line.SequenceEqual(Line.Reverse());
}
Calling reverseMe, and output result like : word is not palindrome
while (meStack.TryPop(out string Line))
{
string isOrNotPalindrome = reverseMe(Line) ? string.Empty : "not";
Console.WriteLine($"{Line} is {isOrNotPalindrome} palindrome");
}
Demo
bool isPalindrome1 = reverseMe("madam");
bool isPalindrome2 = reverseMe("nurses run");
bool isPalindrome3 = reverseMe("AaBbbBaAp");
Result
true
true
false
I hope this will help you fix the issue
Let's start from the problem; I assume that you want to scan all file's lines and print out if the line is a palindrom.
First, we need to implement IsPalindrom method:
private static bool IsPalindrom(string value) {
if (null == value)
return false; // or true, ot throw ArgumentNullException
// We have to prepare the string: when testing for palindrom
// 1. Let's ignore white spaces (' ', '\r', '\t' etc.)
// 2. Let's ignore punctuation (':', ',' etc.)
// 3. Let's ignore cases (i.e. 'M' == 'm')
// So "Madam, I'm Adam" will be a proper palindrom
value = string.Concat(value
.Where(c => !char.IsWhiteSpace(c))
.Where(c => !char.IsPunctuation(c))
.Select(c => char.ToUpperInvariant(c)));
// Instead of Reversing we can just compare:
// [0] and [Length - 1] then [1] and [Length - 2] etc.
for (int i = 0; i < value.Length / 2; ++i)
if (value[i] != value[value.Length - 1 - i])
return false; // we have a counter example: value is NOT a palidrom
// Value has been scanned, no counter examples are found
return true;
}
Time to write Main method:
static void Main(string[] args) {
string filePath = #"C:\Users\Me\Desktop\Palindromes\palindromes.txt";
var result = File
.ReadLines(filePath)
.Where(line => !string.IsNullOrWhiteSpace(line)) // let's skip empty lines
.Select(line => $"{(IsPalindrom(line) ? "Palindrom" : "Not a palindrom")}: \"{line}\"");
// Do not forget to print result on the Console:
foreach (var record in result)
Console.WriteLine(record);
// Pause to have a look at the outcome (wait for a key to be pressed)
Console.ReadKey();
}
Uhm there isn't a Console.WriteLine() to do any actual output after getting results from the reverseMe() function.

Comparing two same string but returning false in C#. Don't know why????

public bool VerifyTextPresent(By by, String actual)
{
WaitUntilElementIsPresent(by);
String expected = GetText(by);
return expected.Equals(actual);
}
expected = "Total Win"
actual = "Total Win"
I used "Contains" method also but return false only.
Please help me out on this.
I got the thing like i ptrinted its ascii value and for actual space value is 160 and for expected space value is 32. But now how can i now move ahead??
One approach is to normalize your strings by replacing certain characters with a baseline. In your case you can replace non-breaking spaces with a "normal" space:
public bool VerifyTextPresent(By by, String actual)
{
WaitUntilElementIsPresent(by);
String expected = GetText(by);
if (expected.Equals(actual)) return true;
if (expected.Equals(Normalize(actual))) return true;
return false;
}
private string Normalize(string s)
{
// hard-code for now; could use a lookup table or other means to expand
s = s.Replace((char)160, (char)32);
// other replacements as necessary
return s;
}

Efficient way to Compare 2 strings for NULL or value and trim to compare if it's not NULL in C#

static void Main(string[] args)
{
string string1 = " "; // it can be NULL and any word too
string string2 = null; // it can be NULL and any word too
if (string.IsNullOrEmpty(string1))
{
if (string.IsNullOrEmpty(string2))
{
Console.WriteLine("Both the string Null & equal");
}
}
else
{
if (!string.IsNullOrEmpty(string2))
{
if(string1.Trim().Equals(string2.Trim(),StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("Both the string has value& equal");
}
}
}
}
This code checks for NULL or value of both the string ultimately to confirm both the string is same. Importantly it has to trim the white space to make it comparable and same time if the string is NULL then it can't be trimmed.
Going through all possible conditions, I have written this block of code and still believing someone can make it more efficient in terms of efficiency.
Thank you!
Assuming that you really meant to check for null rather than null or empty (according to your console comment), I'd implement the following method...
private bool checkEqualityWithTrim(string string1, string string2)
{
bool bothNull = string1 == null && string2 == null;
bool bothNonNullAndEqualTrimmed = string1 != null && string2 != null && string1.Trim() == string2.Trim();
return bothNull || bothNonNullAndEqualTrimmed;
}
Then you can just do...
var areEqual = checkEqualityWithTrim(string1, string2);
If the IsNullOrEmpty() was intentional, then just replace the bothNull line with
bool bothNull = string.IsNullOrEmpty(string1) && string.IsNullOrEmpty(string2);
Yeah, you're doing more checks than you need to do. If the strings are equal, you only need to check that one of the strings is null or whitespace. If so, you know the value in both strings. This works assuming that for you NULL and whitespace are equivalent.
public static void Main(string[] args)
{
string string1 = ""; // it can be NULL and any word too
string string2 = ""; // it can be NULL and any word too
if (String.Equals((string1 ?? "").Trim(), (string2 ?? "").Trim(),StringComparison.OrdinalIgnoreCase))
{
if (string.IsNullOrEmpty(string1)) //since the strings are equal, check one of the strings
{
Console.WriteLine("Both strings are null or empty & equal");
}
else
{
Console.WriteLine("Both strings have values & are equal");
}
}
}
Here is my attempt for you.
If this is something that is going to be used a lot then maybe using extension methods may be the way to go.
I have created two extension methods for you.
1 that performs a null and whitespace check (both conditions will be treated as a null
the second performs the logic you are after.
Here is my attempt for you:
public static bool IsNull(this string source)
{
return string.IsNullOrWhiteSpace(source);
}
public static string IsNullOrSame(this string source, string comparer)
{
//check for both values are null
if (source.IsNull() && comparer.IsNull())
{
return "Both Values Null or contain whitespace only";
}
//check if string 1 is null and string two has a value.
if (source.IsNull() && !comparer.IsNull())
{
return "I don't have a Value, but string 2 does";
}
//check if string 1 has a value and string two is null
if (!source.IsNull() && comparer.IsNull())
{
return "I have Value, but string 2 doesn't";
}
//if we make it this far then both have a value, check if the string value matches
if(source.Trim().Equals(comparer.Trim(), StringComparison.OrdinalIgnoreCase))
{
return "Both value match";
}
//if values don't match
return "strings both have values but don't match";
}
Once you have included these extension methods into your project you can do something simple like:
var string1 = "some value";
var string2 = null;
var result = string1.IsNullOrSame(string2);
Console.WriteLine(result);
this would then result in the message "I have Value, but string 2 doesn't"
The reason for the multiple return statements is one purely for readability. If we meet a "condition" then there is no point performing any more checking and the nesting of multiple if's can get a bit tiresome to debug.
Hopefully this gives you the desired functionality you are after and efficiency.
you are looking for simple and maintainable code not efficiency...
i would code it like that:
(edited: now with all possible conditions)
{
String string1 = "";
String string2 = "";
if (String.IsNullOrEmpty(string1.Trim()) && String.IsNullOrEmpty(string2.Trim()))
{
Console.WriteLine("Both the string Null & equal");
}
else if (!String.IsNullOrEmpty(string1.Trim()) && String.IsNullOrEmpty(string2.Trim()))
{
Console.WriteLine("String2 is null and string1 is not!");
}
else if (String.IsNullOrEmpty(string1.Trim()) && !String.IsNullOrEmpty(string2.Trim()))
{
Console.WriteLine("String1 is null and string2 is not!");
}
else {
if (string1.Trim().Equals( string2.Trim())) {
Console.WriteLine("both strings are not null and Equals!");
}
else {
Console.WriteLine("both strings are not null! and not Equals");
}
}
}
If you can use C# 6 I would definitely suggest you to use the Null Conditional Operator (called also the Elvis operator):
var test = "";
var test2 = "";
if (String.IsNullOrEmpty(test?.Trim()) && String.IsNullOrEmpty(test2?.Trim()))
{
Console.WriteLine("both strings are null or empty and equal");
}
else
{
Console.WriteLine("both strings have value and are equal");
}
Also depending on what the string " " (space) means for you (empty or value) use IsNullOrEmpty (in the case of value) or IsNullOrWhitespace (in the case of empty).

validation rule for only numbers to be entered [duplicate]

If I have these strings:
"abc" = false
"123" = true
"ab2" = false
Is there a command, like IsNumeric() or something else, that can identify if a string is a valid number?
int n;
bool isNumeric = int.TryParse("123", out n);
Update As of C# 7:
var isNumeric = int.TryParse("123", out int n);
or if you don't need the number you can discard the out parameter
var isNumeric = int.TryParse("123", out _);
The var s can be replaced by their respective types!
This will return true if input is all numbers. Don't know if it's any better than TryParse, but it will work.
Regex.IsMatch(input, #"^\d+$")
If you just want to know if it has one or more numbers mixed in with characters, leave off the ^ + and $.
Regex.IsMatch(input, #"\d")
Edit:
Actually I think it is better than TryParse because a very long string could potentially overflow TryParse.
You can also use:
using System.Linq;
stringTest.All(char.IsDigit);
It will return true for all Numeric Digits (not float) and false if input string is any sort of alphanumeric.
Test case
Return value
Test result
"1234"
true
✅Pass
"1"
true
✅Pass
"0"
true
✅Pass
""
true
⚠️Fail (known edge case)
"12.34"
false
✅Pass
"+1234"
false
✅Pass
"-13"
false
✅Pass
"3E14"
false
✅Pass
"0x10"
false
✅Pass
Please note: stringTest should not be an empty string as this would pass the test of being numeric.
I've used this function several times:
public static bool IsNumeric(object Expression)
{
double retNum;
bool isNum = Double.TryParse(Convert.ToString(Expression), System.Globalization.NumberStyles.Any, System.Globalization.NumberFormatInfo.InvariantInfo, out retNum);
return isNum;
}
But you can also use;
bool b1 = Microsoft.VisualBasic.Information.IsNumeric("1"); //true
bool b2 = Microsoft.VisualBasic.Information.IsNumeric("1aa"); // false
From Benchmarking IsNumeric Options
(source: aspalliance.com)
(source: aspalliance.com)
This is probably the best option in C#.
If you want to know if the string contains a whole number (integer):
string someString;
// ...
int myInt;
bool isNumerical = int.TryParse(someString, out myInt);
The TryParse method will try to convert the string to a number (integer) and if it succeeds it will return true and place the corresponding number in myInt. If it can't, it returns false.
Solutions using the int.Parse(someString) alternative shown in other responses works, but it is much slower because throwing exceptions is very expensive. TryParse(...) was added to the C# language in version 2, and until then you didn't have a choice. Now you do: you should therefore avoid the Parse() alternative.
If you want to accept decimal numbers, the decimal class also has a .TryParse(...) method. Replace int with decimal in the above discussion, and the same principles apply.
You can always use the built in TryParse methods for many datatypes to see if the string in question will pass.
Example.
decimal myDec;
var Result = decimal.TryParse("123", out myDec);
Result would then = True
decimal myDec;
var Result = decimal.TryParse("abc", out myDec);
Result would then = False
In case you don't want to use int.Parse or double.Parse, you can roll your own with something like this:
public static class Extensions
{
public static bool IsNumeric(this string s)
{
foreach (char c in s)
{
if (!char.IsDigit(c) && c != '.')
{
return false;
}
}
return true;
}
}
If you want to catch a broader spectrum of numbers, à la PHP's is_numeric, you can use the following:
// From PHP documentation for is_numeric
// (http://php.net/manual/en/function.is-numeric.php)
// Finds whether the given variable is numeric.
// Numeric strings consist of optional sign, any number of digits, optional decimal part and optional
// exponential part. Thus +0123.45e6 is a valid numeric value.
// Hexadecimal (e.g. 0xf4c3b00c), Binary (e.g. 0b10100111001), Octal (e.g. 0777) notation is allowed too but
// only without sign, decimal and exponential part.
static readonly Regex _isNumericRegex =
new Regex( "^(" +
/*Hex*/ #"0x[0-9a-f]+" + "|" +
/*Bin*/ #"0b[01]+" + "|" +
/*Oct*/ #"0[0-7]*" + "|" +
/*Dec*/ #"((?!0)|[-+]|(?=0+\.))(\d*\.)?\d+(e\d+)?" +
")$" );
static bool IsNumeric( string value )
{
return _isNumericRegex.IsMatch( value );
}
Unit Test:
static void IsNumericTest()
{
string[] l_unitTests = new string[] {
"123", /* TRUE */
"abc", /* FALSE */
"12.3", /* TRUE */
"+12.3", /* TRUE */
"-12.3", /* TRUE */
"1.23e2", /* TRUE */
"-1e23", /* TRUE */
"1.2ef", /* FALSE */
"0x0", /* TRUE */
"0xfff", /* TRUE */
"0xf1f", /* TRUE */
"0xf1g", /* FALSE */
"0123", /* TRUE */
"0999", /* FALSE (not octal) */
"+0999", /* TRUE (forced decimal) */
"0b0101", /* TRUE */
"0b0102" /* FALSE */
};
foreach ( string l_unitTest in l_unitTests )
Console.WriteLine( l_unitTest + " => " + IsNumeric( l_unitTest ).ToString() );
Console.ReadKey( true );
}
Keep in mind that just because a value is numeric doesn't mean it can be converted to a numeric type. For example, "999999999999999999999999999999.9999999999" is a perfeclty valid numeric value, but it won't fit into a .NET numeric type (not one defined in the standard library, that is).
I know this is an old thread, but none of the answers really did it for me - either inefficient, or not encapsulated for easy reuse. I also wanted to ensure it returned false if the string was empty or null. TryParse returns true in this case (an empty string does not cause an error when parsing as a number). So, here's my string extension method:
public static class Extensions
{
/// <summary>
/// Returns true if string is numeric and not empty or null or whitespace.
/// Determines if string is numeric by parsing as Double
/// </summary>
/// <param name="str"></param>
/// <param name="style">Optional style - defaults to NumberStyles.Number (leading and trailing whitespace, leading and trailing sign, decimal point and thousands separator) </param>
/// <param name="culture">Optional CultureInfo - defaults to InvariantCulture</param>
/// <returns></returns>
public static bool IsNumeric(this string str, NumberStyles style = NumberStyles.Number,
CultureInfo culture = null)
{
double num;
if (culture == null) culture = CultureInfo.InvariantCulture;
return Double.TryParse(str, style, culture, out num) && !String.IsNullOrWhiteSpace(str);
}
}
Simple to use:
var mystring = "1234.56789";
var test = mystring.IsNumeric();
Or, if you want to test other types of number, you can specify the 'style'.
So, to convert a number with an Exponent, you could use:
var mystring = "5.2453232E6";
var test = mystring.IsNumeric(style: NumberStyles.AllowExponent);
Or to test a potential Hex string, you could use:
var mystring = "0xF67AB2";
var test = mystring.IsNumeric(style: NumberStyles.HexNumber)
The optional 'culture' parameter can be used in much the same way.
It is limited by not being able to convert strings that are too big to be contained in a double, but that is a limited requirement and I think if you are working with numbers larger than this, then you'll probably need additional specialised number handling functions anyway.
UPDATE of Kunal Noel Answer
stringTest.All(char.IsDigit);
// This returns true if all characters of the string are digits.
But, for this case we have that empty strings will pass that test, so, you can:
if (!string.IsNullOrEmpty(stringTest) && stringTest.All(char.IsDigit)){
// Do your logic here
}
You can use TryParse to determine if the string can be parsed into an integer.
int i;
bool bNum = int.TryParse(str, out i);
The boolean will tell you if it worked or not.
If you want to know if a string is a number, you could always try parsing it:
var numberString = "123";
int number;
int.TryParse(numberString , out number);
Note that TryParse returns a bool, which you can use to check if your parsing succeeded.
I guess this answer will just be lost in between all the other ones, but anyway, here goes.
I ended up on this question via Google because I wanted to check if a string was numeric so that I could just use double.Parse("123") instead of the TryParse() method.
Why? Because it's annoying to have to declare an out variable and check the result of TryParse() before you know if the parse failed or not. I want to use the ternary operator to check if the string is numerical and then just parse it in the first ternary expression or provide a default value in the second ternary expression.
Like this:
var doubleValue = IsNumeric(numberAsString) ? double.Parse(numberAsString) : 0;
It's just a lot cleaner than:
var doubleValue = 0;
if (double.TryParse(numberAsString, out doubleValue)) {
//whatever you want to do with doubleValue
}
I made a couple extension methods for these cases:
Extension method one
public static bool IsParseableAs<TInput>(this string value) {
var type = typeof(TInput);
var tryParseMethod = type.GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder,
new[] { typeof(string), type.MakeByRefType() }, null);
if (tryParseMethod == null) return false;
var arguments = new[] { value, Activator.CreateInstance(type) };
return (bool) tryParseMethod.Invoke(null, arguments);
}
Example:
"123".IsParseableAs<double>() ? double.Parse(sNumber) : 0;
Because IsParseableAs() tries to parse the string as the appropriate type instead of just checking if the string is "numeric" it should be pretty safe. And you can even use it for non numeric types that have a TryParse() method, like DateTime.
The method uses reflection and you end up calling the TryParse() method twice which, of course, isn't as efficient, but not everything has to be fully optimized, sometimes convenience is just more important.
This method can also be used to easily parse a list of numeric strings into a list of double or some other type with a default value without having to catch any exceptions:
var sNumbers = new[] {"10", "20", "30"};
var dValues = sNumbers.Select(s => s.IsParseableAs<double>() ? double.Parse(s) : 0);
Extension method two
public static TOutput ParseAs<TOutput>(this string value, TOutput defaultValue) {
var type = typeof(TOutput);
var tryParseMethod = type.GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder,
new[] { typeof(string), type.MakeByRefType() }, null);
if (tryParseMethod == null) return defaultValue;
var arguments = new object[] { value, null };
return ((bool) tryParseMethod.Invoke(null, arguments)) ? (TOutput) arguments[1] : defaultValue;
}
This extension method lets you parse a string as any type that has a TryParse() method and it also lets you specify a default value to return if the conversion fails.
This is better than using the ternary operator with the extension method above as it only does the conversion once. It still uses reflection though...
Examples:
"123".ParseAs<int>(10);
"abc".ParseAs<int>(25);
"123,78".ParseAs<double>(10);
"abc".ParseAs<double>(107.4);
"2014-10-28".ParseAs<DateTime>(DateTime.MinValue);
"monday".ParseAs<DateTime>(DateTime.MinValue);
Outputs:
123
25
123,78
107,4
28.10.2014 00:00:00
01.01.0001 00:00:00
If you want to check if a string is a number (I'm assuming it's a string since if it's a number, duh, you know it's one).
Without regex and
using Microsoft's code as much as possible
you could also do:
public static bool IsNumber(this string aNumber)
{
BigInteger temp_big_int;
var is_number = BigInteger.TryParse(aNumber, out temp_big_int);
return is_number;
}
This will take care of the usual nasties:
Minus (-) or Plus (+) in the beginning
contains decimal character BigIntegers won't parse numbers with decimal points. (So: BigInteger.Parse("3.3") will throw an exception, and TryParse for the same will return false)
no funny non-digits
covers cases where the number is bigger than the usual use of Double.TryParse
You'll have to add a reference to System.Numerics and have
using System.Numerics; on top of your class (well, the second is a bonus I guess :)
Double.TryParse
bool Double.TryParse(string s, out double result)
The best flexible solution with .net built-in function called- char.IsDigit. It works with unlimited long numbers. It will only return true if each character is a numeric number. I used it lot of times with no issues and much easily cleaner solution I ever found. I made a example method.Its ready to use. In addition I added validation for null and empty input. So the method is now totally bulletproof
public static bool IsNumeric(string strNumber)
{
if (string.IsNullOrEmpty(strNumber))
{
return false;
}
else
{
int numberOfChar = strNumber.Count();
if (numberOfChar > 0)
{
bool r = strNumber.All(char.IsDigit);
return r;
}
else
{
return false;
}
}
}
Try the regex define below
new Regex(#"^\d{4}").IsMatch("6") // false
new Regex(#"^\d{4}").IsMatch("68ab") // false
new Regex(#"^\d{4}").IsMatch("1111abcdefg")
new Regex(#"^\d+").IsMatch("6") // true (any length but at least one digit)
With c# 7 it you can inline the out variable:
if(int.TryParse(str, out int v))
{
}
Use these extension methods to clearly distinguish between a check if the string is numerical and if the string only contains 0-9 digits
public static class ExtensionMethods
{
/// <summary>
/// Returns true if string could represent a valid number, including decimals and local culture symbols
/// </summary>
public static bool IsNumeric(this string s)
{
decimal d;
return decimal.TryParse(s, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.CurrentCulture, out d);
}
/// <summary>
/// Returns true only if string is wholy comprised of numerical digits
/// </summary>
public static bool IsNumbersOnly(this string s)
{
if (s == null || s == string.Empty)
return false;
foreach (char c in s)
{
if (c < '0' || c > '9') // Avoid using .IsDigit or .IsNumeric as they will return true for other characters
return false;
}
return true;
}
}
public static bool IsNumeric(this string input)
{
int n;
if (!string.IsNullOrEmpty(input)) //.Replace('.',null).Replace(',',null)
{
foreach (var i in input)
{
if (!int.TryParse(i.ToString(), out n))
{
return false;
}
}
return true;
}
return false;
}
Regex rx = new Regex(#"^([1-9]\d*(\.)\d*|0?(\.)\d*[1-9]\d*|[1-9]\d*)$");
string text = "12.0";
var result = rx.IsMatch(text);
Console.WriteLine(result);
To check string is uint, ulong or contains only digits one .(dot) and digits
Sample inputs
123 => True
123.1 => True
0.123 => True
.123 => True
0.2 => True
3452.434.43=> False
2342f43.34 => False
svasad.324 => False
3215.afa => False
Hope this helps
string myString = "abc";
double num;
bool isNumber = double.TryParse(myString , out num);
if isNumber
{
//string is number
}
else
{
//string is not a number
}
Pull in a reference to Visual Basic in your project and use its Information.IsNumeric method such as shown below and be able to capture floats as well as integers unlike the answer above which only catches ints.
// Using Microsoft.VisualBasic;
var txt = "ABCDEFG";
if (Information.IsNumeric(txt))
Console.WriteLine ("Numeric");
IsNumeric("12.3"); // true
IsNumeric("1"); // true
IsNumeric("abc"); // false
All the Answers are Useful. But while searching for a solution where the Numeric value is 12 digits or more (in my case), then while debugging, I found the following solution useful :
double tempInt = 0;
bool result = double.TryParse("Your_12_Digit_Or_more_StringValue", out tempInt);
Th result variable will give you true or false.
Here is the C# method.
Int.TryParse Method (String, Int32)
bool is_number(string str, char delimiter = '.')
{
if(str.Length==0) //Empty
{
return false;
}
bool is_delimetered = false;
foreach (char c in str)
{
if ((c < '0' || c > '9') && (c != delimiter)) //ASCII table check. Not a digit && not delimeter
{
return false;
}
if (c == delimiter)
{
if (is_delimetered) //more than 1 delimiter
{
return false;
}
else //first time delimiter
{
is_delimetered = true;
}
}
}
return true;
}

Issue with LINQ SequenceEquals extension in C#

I was trying out possibilities to check a string to be an palindrome with the following logic
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Anagram solver");
Console.WriteLine(IsPalindrome("HIMA", "AMHI").ToString());
Console.ReadKey();
}
static bool IsPalindrome(string s1, string s2)
{
return s1.OrderBy(c => c).SequenceEqual(s2.OrderBy(c => c));
}
}
My idea was to get character literals in a string, and compare with that of characters from another string to deduce for a possible palindrome. Is such a thing possible with LINQ SequenceEqual method ?
Looking from the sample above,
'H' shall be compared with 'A' (default equality comparison)
'I' shall be compared with 'M'
'M' shall be compared with 'H'
'A' shall be compared with 'I'
Can any one guide me here.
Thanks and Cheers
Srivatsa
If you want palindrome then you should not order them, just reverse and match -
static bool IsPalindrome(string s1, string s2)
{
return s1.SequenceEqual(s2.Reverse());
}
for case-insensitivity try -
static bool IsPalindrome(string s1, string s2)
{
return s1.ToLower().SequenceEqual(s2.ToLower().Reverse());
}
In your case, "HIMA" and "AMHI" are sorted by the OrderBy LINQ function, which results in two collections containing the characters "AHIM". If you call SequenceEqual this returns true.
For SequenceEqual to return true, both collections have to have the same amount of elements in exactly the same order. No elements are allowed to be duplicated or stored at another position.
If you want to determine if two words are anagrams, that is exactly the functionality you want.
For palindromes, you could use the following:
public bool CheckPalindrome(string first, string second)
{
if (first == null) throw new ArgumentNullException("first");
if (second == null) throw new ArgumentNullExcpetion("second");
return first.Reverse().SequenceEquals(second);
}
You could use this method:
public static bool IsPalindromWith(this string str1, string str2)
{
if(str1 == null || str2 == null) return false;
return str1.SequenceEqual(str2.Reverse());
}
Usage: bool isPalindrom = "HIMA".IsPalindromWith("AMIH");
However, it is a very simple approach which ignores many edge cases.
Here is a better version that takes at least the case into account:
public static bool IsPalindromWith(this string str1, string str2, StringComparison comparison = StringComparison.CurrentCultureIgnoreCase)
{
if(str1 == null || str2 == null) return false;
char[] str2Chars = str2.ToCharArray();
Array.Reverse(str2Chars);
return str1.Equals(new String(str2Chars), comparison);
}
To elaburate on the existing (and i my opinion corrent) answer by #feO2x
Try looking at it like this:
static bool IsAnagram(string s1, string s2)
{
var lst1 = s1.OrderBy(c => c); //will result in { 'A','H','I', 'M' }
var lst2 = s2.OrderBy(c => c); //will *also* result in { 'A','H','I', 'M' }
return lst1.SequenceEqual(lst2);
}
The OrderBy(...) destroys the original order which you are trying to test.
Simply removing them will solve your problem:
static bool IsAnagram(string s1, string s2)
{
var lst1 = s1.AsEnumerable();
var lst2 = s2.AsEnumerable();
return lst1.SequenceEqual(lst2);
}

Categories

Resources