I have to check if all the letters are capital letters in recursion, and i dont know why this isnt working:
public static bool IsCapital(string str)
{
if (str.Length == 1)
return int.Parse(str[0].ToString()) > 65 && int.Parse(str[0].ToString()) < 90;
return IsCapital(str.Substring(1)) && int.Parse(str[0].ToString()) > 65 && int.Parse(str[0].ToString()) < 90;
}
It crashes and says: "Unhandled exception: System.FormatException: Input string was not in a correct format."
Console.WriteLine(IsCapital("abc"));
thanks.
To solely address the exception, just don't parse strings. You can directly compare a char to any ushort value.
In other words, this is a valid check (without string parsing)
str[0] > 65
AsciiTable.com should show you why the checks you have will fail on the edges.
Also consider...
Characters that aren't letters.
IsCapital(null)
Finally, something that might make this easier (assuming non-letters get bypassed) is to create a method along the lines of bool IsNotLowerCase(char c).
Note -- these are all assuming ASCII, as evident by my link.
If you must support full Unicode, hopefully you can use the methods of char.
You're attempting to parse a char as an int, instead of casting it to an int.
What you're doing is taking a letter, such as A, and parsing that as an int. A isn't a number in any way, and therefore the parse fails.
What you'll want to do is explicitly cast the char as an int to get the ASCII value you're looking for:
if (str.Length == 1)
{
return ((int)str[0]) > 65
&& ((int)str[0]) < 90;
}
return IsCapital(str.Substring(1))
&& ((int)str[0]) > 65
&& ((int)str[0]) < 90;
I assume what you're trying to do with int.Parse(str[0].ToString()) is to get the ASCII value.
What you need to use instead is this (int)str[0]
A parse will try to translate the string into a number, so a string that has a value of '412' will get parsed into an int of value 412.
I have to check if all the letters are capital letters in recursion
public static bool IsCapital(string str)
{
if (String.IsNullOrEmpty(str)) return false;
if (str.Length == 1 && char.IsUpper(str[0])) return true;
return char.IsUpper(str[0]) ? IsCapital(str.Substring(1)) :false;
}
I thinks, that number comparison will not work.
First it will return false for string like this "ABC123" even if all letters are capitals. And second there are many national characters that does not fall into range 65..90 even if they are capitals. You should (if you can) use some Char method
http://msdn.microsoft.com/en-us/library/d1x97616.aspx
While there are many ways to skin this cat, I prefer to wrap such code into reusable extension methods that make it trivial to do going forward. When using extension methods, you can also avoid RegEx as it is slower than a direct character check. I like using the extensions in the Extensions.cs NuGet package. It makes this check as simple as:
Add the [https://www.nuget.org/packages/Extensions.cs][1] package to your project.
Add "using Extensions;" to the top of your code.
"smith".IsUpper() will return False whereas "SMITH".IsUpper() will return True. 4. Every other check in the rest of the code is simply MyString.IsUpper().
Your example code would become as simple as:
using Extensions;
//Console.WriteLine(IsCapital("abc"));
Console.WriteLine("abc".IsUpper());
public static bool IsCapital(string str)
{
return !Regex.IsMatch(str, "[a..z]");
}
Related
I have a rather complex issue that I'am unable to figure out.
I'm getting a set of string every 10 seconds from another process in which the first set has first 5 characters constant, next 3 are variable and can change. And then another set of string in which first 3 are variable and next 3 are constant.
I want to compare these values to a fixed string to check if the first 5 char matches in 1st set of string (ABCDE*** == ABCDEFGH) and ignore the last 3 variable characters while making sure the length is the same. Eg : if (ABCDE*** == ABCDEDEF) then condition is true, but if (ABCDE*** == ABCDDEFG) then the condition is false because the first 5 char is not same, also if (ABCDE*** == ABCDEFV) the condition should be false as one char is missing.
I'm using the * in fixed string to try to make the length same while comparing.
Does this solve your requirements?
private static bool MatchesPattern(string input)
{
const string fixedString = "ABCDExyz";
return fixedString.Length == input.Length && fixedString.Substring(0, 5).Equals(input.Substring(0, 5));
}
In last versions of C# you can also use ranges:
private static bool MatchesPattern(string input)
{
const string fixedString = "ABCDExyz";
return fixedString.Length == input.Length && fixedString[..5].Equals(input[..5]);
}
See this fiddle.
BTW: You could probably achieve the same using regex.
It's always a good idea to make an abstraction. Here I've made a simple function that takes the pattern and the value and makes a check:
bool PatternMatches(string pattern, string value)
{
// The null string doesn't match any pattern
if (value == null)
{
return false;
}
// If the value has a different length than the pattern, it doesn't match.
if (pattern.Length != value.Length)
{
return false;
}
// If both strings are zero-length, it's considered a match
bool result = true;
// Check every character against the pattern
for (int i = 0; i< pattern.Length; i++)
{
// Logical and the result, * matches everything
result&= (pattern[i]== '*') ? true: value[i] == pattern[i];
}
return result;
}
You can then call it like this:
bool b1 = PatternMatches("ABCDE***", "ABCDEFGH");
bool b2 = PatternMatches("ABC***", "ABCDEF");
You could use regular expressions, but this is fairly readable, RegExes aren't always.
Here is a link to a dotnetfiddle: https://dotnetfiddle.net/4x1U1E
If the string you match against is known at compile time, your best bet is probably using regular expressions. In the first case, match against ^ABCDE...$. In the second case, match against ^...DEF$.
Another way, probably better if the match string is unknown, uses Length, StartsWith and EndsWith:
String prefix = "ABCDE";
if (str.Length == 8 && str.StartsWith(prefix)) {
// do something
}
Then similarly for the second case, but using EndsWith instead of StartsWith.
check this
public bool Comparing(string str1, string str2)
=> str2.StartWith(str1.replace("*","")) && str1.length == str2.Length;
I'm currently attempting to validate a string for an assignment so it's imperative that I'm not simply given the answer, if you provide an answer please give suitable explanation so that I can learn from it.
Suppose I have a string
(1234)-1234 ABCD
I'd like to create a loop that will go through that string and validate the position of the "()" as well as the "-" and " ". In addition to the validation of those characters their position must also be the same as well as the data type. Finally, it must be inside a method.
CANNOT USE REGEX
TLDR;
Validate the position of characters and digits in a string, while using a loop inside of a method. I cannot use REGEX and need to do this manually.
Here's what I have so far. But I feel like the loop would be more efficient and look nicer.
public static string PhoneChecker(string phoneStr)
{
if (phoneStr[0] == '(' && phoneStr[4] == ')' && phoneStr[5] == ' ' && phoneStr[9] == '-' && phoneStr.Length == 14)
{
phoneStr = phoneStr.Remove(0, 1);
phoneStr = phoneStr.Remove(3, 1);
phoneStr = phoneStr.Remove(3, 1);
phoneStr = phoneStr.Remove(6, 1);
Console.WriteLine(phoneStr);
if (int.TryParse(phoneStr, out int phoneInt) == false)
{
Console.WriteLine("Invalid");
}
else
{
Console.WriteLine("Valid");
}
}
else
{
Console.WriteLine("Invalid");
}
return phoneStr;
}
It is still unmaintaible, but still a little better... Note that your code didn't work with your example string (the indexes were off by one).
public static bool PhoneChecker(string phoneStr)
{
if (phoneStr.Length != 16 || phoneStr[0] != '(' || phoneStr[5] != ')' || phoneStr[6] != '-' || phoneStr[11] != ' ')
{
return false;
}
if (!uint.TryParse(phoneStr.Substring(1, 4), out uint phoneInt))
{
return false;
}
if (!uint.TryParse(phoneStr.Substring(7, 4), out phoneInt))
{
return false;
}
// No checks for phoneStr.Substring(12, 4)
return true;
}
Some differences:
The Length check is the first one. Otherwise a short string would make the program crash (because if you try to do a phoneStr[6] on a phoneStr that has a length of 3 you'll get an exception)
Instead of int.Parse I used uint.Parse, otherwise -500 would be acceptable.
I've splitted the uint.Parse for the two subsections of numbers in two different check
The method returns true or false. It is the caller's work to write the error message.
There are various school of thought about early return in code: I think that the earlier you can abort your code with a return false the better it is. The other advantage is that all the remaining code is at low nesting level (your whole method was inside a big if () {, so nesting +1 compared to mine)
Technically you tagged the question as C#-4.0, but out int is C#-6.0
The main problem here is that stupid constraints produce stupid code. It is rare that Regex are really usefull. This is one of the rare cases. So now you have two possibilities: produce hard-coded unmodifiable code that does exactly what was requested (like the code I wrote), or create a "library" that accepts variable patterns (like the ones used in masked edits, where you can tell the masked edit "accept only (0000)-0000 AAAA") and validates the string based on this pattern... But this will be a poor-man's regex, only worse, because you'll have to maintain and test it. This problem will become clear when one month from the release of the code they'll ask you to accept even the (12345)-1234 ABCD pattern... and then the (1234)-12345 ABCD pattern... and a new pattern every two months (until around one and half years later they'll tell you to remove the validator, because the persons that use the program hate them and it slow their work)
Is there a fastest way to compare two strings (using the space for a wildcard) than this function?
public static bool CustomCompare(this string word, string mask)
{
for (int index = 0; index < mask.Length; index++)
{
if (mask[index] != ' ') && (mask[index]!= word[index]))
{
return false;
}
}
return true;
}
Example: "S nt nce" comparing with "Sentence" will return true. (The two being compared would need to be the same length)
If mask.length is less than word.length, this function will stop comparing at the end of mask. A word/mask length compare in the beginning would prevent that, also it would quick-eliminate some obvious mismatches.
The loop is pretty simple and I'm not sure you can do much better. You might be able to micro optimize the order of the expression in the if statement. For example due to short circuiting of the && it might be faster to order the if statement this way
if (mask[index]!= word[index])) && (mask[index] != ' ')
Assuming that matching characters is more common that matching the wildcard. Of course this is just theory I wouldn't believe it made a difference without benchmarking it.
And as others have pointed out the routine fails if the mask and string are not the same length.
That looks like a pretty good implementation - I don't think you will get much faster than that.
Have you profiled this code and found it to be a bottleneck in your application? I think this should be fine for most purposes.
If you used . instead of , you could do a simple regex match.
Variable Length comparison:
I used your code as a starting place for my own application which assumes the mask length is shorter or equal to the comparison text length. allowing for a variable length wildcard spot in the mask. ie: "concat" would match a mask of "c ncat" or "c t" or even "c nc t"
private bool CustomCompare(string word, string mask)
{
int lengthDifference = word.Length - mask.Length;
int wordOffset = 0;
for (int index = 0; index < mask.Length; index++)
{
if ((mask[index] != ' ') && (mask[index]!= word[index+wordOffset]))
{
if (lengthDifference <= 0)
{
return false;
}
else
{
lengthDifference += -1;
wordOffset += 1;
}
}
}
return true;
}
Not sure if this is any faster but it looks neat:
public static bool CustomCompare(this string word, string mask)
{
return !mask.Where((c, index) => c != word[index] && c != ' ').Any();
}
I think you're doing a little injustice by not giving a little bit of context to your code. Sure, if you want to search only one string of characters of the same length as your pattern, then yes this is fine.
However, if you are using this as the heart of a pattern matcher where there are several other patterns you will be looking for, this is a poor method. There are other known methods, the best of which depends on your exact application. The phrase "inexact pattern matching" is the phrase you are concerned with.
Consider the need for a function in C# that will test whether a string is a numeric value.
The requirements:
must return a boolean.
function should be able to allow for whole numbers, decimals, and negatives.
assume no using Microsoft.VisualBasic to call into IsNumeric(). Here's a case of reinventing the wheel, but the exercise is good.
Current implementation:
//determine whether the input value is a number
public static bool IsNumeric(string someValue)
{
Regex isNumber = new Regex(#"^\d+$");
try
{
Match m = isNumber.Match(someValue);
return m.Success;
}
catch (FormatException)
{return false;}
}
Question: how can this be improved so that the regex would match negatives and decimals? Any radical improvements that you'd make?
Just off of the top of my head - why not just use double.TryParse ? I mean, unless you really want a regexp solution - which I'm not sure you really need in this case :)
Can you just use .TryParse?
int x;
double y;
string spork = "-3.14";
if (int.TryParse(spork, out x))
Console.WriteLine("Yay it's an int (boy)!");
if (double.TryParse(spork, out y))
Console.WriteLine("Yay it's an double (girl)!");
Regex isNumber = new Regex(#"^[-+]?(\d*\.)?\d+$");
Updated to allow either + or - in front of the number.
Edit: Your try block isn't doing anything as none of the methods within it actually throw a FormatException. The entire method could be written:
// Determine whether the input value is a number
public static bool IsNumeric(string someValue)
{
return new Regex(#"^[-+]?(\d*\.)?\d+$").IsMatch(someValue);
}
Well, for negatives you'd need to include an optional minus sign at the start:
^-?\d+$
For decimals you'd need to account for a decimal point:
^-?\d*\.?\d*$
And possible exponential notation:
^-?\d*\.?\d*(e\d+)?$
I can't say that I would use regular expressions to check if a string is a numeric value. Slow and heavy for such a simple process. I would simply run over the string one character at a time until I enter an invalid state:
public static bool IsNumeric(string value)
{
bool isNumber = true;
bool afterDecimal = false;
for (int i=0; i<value.Length; i++)
{
char c = value[i];
if (c == '-' && i == 0) continue;
if (Char.IsDigit(c))
{
continue;
}
if (c == '.' && !afterDecimal)
{
afterDecimal = true;
continue;
}
isNumber = false;
break;
}
return isNumber;
}
The above example is simple, and should get the job done for most numbers. It is not culturally sensitive, however, but it should be strait-forward enough to make it culturally sensitive.
Also, make sure the resulting code passes the Turkey Test:
http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html
Unless you really want to use regex, Noldorin posted a nice extension method in another Q&A.
Update
As Patrick rightly pointed out, the link points to an extension method that check whether the object is a numeric type or not, not whether it represents a numeric value. Then using double.TryParse as suggested by Saulius and yodaj007 is probably the best choice, handling all sorts of quirks with different decimal separators, thousand separators and so on. Just wrap it up in a nice extension method:
public static bool IsNumeric(this string value)
{
double temp;
return double.TryParse(value.ToString(), out temp);
}
...and fire away:
string someValue = "89.9";
if (someValue.IsNumeric()) // will be true in the US, but not in Sweden
{
// wow, it's a number!
]
Can anyone think of a nicer way to do the following:
public string ShortDescription
{
get { return this.Description.Length <= 25 ? this.Description : this.Description.Substring(0, 25) + "..."; }
}
I would have liked to just do string.Substring(0, 25) but it throws an exception if the string is less than the length supplied.
I needed this so often, I wrote an extension method for it:
public static class StringExtensions
{
public static string SafeSubstring(this string input, int startIndex, int length, string suffix)
{
// Todo: Check that startIndex + length does not cause an arithmetic overflow - not that this is likely, but still...
if (input.Length >= (startIndex + length))
{
if (suffix == null) suffix = string.Empty;
return input.Substring(startIndex, length) + suffix;
}
else
{
if (input.Length > startIndex)
{
return input.Substring(startIndex);
}
else
{
return string.Empty;
}
}
}
}
if you only need it once, that is overkill, but if you need it more often then it can come in handy.
Edit: Added support for a string suffix. Pass in "..." and you get your ellipses on shorter strings, or pass in string.Empty for no special suffixes.
return this.Description.Substring(0, Math.Min(this.Description.Length, 25));
Doesn't have the ... part. Your way is probably the best, actually.
public static Take(this string s, int i)
{
if(s.Length <= i)
return s
else
return s.Substring(0, i) + "..."
}
public string ShortDescription
{
get { return this.Description.Take(25); }
}
The way you've done it seems fine to me, with the exception that I would use the magic number 25, I'd have that as a constant.
Do you really want to store this in your bean though? Presumably this is for display somewhere, so your renderer should be the thing doing the truncating instead of the data object
Well I know there's answer accepted already and I may get crucified for throwing out a regular expression here but this is how I usually do it:
//may return more than 25 characters depending on where in the string 25 characters is at
public string ShortDescription(string val)
{
return Regex.Replace(val, #"(.{25})[^\s]*.*","$1...");
}
// stricter version that only returns 25 characters, plus 3 for ...
public string ShortDescriptionStrict(string val)
{
return Regex.Replace(val, #"(.{25}).*","$1...");
}
It has the nice side benefit of not cutting a word in half as it always stops after the first whitespace character past 25 characters. (Of course if you need it to truncate text going into a database, that might be a problem.
Downside, well I'm sure it's not the fastest solution possible.
EDIT: replaced … with "..." since not sure if this solution is for the web!
without .... this should be the shortest :
public string ShortDescription
{
get { return Microsoft.VisualBasic.Left(this.Description;}
}
I think the approach is sound, though I'd recommend a few adjustments
Move the magic number to a const or configuration value
Use a regular if conditional rather than the ternary operator
Use a string.Format("{0}...") rather than + "..."
Have just one return point from the function
So:
public string ShortDescription
{
get
{
const int SHORT_DESCRIPTION_LENGTH = 25;
string _shortDescription = Description;
if (Description.Length > SHORT_DESCRIPTION_LENGTH)
{
_shortDescription = string.Format("{0}...", Description.Substring(0, SHORT_DESCRIPTION_LENGTH));
}
return _shortDescription;
}
}
For a more general approach, you might like to move the logic to an extension method:
public static string ToTruncated(this string s, int truncateAt)
{
string truncated = s;
if (s.Length > truncateAt)
{
truncated = string.Format("{0}...", s.Substring(0, truncateAt));
}
return truncated;
}
Edit
I use the ternary operator extensively, but prefer to avoid it if the code becomes sufficiently verbose that it starts to extend past 120 characters or so. In that case I'd like to wrap it onto multiple lines, so find that a regular if conditional is more readable.
Edit2
For typographical correctness you could also consider using the ellipsis character (…) as opposed to three dots/periods/full stops (...).
One way to do it:
int length = Math.Min(Description.Length, 25);
return Description.Substring(0, length) + "...";
There are two lines instead of one, but shorter ones :).
Edit:
As pointed out in the comments, this gets you the ... all the time, so the answer was wrong. Correcting it means we go back to the original solution.
At this point, I think using string extensions is the only option to shorten the code. And that makes sense only when that code is repeated in at least a few places...
Looks fine to me, being really picky I would replace "..." with the entity reference "…"
I can't think of any but your approach might not be the best. Are you adding presentation logic into your data object? If so then I suggest you put that logic elsewhere, for example a static StringDisplayUtils class with a GetShortStringMethod( int maxCharsToDisplay, string stringToShorten).
However, that approach might not be great either. What about different fonts and character sets? You'd have to start measuring the actual string length in terms of pixels. Check out the AutoEllipsis property on the winform's Label class (you'll prob need to set AutoSize to false if using this). The AutoEllipsis property, when true, will shorten a string and add the '...' chars for you.
I'd stick with what you have tbh, but just as an alternative, if you have LINQ to objects you could
new string(this.Description.ToCharArray().Take(25).ToArray())
//And to maintain the ...
+ (this.Description.Length <= 25 ? String.Empty : "...")
As others have said, you'd likely want to store 25 in a constant
You should see if you can reference the Microsoft.VisualBasic DLL into your app so you can make use of the "Left" function.