Best approach to get ipv4 last octet - c#

I know substring can handle this but, is there a better way to get last octet from an IP ?
Ex.:
192.168.1.100
I want 100
Tks

just for fun:
Console.WriteLine(IPAddress.Parse("192.168.1.33").GetAddressBytes()[3]);

Just for fun I wrote the version which would have the least overhead (string manipulation etc.). #rushui has the correct answer though.
static void Main(string[] args)
{
Console.WriteLine(OctetInIP("10.1.1.100", 0));
Console.ReadLine();
}
static byte OctetInIP(string ip, int octet)
{
var octCount = 0;
var result = 0;
// Loop through each character.
for (var i = 0; i < ip.Length; i++)
{
var c = ip[i];
// If we hit a full stop.
if (c == '.')
{
// Return the value if we are on the correct octet.
if (octCount == octet)
return (byte)result;
octCount++;
}
else if (octCount == octet)
{
// Convert the current octet to a number.
result *= 10;
switch (c)
{
case '0': break;
case '1': result += 1; break;
case '2': result += 2; break;
case '3': result += 3; break;
case '4': result += 4; break;
case '5': result += 5; break;
case '6': result += 6; break;
case '7': result += 7; break;
case '8': result += 8; break;
case '9': result += 9; break;
default:
throw new FormatException();
}
if (result > 255)
throw new FormatException();
}
}
if (octCount != octet)
throw new FormatException();
return (byte)result;
}

It may be overkill, but a simple regex would also do the trick:
(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})

Remember what an IP address is, it is a 32-bit (4 byte) number. So masking the address with the subnet mask would actually be the correct way to do it. If you always want a subnet mask of 255.255.255.0, as your question implies, you can & the number with 0xFF to get the number.
But, if you don't care about efficiency, and only have the address as a string, the split on "." is just fine... :)

Related

c# Switch Case not working and says "Input String was not in a correct format"

I'm trying to end the process when I run my code using a switch case.
Full code:
int[] Slots = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
while (true)
{
Console.WriteLine("Please enter the number of the slot (1-10)");
int Slot = Convert.ToInt32(Console.ReadLine());
if (Slots[Slot - 1] == 0)
{
Slots[Slot - 1] = 1;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Reservation Successful!");
}
else if (Slots[Slot - 1] == 1)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Slot preoccupied.");
}
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("(R)eserve another slot, (C)heck available slots or (E)nd Process?");
char choice = Convert.ToChar(Console.ReadLine());
switch (choice)
{
case 'E':
case 'e':
break;
case 'C':
case 'c':
Console.WriteLine("The available slots are:");
for (int i = 0; i < Slots.Length; i++)
{
if (Slots[i] == 0)
Console.WriteLine("{0}", i + 1);
}
continue;
case 'R':
case 'r':
continue;
default:
Console.WriteLine("Invalid Input");
break;
}
}
Everything works fine except for the 'E' case.
Whenever I try to use the 'E' case it doesn't perform the break command.
Instead it pinpoints to the line:
int Slot = Convert.ToInt32(Console.ReadLine());
And it says that 'Input String was not in a correct format' and when I try to do what the system recommends, which is to change the "int" to "var". It just tells me to change it back to "int" instead.
I am very confused, I have no idea what that means. I am a student and this was never taught to us yet so I don't know what to do.
I expected it to work since it didn't give any errors when i try to run my code, and everything works fine except for the 'E' case.
You seem to think, that the "break" in your switch case will exit your while loop, however the break will only exit the switch case.
The error you are getting, comes from not exiting your while loop. Then the loop executes again and reads an empty line which cannot be parsed to int. Meaning the input string which you are trying to parse into int is not an actual integer (empty line is not an integer).
what you should do is:
bool isRunning = true;
while(isRunning)
{
//your logic
switch(choice)
{
case 'E':
case 'e':
isRunning = false;
break;
}
}
A break inside a switch causes the control to only break out of the switch. Hence, you need another break to break out of the while loop. The easiest way to do this is to use an extra boolean variable that is toggled in the 'E' case. After the switch, test if the variable is set, and if so, break out of the loop.
The suggestion to change int to var and back is basically just a coding style suggestion and has no further meaning.

