C# String Compare not working with trailing slash - c#

In C# 4.0, whenever I compare two strings which have one or more trailing slashes, the comparison gives incorrect results:
String a = "1/2.1/";
String b = "1/2/";
if (a.CompareTo(b) > 0)
MessageBox.Show("Correct: " + a + " > " + b);
else
MessageBox.Show("Not correct: " + a + " <= " + b);
a = a.TrimEnd('/');
b = b.TrimEnd('/');
if (a.CompareTo(b) > 0)
MessageBox.Show("Trailing slash removed. Correct: " + a + " > " + b);
else
MessageBox.Show("Trailing slash removed. Not correct: " + a + " <= " + b);
Lexically speaking, "1/2.1/" comes after "1/2/", and there is not much question about that.
This behaviour also occurs in other places, such as sorting a datatable using the Select method.
Am I doing something wrong? Or is this a bug in .Net?
It should not even have anything to do with culture-specific information etc. since a slash is part of the most basic US ASCII character set.
I am running into this when comparing SQL Server hierarchyIDs. It's easy enough to solve but it is a somewhat astonishing problem.

Lexically speaking, "1/2.1/" comes after "1/2/", and there is not much question about that.
Why would it come after? On the ASCII chart, the / comes immediately after the ..
Given the following two strings, they're equal until you reach the 4th character. Then the / and . are compared, and the / is greater. So the result you're seeing (a < b) is actually correct.
1/2.1/
1/2/
After calling TrimEnd(), you end up with two different strings where and a > b.
1/2.1
1/2

If my old skill in C doesn't fail me, I think that CompareTo executes a character by character subtraction of the Integer value of the characters until the result is not zero.
After the first 3 identical characters the CompareTo looks at the fourth character, and this is a point for the first string and a slash for the second string.
The integer value of the point character is 46 while the integer value of the slash is 47, 46-47 gives back -1 so "1/2.1/" is less than "1/2/".

You can compare strings containing numbers if the numbers are right aligned:
01/02.00/
01/02.10/
01/10.00/
If this is not possible, consider creating a type for your numbers
public class ChapterNumber : IComparable<ChapterNumber>
{
private readonly decimal[] _number;
public ChapterNumber(params decimal[] number)
{
_number = number;
}
public int CompareTo(T obj)
{
var other = obj as ChapterNumber;
if (other == null) {
return +1;
}
int len = Math.Min(_number.Length, other._number.Length);
for (int i = 0; i < len; i++) {
int result = _number[i].CompareTo(other._number[i]);
if (result != 0) {
return result;
}
}
return _number.Length.CompareTo(other._number.Length);
}
public override ToString()
{
return String.Join('/', _number) + "/";
}
}
Usage:
var a = new ChapterNumber(1, 2.1m);
var b = new ChapterNumber(1, 2);
if (a.CompareTo(b) > 0) {
...
}

Related

Input string was not in a correct format. c# (New)

