False positive using string.length in if statement - c#

I'm trying to format phone numbers. Perhaps my approach is not the best but it works with the exception of some unexpected behavior. I'm using string.length in an if statement to see if the phone number's length (stored as a string) is greater than 9. I've also tried >= 10 instead of > 9 with the same results. All works fine with 18001234567 or 7041234567. I get (800) 123-4567 or (704) 123-4567. But with 828464047 I get (82) 846-4047 rather than the number just being returned as is.
try
{
if (ANI.Length > 9)
{
char[] Number1 = { '1' };
ANI = ANI.TrimStart(Number1);
return String.Format("{0:(###) ###-####}", Convert.ToDouble(ANI));
}
else if (ANI == "")
{
return "Private";
}
else
{
return ANI;
}
}
catch (Exception ex)
{
return ex.Message;
}
Any ideas? Is there a better way to approach this?
Thanks.
If I change the code that formats the phone number to use substrings, things break, as expected.
return "(" + ANI.Substring(0, 3) + ") " + ANI.Substring(3, 3) + "-" + ANI.Substring(6, 4);
An exception is caught and "Index and length must refer to a location within the string. Parameter name: length" is returned.

I put it into a unit test method and it works. You're obviously getting an extra character added onto the string 828464047. You can debug and place a breakpoint at the IF statement and see what is actually in ANI.
A few things as well,
Don't name a variable something ambiguous like "ANI".
rename Number1 to something like "firstNumber"
A try/Catch is not needed for this statement, if you're getting an exception you're doing something that can be solved by better coding.

I can see ANI.TrimStart() in your code which leads me to suspect that you have some leading whitespace. You can probably best solve the problem by moving the trimming to outside the if.
It's pretty safe to assume that something as fundamental as String.Length works correctly. When it says your string is a certain length, your string really will be that length.

I'd check your inputs for whitespace or, perhaps you transcribed your input wrong here. The following tests pass against your code, copied and pasted:
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void Ten_Digit_800_Number()
{
var myPad = new NumberFormatter();
Assert.AreEqual<string>("(800) 123-4567", myPad.FormatNumber("18001234567"));
}
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void Ten_Digit_800_Number()
{
var myPad = new NumberFormatter();
Assert.AreEqual<string>("(800) 123-4567", myPad.FormatNumber("18001234567 "));
}
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void TroubleString()
{
var myPad = new NumberFormatter();
Assert.AreEqual<string>("828464047", myPad.FormatNumber("828464047"));
}

The problem was stripping the leading '1' after having evaluated the length of the string. Stripping the '1' bef

Related

Check if input has number and string to calculate in C#

I am really into the basics of programming and while writing a few lines of code to convert Celsius to Fahrenheit, which is pretty easy I started to wonder the following:
Can I make the program show me an answer depending if I wrote in the Console:
25C //to convert to F
or for example 100F // to convert to C
So far my knowledge goes to advanced "if" constructs and "for" cycles. Just started to study "do-while".
I am missing some knowledge how to properly search an input for number && specific char in order to give proper calculation.
I know that it seems a little complicated to make input :
25F // in one line instead of
25
F
but this will expand my knowledge and understanding.
I will try the latter now, should be easy, but can't find out how to do the former.
Thanks in advance!
Darin
In C# any string is actually a class, which contains useful methods for example:
string input = "25F";
if (input.EndsWith("F"))
{
// handle Fahrenheit
}
Then you can get rid of the last character like so:
string inputWithoutLastCharacter = input.Substring(0, input.Length - 1);
To convert a string to a number you can:
try
{
int number = int.Parse(inputWithoutLastCharacter);
}
catch (Exception ex)
{
Console.WriteLine("Could not convert your input to a number " + ex.ToString());
}
Try/catch is there to handle error cases where the input is not a valid number.
Also check out other methods of string. For example ToLower() to handle both "f" and "F".
Good luck.
String temp = Console.ReadLine();
char scale = temp[temp.Length-1];
if(temp.ToUpper().Contains("F")) {
int temperature = Int32.Parse(temp.Remove(temp.Length-1,1));
double celciusValueOfTemp = (temperature-32)/1.8;
Console.WriteLine(celciusValueOfTemp);
}
else if(temp.ToUpper().Contains("C")) {
int temperature = Int32.Parse(temp.Remove(temp.Length-1,1));
double fahrenheitValueOfTemp = temperature*1.8+32;
Console.WriteLine(fahrenheitValueOfTemp);
}

How to take screenshot if Assert.AreEqual fails? How to put if condition with Assert.AreEqual?