How can I make the "dot" and "comma" characters to both function the same way in TextBox without giving error?

I want to make "." and "," to both work as decimal numbers. My problem is that by default on my computer it is "."(23.33 works) and it does error when i try putting "," (23,33). How can I make it work.
private static Double SolveExpression(String expression)
{
char uiSep = CultureInfo.CurrentUICulture.NumberFormat.NumberDecimalSeparator[0];
expression = expression.Replace('.', uiSep);
expression = expression.Replace(',', uiSep);
if (expression.StartsWith("("))
{
int opening_brackets = 1, closing_brackets = 0, current_symbol = 1;
while (opening_brackets != closing_brackets)
{
if (expression[current_symbol] == '(')
opening_brackets++;
else if (expression[current_symbol] == ')')
closing_brackets++;
current_symbol++;
}
String expr = expression.Substring(1, current_symbol - 2);
expression = expression.Remove(0, current_symbol);
Match operation = Regex.Match(expression, #"^[\+\-\*\/]");
if (operation.Success)
{
expression = expression.Remove(0, operation.Value.Length);
switch (operation.Value)
{
case "+":
{
return SolveExpression(expr) + SolveExpression(expression);
}
case "-":
{
return SolveExpression(expr) - SolveExpression(expression);
}
case "*":
{
return SolveExpression(expr) * SolveExpression(expression);
}
case "/":
{
return SolveExpression(expr) / SolveExpression(expression);
}
}
}
else
return SolveExpression(expr);
}
Match constant = Regex.Match(expression, #"(^-*\d+)((\.|\,)(\d+))?");
if (constant.Success)
{
expression = expression.Remove(0, constant.Value.Length);
Match operation = Regex.Match(expression, #"^[\+\-\*\/]");
if (operation.Success)
{
expression = expression.Remove(0, operation.Value.Length);
switch (operation.Value)
{
case "+":
{
return Double.Parse(constant.Value) + SolveExpression(expression);
}
case "-":
{
return Double.Parse(constant.Value) - SolveExpression(expression);
}
case "*":
{
return Double.Parse(constant.Value) * SolveExpression(expression);
}
case "/":
{
return Double.Parse(constant.Value) / SolveExpression(expression);
}
}
}
else
return Double.Parse(constant.Value);
}
else
//throw new Exception("Invalid Expression");
MessageBox.Show("You have entered invalid expression! Revise and try again", "Something went wrong", MessageBoxButtons.OK,MessageBoxIcon.Error);
return 0;
}
If you want to support either character as a decimal point but not accept thousands separators then the easiest way is to just replace all , with . and use CultureInfo.InvariantCulture:
stringValue = stringValue.Replace(',','.');
double.TryParse(stringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out double doubleValue)
However, if a user supplies a value with a thousands separator (with or without a decimal), then this method will give wrong results.
Didn't get what you mean exactly. But here is something that can help with the Numeric format of a string:
double [] value = {123.456,567.1};
Console.WriteLine("Your account balance is {0:C2}.", value[0],value[1]);
Console.WriteLine("Your account balance is {1:C3}.", value[0],value[1]);
// Displays "Your account balance is $123.46."
// "Your account balance is $567.100."
where: 0 and 1 are the elements of the value array, value[0] and value1.
C2 and C3 is showing in the currency format with two and three digits after decimal
for details and more check this out
Using the regex in the line of:
\-?[0-9]+[\.\,][0-9]+
This will allow numbers in the form of:
12.34
12,34
-12.34
-12,34
Then by using the string.Replace
it is possible to do this:
input = input.Replace(",", ".")
var numberFormat = System.Globalization.CultureInfo.InvariantCulture.NumberFormat;
double value = Convert.ToDouble(TextBox.Text, numberFormat);
The number can be parsed.
Try this:
var str = "1.25";
var str2 = "1,25";
double Parse(string txt){
return double.Parse(txt.Replace(",",".")
.Replace(".", CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator));
}
Parse(str); // not crashing
Parse(str2); // not crashing

Parsing routine for over-sign characters relatively slow

I am trying to make the enclosed subroutine more performant using NET framework 4.6.1 although I will eventually port it to net core 2.2 .
It may run up to 250,000 times when parsing a file.
Using Visual Studio Performance Analyzer I see this routine seems to have a fairly high relative cost in the whole parsing process.
The code is part of a parsing program whose input is a binary file that contains some very old record formats that contain over-signed numbers.
Over-signed Numbers (background)
Instead of a minus sign and in order to save space the last digit is made a letter if the number is negative. Its a very old standard dating back to when computers had limited memory and fixed width records were required for performance.
When parsing I need to convert the last letter back to a number and make the number negative
Some examples of input and output of the routine
00056K = -562
00032N = -325
Current Code (slow)
private int ConvertOverSign(string overSignedString)
{
switch(overSignedString.Substring(overSignedString.Length -1,1))
{
case " ":
return 0;
case "J":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "1");
case "K":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "2");
case "L":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "3");
case "M":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "4");
case "N":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "5");
case "O":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "6");
case "P":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "7");
case "Q":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "8");
case "R":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "9");
case "!":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "0");
default:
return Convert.ToInt32(overSignedString);
}
}
Not sure the below solution is fully equivalent to yours, but at least should give you a hint on how to make a very fast string-to-number parser.
private int ConvertOverSign(string overSignedString)
{
if (overSignedString == " ") return 0;
int value = 0;
for (int i = 0; i < overSignedString.Length; i++)
{
char ch = overSignedString[i];
switch (ch)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
value = value * 10 + (ch - 0x30);
break;
case '!':
value *= 10;
return -value;
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
value = value * 10 + (ch - 'I');
return -value;
}
}
return value;
}
Bear in mind that string manipulations (e.g. Substring) are typically heavy if you need performance.
Switch over the indexed character. Substring is actually alocating a new string and that is slow:
switch (overSignedString[Length - 1])
{
case ' ':
return 0;
case "J":
return ...
You might want to read this to see if its worth parsing the string inside each case avoiding Convert. There are faster ways.
Your method is slow because it generates a lot of string garbage.
You could improve it by comparing characters instead of strings, and perform multiplication of the resulting integer instead of appending strings and using a lookup instead of a switch:
private Dictionary<char, int> _additions = new Dictionary<char, int>
{
{ '!', 0 },
{ 'J', 1 },
{ 'K', 2 },
{ 'L', 3 },
{ 'M', 4 },
{ 'N', 5 },
{ 'O', 6 },
{ 'P', 7 },
{ 'Q', 8 },
{ 'R', 9 },
};
private int ConvertOverSign(string overSignedString)
{
var lastChar = overSignedString[overSignedString.Length -1];
if (lastChar == ' ')
{
return 0;
}
if (!_additions.TryGetValue(lastChar, out int addition))
{
return Convert.ToInt32(overSignedString);
}
var result = (Convert.ToInt32(overSignedString.Substring(0, overSignedString.Length - 1)) * -10) - addition;
return result;
}

C# switch case how to calculate

Hey I´am trying to add two numbers together via switch case.
I have 3 inputs, number 1 and number 2. The 3rd input is the method which I´d like to calculate number 1 and 2 with(e.g +, -, *, /, etc...)
Now the problem is how do I create something like "this" ? I´ve tried this way, but it does not work...
Is it possible to make switch case like this : case %: ???
Thanks
string firstNumber;
string secondNumber;
string method;
//get numbers
Console.WriteLine ("Get first number");
firstNumber = Console.ReadLine ();
Console.WriteLine ("get 2nd number");
secondNumber = Console.ReadLine ();
Console.WriteLine ("the method to calculate with");
Console.WriteLine (" 1:\"*\"");
Console.WriteLine (" 2:\"/\"");
Console.WriteLine (" 3:\"+\"");
Console.WriteLine (" 4:\"-\"");
method = Console.ReadLine ();
//convert
int methodNew = Convert.ToInt32 (method);
int firstNumberNew = Convert.ToInt32 (firstNumber);
int secondNumberNew = Convert.ToInt32 (secondNumber);
switch (methodNew) {
case 1:
firstNumberNew *= secondNumberNew;
break;
default:
Console.WriteLine ("check the methods.");
break;
}
Console.WriteLine (methodNew);
Of course, you can read in a char and do a switch-case
for it:
int c = Console.Read(); // read from console
switch(c) {
case '/':
// work
break;
case '%':
// work
break;
case '*':
// work
break;
case '+':
// work
break;
}
First get the operator then use switch like this:
char method = Console.ReadKey().KeyChar;
double result = 0.0;
switch (method)
{
case '+':
result = firstNumberNew + secondNumberNew;
break;
case '-':
result = firstNumberNew - secondNumberNew;
break;
case '/':
result = firstNumberNew / secondNumberNew;
break;
case '%':
result = firstNumberNew % secondNumberNew;
break;
default:
Console.WriteLine("Invalid value, try again");
break;
}
Console.WriteLine(result);
It would be better if you change the type of firstNumberNew and secondNumberNew to double.Alşo you can use a while loop to force user to enter a valid character.

complex string to double conversion

I have strings in a XML file that ment to be doubles (or float) such as:
<VIPair>
<voltage>+100mV</voltage>
<current>+1.05pA</current>
</VIPair>
<VIPair>
<voltage>+5.00mV</voltage>
<current>+0.0035nA</current>
</VIPair>
The first pair will be "0.1" Volt and "0.00000000000105" Ampere.
The second pair would be "0.005" Volt and "0.000000000035" Ampere.
How can I convert them to double of float in C#?
Thanks.
P.S: I already can read them from xml file and at the moment I retrive them as string.
Try with this:
// Read string (if you do not want to use xml)
string test = "<voltage>+100mV</voltage>";
string measure = test.Substring(test.IndexOf('>')+1);
measure = measure.Substring(0, measure.IndexOf('<')-1);
// Extract measure unit
string um = measure.Substring(measure.Length - 1);
measure = measure.Substring(0, measure.Length - 1);
// Get value
double val = Double.Parse(measure);
// Convert value according to measure unit
switch (um)
{
case "G": val *= 1E9; break;
case "M": val *= 1E6; break;
case "k": val *= 1E3; break;
case "m": val /= 1E3; break;
case "u": val /= 1E6; break;
case "n": val /= 1E9; break;
case "p": val /= 1E12; break;
}
Hi here is another version of what Marco has written.
string str = "1pV";
double factor;
double value;
switch (str[str.Length-2])
{
case 'M': factor = 1E6; break;
case 'm': factor = 1E-3; break;
case 'n': factor = 1E-9; break;
case 'p': factor = 1E-12; break;
default:
factor = 1; break;
}
value = double.Parse(str.Substring(0,str.Length-2)) * factor;
Assuming that the html text is already available to you. I have tried to do the same thing with one substring, switch case with characters instead of strings(This is a bit faster to comparing strings) and a double.parse. Hope someone comes up with a better version than this.
Remove the suffix string mV and nA using string.Substring or string.Remove() method and use double.TryParse() method to parse string to double.
If your values always have 2 chars on the end you could simple remove these and parse the number.
var newstring = fullstring.Substring(0, fullstring.Length - 2);
var number = double.Parse(newstring);

Categories

Resources