I'm having "Input string was not in a correct format." error from this code
rainTb.Text = " " + int.Parse(parsed[0]) * 100 / 1023;
There's no error in my code. Except for the error above. I've made a calculation to extract the analogue value (above calculation) from Arduino hardware via serial communication (cable). Arduino works fine though. Everything was fine though until this error shows up... Why? cries
p/s : I've gone through many solutions but still.. So here I am now. Sorry for my English
private void ProcessCOMRx(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(COMRx))
{
systemTb.Text = "Processing Data...";
systemTb.BackColor = System.Drawing.Color.Lime;
string [] parsed = COMRx.Split(',');
int curveNo;
if (parsed.Count() > zedAll.GraphPane.CurveList.Count())
curveNo = zedAll.GraphPane.CurveList.Count();
else
curveNo = parsed.Count();
for (int k = 0; k < curveNo; k++)
{
for (int j = zedAll.GraphPane.CurveList[k].NPts - 1; j > 0; j--)
{
zedAll.GraphPane.CurveList[k].Points[j].Y = zedAll.GraphPane.CurveList[k].Points[j - 1].Y;
}
double temp = 0;
try
{
temp = double.Parse(parsed[k]);
}
catch
{
systemTb.Text = "Parse Error";
systemTb.BackColor = System.Drawing.Color.Red;
}
rainTb.Text = "" + int.Parse(parsed[0]) * 100 / 1023;
phTb.Text = "" + (3.5 + int.Parse(parsed[1]) * 4.5 / 1023);
moistTb.Text = "" + int.Parse(parsed[2]) * 100 / 1023;
tempTb.Text = "" + int.Parse(parsed[3]) * 100 / 1023;
zedAll.GraphPane.CurveList[k].Points[0].X = 0;
zedAll.GraphPane.CurveList[k].Points[0].Y = temp;
}
}
else
{
this.BeginInvoke(new EventHandler(processPumpStates));
}
}
There are few possible cases why it happens. One is because (1) parsed[0] number is too big, another is because parsed[0] contains (2) non-number, (3) non-recognized thousand separators, or (4) decimal separator (which should not exist in int parsing) in the applied culture for your code.
In all cases, please check the value of parsed[0] with your Visual Studio debugger and make sure that it has purely-acceptable numerical format for int range. Something like:
1234
Also, you may consider of
using TryParse instead of Parse to ensure that the non-parsed number does not cause you exception problem.
use ToString() for printing your numerical calculation result,
check the result of TryParse and
beware of the integer division that you potentially do in the original int.Parse(parsed[0]) * 100 / 1023:
Something like this:
int val;
bool result = int.TryParse(parsed[0], out val);
if (!result)
return; //something has gone wrong
Textbox1.Text = " " + (val * 100d / 1023d).ToString(); //note the d
You are getting such error on the basics of the value contained in the parsed[0] if it is a convertible string your code works fine else it throws the exception that you got. ie, the content inside the parsed[0] is not convertible to an integer, in such situations you should Use int.TryParse instead for int.Parse, it is having internal error handling, which help you to determine whether the conversion is successful or not.
So the code will looks like:
int tempNumber=0;
if (int.TryParse(parsed[0], out tempNumber))
{
Textbox1.Text = " " + (tempNumber * 100 / 1023).ToString();
}
else
{
Textbox1.Text= "invalid zipCode";
}

avoid extra zeros in number formatting in C#