I am trying to take screenshot of failed test case in C# selenium.
But i dont know how to use if condition with Assert.AreEqual.
I tried using if(Assert.Equals == false) also but that's not working.
Can anybody help??
Well actually, "Asset.AreEqual" accepts three parameter
1. expected result in bool
2. Original result in bool
3. error message
if expected and original does not match it will throw an error and for the screenshot u need to use try-catch, I have used this long ago.
public void AreEqual(bool expected, bool result, string comment = "",string pictureName = "")
{
try
{
Assert.AreEqual(expected, result, comment);
}
catch
{
/// will capture a screenshot of errors
if (string.IsNullOrEmpty(pictureName) && !string.IsNullOrEmpty(comment))
{
int length = comment.Replace(" ", string.Empty).Length;
if (length > 30)
length = 30;
pictureName = comment.Replace(" ", string.Empty).Substring(0, length);
}
pictureName = (pictureName == "" ? Guid.NewGuid().ToString() : pictureName);
GetScreenShot(pictureName);
// Getscreenshot function capture image for me u need to put your code here(before throw)
throw;
}
}
It'd help to see more of your actual test, but since Assert.Equals doesn't return a value, you could break it down into multiple steps.
For example, if you have this:
Assert.AreEqual(value1, value2);
Then you could replace it with this:
var areValuesEqual = (value1 == value2);
Assert.IsTrue(areValuesEqual);
if (!areValuesEqual)
{
// rest of testing logic
}

Does Console.Write ever fail?

I am testing my run() function to make sure it has all the correct things populated by the end of the method. I populate 4 fields from our databases, two strings, and two IEnumerable(string)'s. The idea is to print them all out for all the people I am pulling from the database.
When I only print the string fields, everything works fine. However, when I try to add the Enumerables as well, nothing prints at all. I am also printing a counter so I know the program is still running and working. Does Console ever decide to not print anything at all due to space or something else?
Here's the code that does it:
int i = 0;
foreach (Contact contact in Contact.LoadWithPredicate(getAll))
{
-------other code to populate fields---------
i ++;
Console.WriteLine(i);
//Turn the Enumerables into strings for printing
string firstEnumAsString = String.Join(", ", firstEnumerable.ToArray());
string secondEnumAsString = String.Join(", ", secondEnumerable.ToArray());
Console.WriteLine("Email: " + firstString+ ", correspondance: " + secondString+ ", PAM addresses: " + firstEnumAsString+ ", famousPeople: " + secondEnumAsString);
}
So, as my output, whenever I run the code above, I get an output like this:
1
2
Email: foo#bar.com, correspondance: John, PAM addresses: bar#foo.com, famousPeople: foo, bar, foo
3
4
etc
Problem is, only two people out of the total (~425) show up, the rest of the lines are just numbers. Shouldn't I at least get the strings "Email", and ", correspondence"? It seems like Console is just deciding not to do anything. And I know that the code must reach it because it prints out the integer i just before I call that Console.WriteLine().
On the other hand, whenever I just ask for the two string fields to be printed, the Console displays both fields for all 425 users, right after their corresponding integer. Does anyone know what's happening here? TIA
Based on your comments, I think either your firstEnumerable or secondEnumerable objects are null. But since you did not post how you obtain these objects, I can't comment on why they are null or how to fix it.
It's okay for them to contain null entries, or even be fully empty, but they themselves cannot be null or it will throw an ArgumentNullException when you call .ToArray() on them. This corresponds with the "value cannot be null" exception message you're seeing.
The reason why it's not crashing and burning hard is because you are swallowing (and logging?) the exceptions within your iteration loop with a try/catch block that was not posted in your code sample.
I'm guessing your actual code is something like this:
foreach (Contact contact in Contact.LoadWithPredicate(getAll))
{
try
{
...
object[] firstEnumerable = null;
object[] secondEnumerable = null;
//some logic gates here which under some circumstances do not
//assign a valid instance to firstEnumerable or secondEnumerable
...
Console.WriteLine(i); //this prints every time
//Turn the Enumerables into strings for printing
string firstEnumAsString = String.Join(", ", firstEnumerable.ToArray()); //exception here
string secondEnumAsString = String.Join(", ", secondEnumerable.ToArray()); //or exception here
Console.WriteLine("Email: " + firstString+ ", correspondance: " + secondString+ ", PAM addresses: " + firstEnumAsString+ ", famousPeople: " + secondEnumAsString);
...
}
catch
{
//maybe some logging? maybe not?
}
}
This will print out the i value each time. But when it attempts to create firstEnumAsString or secondEnumAsString it throws an exception and never hits your second Console.WriteLine("Email: " + ...); thus producing the output you're seeing. It's not that the Console.WriteLine is failing, it's that you're never calling it in the first place.
If value is null, only the line terminator is written to the standard output stream.
For more information about the line terminator, see the Remarks section of the WriteLine() method. - Source
On top of that, if one of the values you're trying to write to the console throw an Exception, like in the following code:
private static string SomeVal { get { throw new Exception(); } }
Console.WriteLine("Foo");
Console.WriteLine("This throws an exception: " + SomeVal);
"This throws an exception:" won't be written to the console either; the entire string is just considered null. To me it looks like that's what's actually happening in your code; one of the values you're trying to write to the console is throwing an Exception, and it's handled somewhere silently. Are you running this code in a supressive try/catch clause?
You can easily figure out if that's the case by putting a breakpoint on Console.WriteLine or the trailing } and check the values of firstString, secondString and see if they're null. You can also tell whether one of the values you're trying to write threw an exception.
Also, you should consider using string.Format(string format, params object[] args) rather than concatenating with +. Makes debugging your code a lot easier, too.

Getting an unexpected "?" at the end of a Registry GetValue

I use the Registry class to manage values in the Registry on Windows Seven in C#.
Registry.GetValue(...);
But, I'm facing a curious behavior :
Every time, the returned value is the correct one, but sometimes, it is followed by an unexpected "?"
When I check the Registry, (regedit), the "?" doesn't exist.
I really don't understand from where this question mark come from.
Info :
C#
3.5 framework
windows 7 64 bits (and i want my application to work on both 32 and 64 bits systems)
That didn't quite work for me, I was also getting a random ? at the end of a value from the registry that was a file path. It only appeared every now and again. It seems like a bug.
I use 2 pass method to see if directory exists and then strip out characters, I was getting unicode character 1792 at the end. < 128 probably won't work for some languages.
string configPath = val.ToString();
bool dirExists = false;
if (Directory.Exists(configPath))
{
dirExists = true;
}
else
{
_logger.Warn("The path for service {0} doesn't exist: {1}", serviceName, configPath);
StringBuilder configPathBuilder = new StringBuilder(configPath.Length);
// Do this to remove any dodgy characters in the path like a ? at end
char[] inValidChars = Path.GetInvalidPathChars();
foreach (Char c in configPath.ToCharArray())
{
if (inValidChars.Contains(c) == false && c < 128)
{
configPathBuilder.Append(c);
}
else
{
_logger.Warn("An invalid path was character was found in the path: {0} {1}", c, (int)c);
}
}
configPath = configPathBuilder.ToString();
if (Directory.Exists(configPath))
{
dirExists = true;
}
}
So my question is, "who set the value"?
Perhaps whoever did the setting put in an unprintable character at the end of the string. It is probably not actually a question mark. This may be a result of a bug in the program which did the setting, not anything to do with your code, per se.
I found a way to remove the unexpected char, thanks to all your comments ;)
String value = null;
try
{
foreach (Char item in Registry.GetValue(registryKey, key, "").ToString().ToCharArray())
{
if (Char.GetUnicodeCategory(item) != System.Globalization.UnicodeCategory.OtherLetter && Char.GetUnicodeCategory(item) != System.Globalization.UnicodeCategory.OtherNotAssigned)
{
value += item;
}
}
}
catch (Exception ex)
{
LOG.Error("Unable to get value of " + key + ex, ex);
}
return value;
I made some tests to know what kind of char appears from time to time. It was, just like you said Larry, an unicode problem.
I still don't understand why this char appears sometimes.

Help with a C# conditional statement dealing with Strings

In my attempt at dissecting a bit of C# I am afraid I do not understand either the goal or the logic of this bit of code:
if (!string.IsNullOrEmpty(str2) && (Strings.UCase(Strings.Left(str2, 1)) != Strings.Left(str2, 1)))
{
return false;
}
I understand the first part is checking if str2 is "not null", however the second part is coming off a bit flaky. So we UCase the first character of str2, and if it does not equal the first character of str2 (which is NOT "UCase"d), then return "false"?
Maybe I am not missing anything and what I described above is in fact what the code is doing. If this is the case, can we reform this into something else that offers the same result,say for example, check if str2 is uppercase or not? I feel like this is the end goal.
You thoughts?
Yes, you understood the code right.
It looks like something translated from VB using a translation tool, as it's using functions from the VisualBasic namespace. I would rather write it with String methods:
if (!String.IsNullOrEmpty(str2) && str2.Substring(0,1).ToUpper() != str2.SubString(0,1)) {
return false;
}
Or simply getting the first character as a character instead of as a string, and use the IsLower method of the Char class:
if (!string.IsNullOrEmpty(str2) && Char.IsLower(str2[0])) {
return false;
}
My bet is that they are really just testing whether the first character is uppercase. The initial "IsNullOrEmpty" test is just there to make sure that the real test doesn't throw an exception.
The big question: if there is no string value (null or empty) this will not return false. Is that the expected outcome?
Code Objective in English :)
If the non-empty string begins with a lower case character then return false
This is the same, but refactored:
if (!string.IsNullOrEmpty(str2)) {
string s = Strings.Left(str2, 1);
if (Strings.UCase(s) != s) {
return false;
}
}
It is clear that this code tests that the first letter of str2 is or isn't in uppercase when it has any character.
I share the perceptions you have when you say : "I do not understand either the goal or the logic of this bit of code" :) A test that returns only 'false is "fishy" : presumably "something" is waiting for a boolean to be returned, and nothing is returned if the result of this evaluates to 'true.
But if I had to write such a function I'd use the alternative OR logic :
return (! (String.IsNullOrEmpty(testString) || testString.ToUpper()[0] == testString[0]));

Categories

Resources