(First of all: this is not a duplicate of Format numbers with floating points and sign in textbox in C#)
I am using the solution from dodald (https://stackoverflow.com/a/27510646/3179989) for formatting numbers with floating points and sign to make them aligned based on the floating point:
textbox1.Text = String.Format("{0:+;-}{0,9:0.00000;0.00000}", number1);
textbox2.Text = String.Format("{0:+;-}{0,9:0.00000;0.00000}", number2);
textbox3.Text = String.Format("{0:+;-}{0,9:0.00000;0.00000}", number3);
textbox4.Text = String.Format("{0:+;-}{0,9:0.00000;0.00000}", number4);
textbox5.Text = String.Format("{0:+;-}{0,9:0.00000;0.00000}", number5);
It works perfectly for numbers are like -1.23456 (results in "- 1.23456"), however if the number is 1.2, then this will change it to "+ 1.20000".
Questions:
Is there anyway to avoid any extra zeros?
How can I add a space at the end of the text by using the formatting parameters and not using (text + " ")?
Thanks in advance
EDIT: to clarify this here is what I am looking for:
-123.123456
+ 1.123456
- 0.123456
- 0.123
+ 1.1
- 12.123456
I have multiple textboxes that are vertically aligned. I want the numbers to be displayed the way is presented above where the position of the floating point is always fixed and vertically aligned. The solution provided by dodald (https://stackoverflow.com/a/27510646/3179989) works just for the number with five decimal numbers like -1.23456 (results in "- 1.23456"), however if the number is 1.2, then his solution will change it to "+ 1.20000". I'd like to remove the added zeros to the string.
You can use this code by using string builder and you will find that all zeros on the right side of decimal point deleted and this is shown before (1555454545445.20000000000000000) and after (1555454545445.2) in console:
static void Main(string[] args)
{
string input = "1555454545445.20000000000000000";
StringBuilder sb = new StringBuilder(input);
for (int i = 0; i < input.Length-2; i++)
{
if (input[i] == '.')
{
if (input[input.Length - 1] == '0')
{
for (int x = 0; x < input.Length - i; i++)
{
if (sb[sb.Length - 1] == '0')
{
sb = sb.Remove((sb.Length - 1), 1);
}
}
}
}
}
Console.WriteLine(input);
Console.WriteLine(sb.ToString());
}
You can also use this code for removing any additional zeros on the right of the decimal point by using regular expression:
class MainProgram
{
public static void Main(string[] args)
{
decimal DNumber = 1223456.45600000M;
Console.WriteLine("Original Decimal Number = {0}, Decimal Number Without Zeros = {1}", DNumber, DNumber.ToString("#.##############"));
Console.Read();
}
}

How do I round doubles in human-friendly manner in C#?

In my C# program I have a double obtained from some computation and its value is something like 0,13999 or 0,0079996 but this value has to be presented to a human so it's better displayed as 0,14 or 0,008 respectively.
So I need to round the value, but have no idea to which precision - I just need to "throw away those noise digits".
How could I do that in my code?
To clarify - I need to round the double values to a precision that is unknown at compile time - this needs to be determined at runtime. What would be a good heuristic to achieve this?
You seem to want to output a value which is not very different to the input value, so try increasing numbers of digits until a given error is achieved:
static double Round(double input, double errorDesired)
{
if (input == 0.0)
return 0.0;
for (int decimals = 0; decimals < 17; ++decimals)
{
var output = Math.Round(input, decimals);
var errorAchieved = Math.Abs((output - input) / input);
if (errorAchieved <= errorDesired)
return output;
}
return input;
}
}
static void Main(string[] args)
{
foreach (var input in new[] { 0.13999, 0.0079996, 0.12345 })
{
Console.WriteLine("{0} -> {1} (.1%)", input, Round(input, 0.001));
Console.WriteLine("{0} -> {1} (1%)", input, Round(input, 0.01));
Console.WriteLine("{0} -> {1} (10%)", input, Round(input, 0.1));
}
}
private double PrettyRound(double inp)
{
string d = inp.ToString();
d = d.Remove(0,d.IndexOf(',') + 1);
int decRound = 1;
bool onStartZeroes = true;
for (int c = 1; c < d.Length; c++ )
{
if (!onStartZeroes && d[c] == d[c - 1])
break;
else
decRound++;
if (d[c] != '0')
onStartZeroes = false;
}
inp = Math.Round(inp, decRound);
return inp;
}
Test:
double d1 = 0.13999; //no zeroes
double d2 = 0.0079996; //zeroes
double d3 = 0.00700956; //zeroes within decimal
Response.Write(d1 + "<br/>" + d2 + "<br/>" + d3 + "<br/><br/>");
d1 = PrettyRound(d1);
d2 = PrettyRound(d2);
d3 = PrettyRound(d3);
Response.Write(d1 + "<br/>" + d2 + "<br/>" + d3 +"<br/><br/>");
Prints:
0,13999
0,0079996
0,00700956
0,14
0,008
0,007
Rounds your numbers as you wrote in your example..
I can think of a solution though it isn't very efficient...
My assumption is that you can tell when a number is in the "best" human readable format when extra digits make no difference to how it is rounded.
eg in the example of 0,13999 rounding it to various numbers of decimal places gives:
0
0.1
0.14
0.14
0.14
0.13999
I'd suggest that you could loop through and detect that stable patch and cut off there.
This method seems to do this:
public double CustomRound(double d)
{
double currentRound = 0;
int stability = 0;
int roundLevel = 0;
while (stability < 3)
{
roundLevel++;
double current = Math.Round(d, roundLevel);
if (current == currentRound)
{
stability++;
}
else
{
stability = 1;
currentRound=current;
}
}
return Math.Round(d, roundLevel);
}
This code might be cleanable but it does the job and is a sufficient proof of concept. :)
I should emphasise that that initial assumption (that no change when rounding) is the criteria we are looking at which means that something like 0.3333333333 will not get rounded at all. With the examples given I'm unable to say if this is correct or not but I assume if this is a double issues that the problem is with the very slight variations from the "right" value and the value as a double.
Heres what I tried:
public decimal myRounding(decimal number)
{
double log10 = Math.Log10((double) number);
int precision = (int)(log10 >= 0 ? 0 : Math.Abs(log10)) + (number < 0.01m ? 1 : 2);
return Math.Round(number, precision);
}
test:
Console.WriteLine(myRounding(0.0000019999m)); //0.000002
Console.WriteLine(myRounding(0.0003019999m)); //0.0003
Console.WriteLine(myRounding(2.56777777m)); //2.57
Console.WriteLine(myRounding(0.13999m)); //0.14
Console.WriteLine(myRounding(0.0079996m)); //0.008
You can do it without converting to string. This is what I created fast:
private static double RoundDecimal(double number)
{
double temp2 = number;
int temp, counter = 0;
do
{
temp2 = 10 * temp2;
temp = (int)temp2;
counter++;
} while (temp < 1);
return Math.Round(number, counter < 2 ? 2 : counter);
}
or
private static double RoundDecimal(double number)
{
int counter = 0;
if (number > 0) {
counter = Math.Abs((int) Math.Log10(number)) + 1;
return Math.Round(arv, counter < 2 ? 2 : counter);
}
After giving it another thought I did the following and looks like it does what I want so far.
I iterate over the number of digits and compare Round( value, number ) and Round( value, number + 1 ). Once they are equal (not == of course - I compare the difference against a small number) then number is the number of digits I'm looking for.
Double.ToString() can take a string format as an argument. This will display as many characters as you require, rounding to the decimal place. E.G:
double Value = 1054.32179;
MessageBox.Show(Value.ToString("0.000"));
Will display "1054.322".
Source
Generic formats (i.e, pre-generated)
How to generate custom formats
You can use no of digits with Math.Round Function
Double doubleValue = 4.052102;
Math.Round(doubleValue, 2);
This will return 4.05 as your required answer.
This is tested code, can u explain me how i am wrong. So i need to change.

Regular expression for subnet masking?

I am using regular expression for checking the subnet masking. I use ajax txtbox with masking value but that is not working, then I switched to a textbox and applying a regular expression for that. unfortunatly that one is also not working.
Can you help me out to give a RE for subnet masking 255.255.255.255
Or any best way to do that?
Solution:
I was using masked text box and don't know how to put validation expression.
Finally I found a property of masked text box as validation expression, and there I put the RE and change the property validate to true.
No need to use validator expression explicitly.
Thanks
To do this with a regular expression, you have to ensure that the entire IPv4 dotted quad represents a 32 bit number with leading ones only. It is not enough to ensure that each number in the quad has only leading ones. For example, 255.192.255.0 is not a valid submask, even though each number in the quad has only leading ones. Building on the solution offered by #xanatos,
var leadingOnes = new Regex("255|254|252|248|240|224|192|128|0+");
defines a regular expression that will match any 8-bit (decimal) number with leading ones only. I have used "0+" to allow for .000, which is sometimes used in quads. Obviously, if you want to force a singe zero, use "0" instead.
You then have to build up a regular expression that matches any one of the four following patterns, which I represent as pseudo regular expressions to make it easer to understand:
255.255.255.leadingOnes
255.255.leadingOnes*.0
255.leadingOnes.0.0
leadingOnes.0.0.0
You can either write this out as a single string, or build it up through concatenation. Here's building it up:
var leadingOnes = "(255|254|252|248|240|224|192|128|0+);"
var allOnes = #"(255\.)";
var re = new Regex("^((" + allOnes + "{3}" + leadingOnes + ")|" +
"(" + allOnes + "{2}" + leadingOnes + #"\.0+)|" +
"(" + allOnes + leadingOnes + #"(\.0+){2})|" +
"(" + leadingOnes + #"(\.0+){3}))$");
And here's the entire string, if we ignore line breaks.
var re = new Regex(#"^(((255\.){3}(255|254|252|248|240|224|192|128|0+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))$");
Following #Keith's suggestion, you could start with a simple regular expression such as
Regex("([0-9]{1,3}\.){3}[0-9]{1,3}" to get four 3-digit numbers separated by dots, and then write a function that extracts and evaluates the four pieces into a 32-bit integer that you then check to ensure that it has only leading ones. There are several ways to do that, but all of them require up to 31 compare operations to complete the validation.
If you want to accept any IP address as a subnet mask:
var num = #"(25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})";
var rx = new Regex("^" + num + #"\." + num + #"\." + num + #"\." + num + "$");
I considered easier to split the "repeating" match for a single group of numbers in a separate variable.
As an exercise for the reader, I'll give another variant of the expression. This one will capture all the numbers in the same group but different captures:
var rx = new Regex("^(?:" + num + #"(?:\.(?!$)|$)){4}$");
BUT it's wrong, you should use this
var num = #"(255|254|252|248|240|224|192|128|0+)";
var rx = new Regex("^" + num + #"\." + num + #"\." +num + #"\." +num + "$");
or
var rx = new Regex("^(?:" + num + #"(?:\.(?!$)|$)){4}$");
http://www.freesoft.org/CIE/Course/Subnet/6.htm
I know the question asked about a Regex expression, but for anyone else who's interested, here are two iterative solutions to the problem. The second function is a bit faster than the first.
private bool IsValidSubnet(IPAddress ip) {
byte[] validOctets = new byte[] { 255, 254, 252, 248, 240, 224, 192, 128, 0 };
byte[] ipOctets = ip.GetAddressBytes();
bool restAreZeros = false;
for (int i = 0; i < 4; i++) {
if (!validOctets.Contains(ipOctets[i]))
return false;
if (restAreZeros && ipOctets[i] != 0)
return false;
if (ipOctets[i] < 255)
restAreZeros = true;
}
return true;
}
// checks if the address is all leading ones followed by only zeroes
private bool IsValidSubnet2(IPAddress ip) {
byte[] ipOctets = ip.GetAddressBytes();
bool restAreOnes = false;
for (int i = 3; i >= 0; i--) {
for (int j = 0; j < 8; j++) {
bool bitValue = (ipOctets[i] >> j & 1) == 1;
if (restAreOnes && !bitValue)
return false;
restAreOnes = bitValue;
}
}
return true;
}
From http://pastebin.com/wTEKjKpP
var subnetRegex = /^((128|192|224|240|248|252|254)\.0\.0\.0)|(255\.(((0|128|192|224|240|248|252|254)\.0\.0)|(255\.(((0|128|192|224|240|248|252|254)\.0)|255\.(0|128|192|224|240|248|252|254)))))$/
Of course that's for javascript, but that should help.
you can use this regex to validate subnet
^(((255\.){3}(255|254|252|248|240|224|192|128+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))$
Explanation
A little late to the party, but we can't do just a regex check on valid octets because:
A subnet must start with 255.X.X.X
A subnet cannot look like this: 255.254.128.X - once there is 0 bit, everything else must be 0 afterwards
The correct way to do this is to walk the bits from the MSB, checking for the first 0 bit. Once you discover the first 0 bit, check what position it's in. The largest legal subnet is a /8, or 255.0.0.0, meaning there needs to be 8 1 bits before the first zero. Then, make sure every bit after the first 0 is a zero. So in summary:
(Optionally verify that it's even a valid IP address...)
Start at MSB, walk down bits looking for the first 0
If you find a 0 (255.255.255.255 would still be valid), check position
Check that all remaining bits are zero
Code
private bool IsValidSubnet(string subnet)
{
//A subnet is a valid ipv4 address, so start checking there
if (!IsIPv4(subnet)) return false;
// Get the 4 bytes
byte[] subnetMaskBytes =
System.Net.IPAddress.Parse(subnet).GetAddressBytes();
//Shift to get uint representation of the bits
var UintSubnet = (uint)subnetMaskBytes[0] << 24;
UintSubnet += (uint)subnetMaskBytes[1] << 16;
UintSubnet += (uint)subnetMaskBytes[2] << 8;
UintSubnet += (uint)subnetMaskBytes[3];
int i = 31;
while (i >= 0)
{
UInt32 mask = (UInt32)(1 << i);
if ((UintSubnet & mask) == 0) break;
i--;
}
// It is not legal to have fewer than 8 bits of addressing
if (i >= 24) return false;
// Make sure that all remaining bits are 0
while (i >= 0)
{
UInt32 mask = (UInt32)(1 << i);
if ((UintSubnet & mask) != 0) return false;
i--;
}
return true;
}

Need code for addition of 2 numbers

I am having the numbers follows taken as strings
My actual number is 1234567890123456789
from this i have to separate it as s=12 s1=6789 s3=3456789012345
remaining as i said
I would like to add as follows
11+3, 2+4, 6+5, 7+6, 8+7, 9+8 such that the output should be as follows
4613579012345
Any help please
public static string CombineNumbers(string number1, string number2)
{
int length = number1.Length > number2.Length ? number1.Length : number2.Length;
string returnValue = string.Empty;
for (int i = 0; i < length; i++)
{
int n1 = i >= number1.Length ? 0 : int.Parse(number1.Substring(i,1));
int n2 = i >= number2.Length ? 0 : int.Parse(number2.Substring(i,1));
int sum = n1 + n2;
returnValue += sum < 10 ? sum : sum - 10;
}
return returnValue;
}
This sounds an awful lot like a homework problem, so I'm not giving code. Just think about what you need to do. You are saying that you need to take the first character off the front of two strings, parse them to ints, and add them together. Finally, take the result of the addition and append them to the end of a new string. If you write code that follows that path, it should work out fine.
EDIT: As Ralph pointed out, you'll also need to check for overflows. I didn't notice that when I started typing. Although, that shouldn't be too hard, since you're starting with a two one digit numbers. If the number is greater than 9, then you can just subtract 10 to bring it down to the proper one digit number.
How about this LINQish solution:
private string SumIt(string first, string second)
{
IEnumerable<char> left = first;
IEnumerable<char> right = second;
var sb = new StringBuilder();
var query = left.Zip(right, (l, r) => new { Left = l, Right = r })
.Select(chars => new { Left = int.Parse(chars.Left.ToString()),
Right = int.Parse(chars.Right.ToString()) })
.Select(numbers => (numbers.Left + numbers.Right) % 10);
foreach (var number in query)
{
sb.Append(number);
}
return sb.ToString();
}
Tried something:
public static string NumAdd(int iOne, int iTwo)
{
char[] strOne = iOne.ToString().ToCharArray();
char[] strTwo = iTwo.ToString().ToCharArray();
string strReturn = string.Empty;
for (int i = 0; i < strOne.Length; i++)
{
int iFirst = 0;
if (int.TryParse(strOne[i].ToString(), out iFirst))
{
int iSecond = 0;
if (int.TryParse(strTwo[i].ToString(), out iSecond))
{
strReturn += ((int)(iFirst + iSecond)).ToString();
}
}
// last one, add the remaining string
if (i + 1 == strOne.Length)
{
strReturn += iTwo.ToString().Substring(i+1);
break;
}
}
return strReturn;
}
You should call it like this:
string strBla = NumAdd(12345, 123456789);
This function works only if the first number is smaller than the second one. But this will help you to know how it is about.
In other words, you want to add two numbers treating the lesser number like it had zeroes to its right until it had the same amount of digits as the greater number.
Sounds like the problem at this point is simply a matter of finding out how much you need to multiply the smaller number by in order to reach the number of digits of the larger number.

Categories