ip address increment problem - c#

I want to increase my ip address and;
Here is the code
ipAddressControl1.Text = "192.168.1.255";
byte[] ip = ipAddressControl1.GetAddressBytes();
ip[3] = (byte)(++ip[3]);
IPAddress ipAddress1 = new IPAddress(ip);
MessageBox.Show(ipAddress1.ToString());
or I also tried this
ipAddressControl3.Text = "192.168.1.255";
IPAddress ipAddress1 = new IPAddress(ıpAddressControl3.GetAddressBytes());
ipAddress1.Address += 0x1 << 24;
MessageBox.Show(ipAddress1.ToString());
but both of them gives me 192.168.1.0 but I want to get value as 192.168.2.0

Your problem is that you're not increasing ip[2] when ip[3] wraps around (and so on up the hierarchy). The following code should do the trick, finally wrapping from 255.255.255.255 to 0.0.0.0:
byte[] ip = ipAddressControl1.GetAddressBytes();
ip[3] = (byte)(ip[3] + 1);
if (ip[3] == 0) {
ip[2] = (byte)(ip[2] + 1);
if (ip[2] == 0) {
ip[1] = (byte)(ip[1] + 1);
if (ip[1] == 0) {
ip[0] = (byte)(ip[0] + 1);
}
}
}
The following may also work:
byte[] ip = ipAddressControl1.GetAddressBytes();
if (++ip[3] == 0)
if (++ip[2] == 0)
if (++ip[1] == 0)
++ip[0];

It might be worth noting that none of the existing answers handle IPv6 addresses, which the IPAddress class itself does indeed cater for. For that you'd probably want to adopt a more general strategy (and I'm not sure what the increment rules for IPv6 are like, though they could be exactly the same, just with more bytes to do it over, which I suspect is the case).
-- Edit:
On that basis, this seems to work:
public static IPAddress Increment (IPAddress address)
{
IPAddress result;
byte[] bytes = address.GetAddressBytes();
for(int k = bytes.Length - 1; k >= 0; k--){
if( bytes[k] == byte.MaxValue ){
bytes[k] = 0;
continue;
}
bytes[k]++;
result = new IPAddress(bytes);
return result;
}
// Un-incrementable, return the original address.
return address;
}

In the first example, you're only incrementing the 4th byte sequence. So it's going to go from 255 to 0 with no effect to byte[2].
In the second sequence, you're incrementing it 1, but then you're shifting it back from 2 to 1. I'm not sure why you chose to do this.

You need to check if your address is 254 - 255 and 0 are a broadcast addresses.
ipAddressControl1.Text = "192.168.1.255";
byte[] ip = ipAddressControl1.GetAddressBytes();
if (ip[3] != 255)
{
ip[3] = (byte)(++ip[3]);
}
else
{
ip[2] = (byte)(++ip[2]);
ip[3] = (byte)0;
}
IPAddress ipAddress1 = new IPAddress(ip);
MessageBox.Show(ipAddress1.ToString());
But you can only check for overflows up to ip[0] - you need to take care if you hit 255 there.

Looks like IP addresses are stored the “wrong way around” in the .Address property you tried to use:
192.168.1.255
c0 a8 01 ff is stored as 0xff01a8c0
So adding 1 << 24 is only going to increment the 0xff on the left and then truncate it, turning it into 0.
You’ll have to write your own addition function if you want this to work the way you describe.
public static IPAddress IncrementIP(IPAddress addr)
{
byte[] ip = addr.GetAddressBytes();
ip[3]++;
if (ip[3] == 0) {
ip[2]++;
if (ip[2] == 0) {
ip[1]++;
if (ip[1] == 0)
ip[0]++;
}
}
return new IPAddress(ip);
}
or something like that.

You can convert the IP into its numerical equivalent.
Check this previously answered question for details:
Best type for IP-address in Hibernate Entity?
public static string GetStandardIP(long numericIP)
{
string w = Convert.ToString(Convert.ToInt64(numericIP / 16777216) % 256);
string x = Convert.ToString(Convert.ToInt64(numericIP / 65536) % 256);
string y = Convert.ToString(Convert.ToInt64(numericIP / 256) % 256);
string z = Convert.ToString(Convert.ToInt64(numericIP) % 256);
return w + "." + x + "." + y + "." + z;
}
And this one
public static long GetNumericIP(string standardIP)
{
if (standardIP != null && standardIP != string.Empty)
{
string[] ipParts = standardIP.Split('.');
long numericIP = 16777216 * Convert.ToInt64(ipParts[0]) + 65536 * Convert.ToInt64(ipParts[1]) + 256 * Convert.ToInt32(ipParts[2]) + Convert.ToInt32(ipParts[3]);
return numericIP;
}
return 0;
}
You may want to improve them by doing checks on the parameters and use string.concat

I strongly disagree with the provided answer. It surely works, but I can see serious problems with it, starting with readability. In my opinion, readability and maintainability are paramount, and the accepted solution simply won't do. Adding to this, a more generic approach will also solve the problem for IPv6, while the accepted solution will not work.
My proposal is to use the following method:
public static IPAddress AddOne(this IPAddress ipAddress)
{
byte[] data = ipAddress.GetAddressBytes();
IncrementByOneFromRight(data, data.Length - 1);
return new IPAddress(data);
}
private static void IncrementByOneFromRight(byte[] data, int index)
{
if (index < 0)
return;
if (data[index] < byte.MaxValue)
data[index] += 1;
else
{
data[index] = 0;
IncrementByOneFromRight(data, index - 1);
}
}
Place the above in a visible static class, and the AddOne method will work as an extension method to IPAddress. This makes it easier to work with, and you will not expose the nitty-gritty implementation details of adding to the IPAddress in your class, while maintaining and readability. This will have the added benefit of not cluttering the class you are already writing with possibly unrelated methods.
Please vote up so that this is visible to people coming to this question if you agree with my answer and the reasons I disagree with the approved one.

Related

Performance Way to check if a byte array contains another byte Array C#

I'm checking if an byte array contains a another Byte Array with this Code:
private int IndexOf(int index, byte[] AllBytes, byte[] searchByteArray)
{
for (int i = index; i <= AllBytes.Length - 1 - searchByteArray.Length - 1; i++)
{
for (int j = 0; j <= searchByteArray.Length - 1; j++)
{
if (AllBytes[i + j] == searchByteArray[j])
{
if (j + 1 == searchByteArray.Length)
return i;
}
else
break;
}
}
return -1;
}
That works perfect and I get the index of the first byte back.
But the problem is I want to check very large Data.
My "big" Array contains around 900000000 Bytes and my searchArray about 10-20 Bytes. In that way my function is very very slow. Is there a way to make a better performance?
Thanks.
You could adapt the Boyer–Moore string-search algorithm to bytes.
First, you create an array int[256] where the array indexes correspond to all possible byte values. The array contains the positions of each byte value in the search pattern starting from the end, and the search pattern length for values not appearing in the search pattern.
Then you compare the last position of the pattern with a position in the input array. If the values do not match, you can advance the search position by the value in the table found at the index equal to the value in the input array. If they match, compare the pattern with the input.
Example
intput: 100 206 002 250 123 075 074 109 184 222
search pattern: 200 109 100 150 123
^
|
The table
...
[108] = 5
[109] = 3
[110] = 5
...
the value 123 does not match 109, therefore you look up the table at position 109 and get 3. I.e. you can increase the search position by 3, so that the two 109 values line up. If the value was 108, you could have moved by 5 positions (the full search pattern length).
The link above explains the algorithm in more detail.
I needed something similar. What I needed to do was determine if an array of bytes is present within a different array of bytes. I did not need to know how many times one array appeared within the other array or even the position.
My search for a quick solution which performs well didn't yield any acceptable results. I've seen the Boyer–Moore string-search algorithm as well as other supposedly fast search algorithms suggested as answers to virtually every question on the subject I found yet I have been unable to find a single implementation of one of those algorithms which is actually faster than unoptimized brute code.
So I decided to go with brute force since the code is vastly superior than the Boyer–Moore implementations. Being a little on the obsessive side I did make a few basic optimizations to the brute force approach. I present it here for others who happen upon this in the future.
In my testing my optimizations resulted in code which executes very close to 100% faster when tested against purely pseudo-random data. My code is not designed to allow you to find all the occurrences of one array within another but it can be easily modified to do so. I'll leave that to the reader.
My code:
/// <summary>
/// Determines whether a byte array contains the specified sequence of bytes.
/// </summary>
/// <param name="caller">The byte array to be searched.</param>
/// <param name="array">The byte to be found.</param>
/// <returns>The first location of the sequence within the array, -1 if the sequence is not found.</returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public static int Contains(this byte[] caller, byte[] array)
{
byte startValue, endValue;
int result, arrayLength, searchBoundary, j, startLocation, endOffset;
if (caller == null)
throw new ArgumentNullException($"{nameof(caller)}");
if (array == null)
throw new ArgumentNullException($"{nameof(array)}");
if (caller.Length == 0 || array.Length == 0)
throw new ArgumentException($"Argument {(caller.Length == 0 ? nameof(caller) : nameof(array))} is empty.");
if (array.Length > caller.Length)
return -1;
startValue = array[0];
arrayLength = array.Length;
if (arrayLength > 1)
{
result = -1;
endValue = array[^1];
endOffset = arrayLength - 1;
searchBoundary = caller.Length - arrayLength;
startLocation = -1;
while ((startLocation = Array.IndexOf(caller, startValue, startLocation + 1)) >= 0)
{
if (startLocation > searchBoundary)
break;
if (caller[startLocation + endOffset] == endValue)
{
for (j = 1; j < endOffset && caller[startLocation + j] == array[j]; j++) { }
if (j == endOffset)
{
result = startLocation;
break;
}
}
}
}
else
{
result = Array.IndexOf(caller, startValue);
}
return result;
}
Also the version of the original posters code I used for test purposes:
public static int IndexOf(this byte[] AllBytes, int index, byte[] searchByteArray)
{
for (int i = index; i <= AllBytes.Length - 1 - searchByteArray.Length - 1; i++)
{
for (int j = 0; j <= searchByteArray.Length - 1; j++)
{
if (AllBytes[i + j] == searchByteArray[j])
{
if (j + 1 == searchByteArray.Length)
return i;
}
else
break;
}
}
return -1;
}
And finally my code which tests the functions:
private static void TestContains()
{
bool copyContained;
int result, offset;
byte[] containedValue, containingValue;
Random rng;
Stopwatch watch1, watch2;
List<Tuple<byte[], byte[], bool, int>> testList;
testList = new();
watch1 = new();
watch2 = new();
rng = new();
for (int j = 0; j < 120; j++)
{
Console.SetCursorPosition(0, 0);
Console.WriteLine($"Test number {j:#,0} in progress...");
for (int i = 32; i < 40000; i++)
{
offset = 0;
copyContained = rng.Next(0, 1000) != 0;
containingValue = new byte[i];
rng.NextBytes(containingValue);
containedValue = new byte[rng.Next(8, i)];
if (copyContained)
{
offset = rng.Next(0, i - containedValue.Length);
rng.NextBytes(containedValue);
Array.Copy(containedValue, 0, containingValue, offset, containedValue.Length);
}
testList.Add(new Tuple<byte[], byte[], bool, int>(containingValue, containedValue, copyContained, offset));
}
foreach (var testCase in testList)
{
watch1.Start();
result = testCase.Item1.Contains(testCase.Item2);
watch1.Stop();
watch2.Start();
testCase.Item1.IndexOf(0, testCase.Item2);
watch2.Stop();
if ((testCase.Item1.Length == 0 && result != -1) ||
(testCase.Item2.Length == 0 && result != -1) ||
(testCase.Item3 && result != testCase.Item4) ||
(!testCase.Item3 && result != -1))
Debugger.Break();
}
testList.Clear();
//CollectGarbage(0);
}
Console.WriteLine(
"\r\n\r\n" + $#"Comparison duration (using Contains): {watch1.Elapsed:hh\:mm\:ss\.ff}" + "\r\n" +
"\r\n" + $#"Comparison duration (using Contains2): {watch2.Elapsed:hh\:mm\:ss\.ff}" + "\r\n" +
"\r\n" + $#"Speed differential: {(watch1.Elapsed > watch2.Elapsed ? $"Contains2 is {((double)watch1.ElapsedTicks / watch2.ElapsedTicks - 1) * 100:#.00}%" : $"Contains is {((double)watch2.ElapsedTicks / watch1.ElapsedTicks - 1) * 100:#.00}%")} faster." +
"\r\n\r\n\r\n Press enter to continue.");
Console.ReadLine();
}
While a 100% improvement isn't going to make the difference in some cases, it's an improvement nonetheless and a pretty significant one. On the old desktop I am testing this on, a Core i5-4570, I can find the position of the array I am searching for in a 1 GB array in less than a second. I didn't specifically test large arrays as you can see because my use case is for smaller arrays, less than 65 KB.

C# code issue for ASCII to HEX. insight required

I am doing me university project and facing a big issue. i am developing a UI on C# visual studio 2010. I need to open a serial connection and feed some values into the micro controller. basically i have nodes with 24 bits addresses (3 bytes) e.g 0x78A26F.
i take my input from user in the GUI in a text Box. the user shall enter this 78A26F and i want that the serial port sends the following data 0x6F 0xA2 0x78.
But the user input is saved as a string and when i send it through serial connection, the ASCII are sent e.g 0x37 0x38 0x41 0x32 0x36 0x46. i can do the processing in the uC and perform some checks to subtract 0x30 if between 0x30 and 0x39 or subtract 0x37 if between 0x41 and 0x46. but i do not want to use the uC for this calculations. i want to implement some algorithm in the GUI c# for sending the correct HEX value. So i wrote the following program. but i am getting an error. "Value was either too large or too small for an unsigned byte." at code line stating (data[2 - i] = Convert.ToByte(x*16 + y)).
I am unable to figure out this issue and fed up now as this should not happen in any case.
if anyone can help me in this regard, either with this code or any other algo/method, i will be really thankful. please, I would prefer never to implement some algo on uC.
Thanks
Maleeha
/***********************************************************************/
/*The code for opening the serial connection and converting it appropriately*/
/***********************************************************************/
byte[] conversion()
{
string text = label16.Text.ToUpper(); // if user enters not capital letters
byte[] data = new byte[3];
int x, y;
bool valid;
for (int i = 2; i >= 0; i--)
{
valid = true;
x = (Convert.ToInt32(Convert.ToChar(text[2 * i + 1])));
y = (Convert.ToInt32(Convert.ToChar(text[2 * i]))); // I want to first send the 0x6F then 0xA2 and finally 0x78. ToChar is so that i can check for A-F
if(x >= 48 || x <= 57) // i,e it is already a number
x = Convert.ToInt32(text[2 * i + 1]);
else if (x >= 65 || x <= 70) // it is between A-F
x = x - 55; // in case of A, i get 10
else // any other value i.e greater than F or any other.
{
valid = false;
break;
}
if (y >= 48 || y <= 57) // same for y
y = Convert.ToInt32(text[2 * i]);
else if (y >= 65 || y <= 70)
y = y - 55;
else
{
valid = false;
break;
}
if (valid == true)
data[2 - i] = Convert.ToByte(x*16 + y); // max will be 15*16 + 15 = 255 which should be OK for convert.ToByte.
}
return data;
}
void serial(byte[] text)
{
SerialPort serialPort1 = new SerialPort();
//configuring the serial port
serialPort1.PortName = "COM1";
serialPort1.BaudRate = 9600;
serialPort1.DataBits = 8;
serialPort1.Parity = Parity.None;
serialPort1.StopBits = StopBits.One;
//opening the serial port
serialPort1.Open();
//write data to serial port
serialPort1.Write(text, 0, 3);
//close the port
serialPort1.Close();
}
/***********************************************************************/
private void button3_Click(object sender, EventArgs e)
{
byte[] data = conversion();
serial(data);
}
The .NET framework already supports converting hex strings. Make your code look like this:
uint value;
if (!uint.TryParse(label16.Text, // Ought to be a text box
System.Globalization.NumberStyles.HexNumber, null, out value)) {
MessageBox.Show("Invalid hex value");
return;
}
serialPort1.Write(BitConverter.GetBytes(value), 0, 3);
Can you use the built in methods?
byte[] conversion()
{
string text = label16.Text;
for (int i = 0; i < text.length - 1; i+=2) //Make sure to increment by 2, currently ignores a trailing char.
{
string hex = text.Substring(i * 2, 2);
data[i / 2] = Convert.ToByte(hex, 16);
}
return data;
}
Not the cleanest code, but you get the idea.
You should wrap the data[i / 2] = Convert.ToByte(hex, 16); line in a try catch, but I am not sure if you want to do that for the line or just call the method in a try catch.
The problem with your code seems to be the lines x = Convert.ToInt32(text[2 * i + 1]); and y = Convert.ToInt32(text[2 * i]); which are converting the char directly to an int. to get your solution to work you should do something like x = ((byte)text[2 * i + 1]) - 48;
Your call to Convert.ToInt32() isn't doing what you think it's doing.
Here's an overview on different usages of Convert.ToInt32():
http://msdn.microsoft.com/en-us/library/bb311038.aspx
There are three problems with the logic:
Look at your if statements that determine if x and y fall within certain number ranges. Consider what happens if x = 100. Remember that || means "OR".
The conversion if x or y is a character representing a number using Convert.ToInt32() needs to take a string, not a character, in order to get the conversion you're looking for.
Once you get past those two, examine your output of your conversion() method. You should notice the final issue.

VB6: How are binary files encoded? using Put statement

I have this code
Open WritingPath & "\FplDb.txt" For Random As #1 Len = Len(WpRec)
For i = 1 To 99
WpRec.WpIndex = FplDB(i, 1)
WpRec.WpName = FplDB(i, 2)
WpRec.WpLat = FplDB(i, 3)
WpRec.WpLon = FplDB(i, 4)
WpRec.WpLatDir = FplDB(i, 5)
WpRec.WpLonDir = FplDB(i, 6)
Put #1, i, WpRec
Next i
Close #1
SaveOk = 1
FplSave = SaveOk
Exit Function
This function makes binary serialization of a matrix of 99 structs (WpRec) to file, using "Open" and "Put" statements. But I didn't get how it is encoded... It is important to me because I need to rewrite the same serialization in C# but I need to know what encoding method is used for that so I can do the same in C#....
The tricky bit in VB6 was that you were allowed to declare structures with fixed length strings so that you could write records containing strings that didn't need a length prefix. The length of the string buffer was encoded into the type instead of needing to be written out with the record. This allowed for fixed size records. In .NET, this has kind of been left behind in the sense that VB.NET has a mechanism to support it for backward compatibility, but it's not really intended for C# as far as I can tell: How to declare a fixed-length string in VB.NET?.
.NET seems to have a preference for generally writing out strings with a length prefix, meaning that records are generally variable-length. This is suggested by the implementation of BinaryReader.ReadString.
However, you can use System.BitConverter to get finer control over how records are serialized and de-serialized as bytes (System.IO.BinaryReader and System.IO.BinaryWriter are probably not useful since they make assumptions that strings have a length prefix). Keep in mind that a VB6 Integer maps to a .NET Int16 and a VB6 Long is a .Net Int32. I don't know exactly how you have defined your VB6 structure, but here's one possible implementation as an example:
class Program
{
static void Main(string[] args)
{
WpRecType[] WpRec = new WpRecType[3];
WpRec[0] = new WpRecType();
WpRec[0].WpIndex = 0;
WpRec[0].WpName = "New York";
WpRec[0].WpLat = 40.783f;
WpRec[0].WpLon = 73.967f;
WpRec[0].WpLatDir = 1;
WpRec[0].WpLonDir = 1;
WpRec[1] = new WpRecType();
WpRec[1].WpIndex = 1;
WpRec[1].WpName = "Minneapolis";
WpRec[1].WpLat = 44.983f;
WpRec[1].WpLon = 93.233f;
WpRec[1].WpLatDir = 1;
WpRec[1].WpLonDir = 1;
WpRec[2] = new WpRecType();
WpRec[2].WpIndex = 2;
WpRec[2].WpName = "Moscow";
WpRec[2].WpLat = 55.75f;
WpRec[2].WpLon = 37.6f;
WpRec[2].WpLatDir = 1;
WpRec[2].WpLonDir = 2;
byte[] buffer = new byte[WpRecType.RecordSize];
using (System.IO.FileStream stm =
new System.IO.FileStream(#"C:\Users\Public\Documents\FplDb.dat",
System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
{
WpRec[0].SerializeInto(buffer);
stm.Write(buffer, 0, buffer.Length);
WpRec[1].SerializeInto(buffer);
stm.Write(buffer, 0, buffer.Length);
WpRec[2].SerializeInto(buffer);
stm.Write(buffer, 0, buffer.Length);
// Seek to record #1, load and display it
stm.Seek(WpRecType.RecordSize * 1, System.IO.SeekOrigin.Begin);
stm.Read(buffer, 0, WpRecType.RecordSize);
WpRecType rec = new WpRecType(buffer);
Console.WriteLine("[{0}] {1}: {2} {3}, {4} {5}", rec.WpIndex, rec.WpName,
rec.WpLat, (rec.WpLatDir == 1) ? "N" : "S",
rec.WpLon, (rec.WpLonDir == 1) ? "W" : "E");
}
}
}
class WpRecType
{
public short WpIndex;
public string WpName;
public Single WpLat;
public Single WpLon;
public byte WpLatDir;
public byte WpLonDir;
const int WpNameBytes = 40; // 20 unicode characters
public const int RecordSize = WpNameBytes + 12;
public void SerializeInto(byte[] target)
{
int position = 0;
target.Initialize();
BitConverter.GetBytes(WpIndex).CopyTo(target, position);
position += 2;
System.Text.Encoding.Unicode.GetBytes(WpName).CopyTo(target, position);
position += WpNameBytes;
BitConverter.GetBytes(WpLat).CopyTo(target, position);
position += 4;
BitConverter.GetBytes(WpLon).CopyTo(target, position);
position += 4;
target[position++] = WpLatDir;
target[position++] = WpLonDir;
}
public void Deserialize(byte[] source)
{
int position = 0;
WpIndex = BitConverter.ToInt16(source, position);
position += 2;
WpName = System.Text.Encoding.Unicode.GetString(source, position, WpNameBytes);
position += WpNameBytes;
WpLat = BitConverter.ToSingle(source, position);
position += 4;
WpLon = BitConverter.ToSingle(source, position);
position += 4;
WpLatDir = source[position++];
WpLonDir = source[position++];
}
public WpRecType()
{
}
public WpRecType(byte[] source)
{
Deserialize(source);
}
}
Add a reference to Microsoft.VisualBasic and use FilePut
It is designed to assist with compatibility with VB6
The VB6 code in your question would be something like this in C# (I haven't compiled this)
Microsoft.VisualBasic.FileOpen (1, WritingPath & "\FplDb.txt", OpenMode.Random,
RecordLength:=Marshal.SizeOf(WpRec))
for (i = 1; i < 100 ; i++) {
WpRec.WpIndex = FplDB(i, 1)
WpRec.WpName = FplDB(i, 2)
WpRec.WpLat = FplDB(i, 3)
WpRec.WpLon = FplDB(i, 4)
WpRec.WpLatDir = FplDB(i, 5)
WpRec.WpLonDir = FplDB(i, 6)
Microsoft.VisualBasic.FilePut(1, WpRec, i)
}
Microsoft.VisualBasic.FileClose(1)
I think Marshal.SizeOf(WpRec) returns the same value that Len(WpRec) will return in VB6 - do check this though.
The put statement in VB6 does not do any encoding. It saves a structure just as it is stored internally in memory. For example, put saves a double as a 64-bit floating point value, just as it is represented in memory. In your example, the members of WpRec are stored in the put statement just as WpRec is stored in memory.

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;
}

Programmatically check if a number is a palindrome

This sounds like homework, yes it is (of someone else), I asked a friend of mine who is learning C# to lend me some of his class exercises to get the hang of it.
So as the title says: How can I check if a number is a Palindrome?
I'm not asking for source code (although its very useful), but rather that someone explained how should the code should work, so that it can be applied to many different languages.
The Solution:
#statikfx searched SO for this and found the solution.
n = num;
while (num > 0)
{
dig = num % 10;
rev = rev * 10 + dig;
num = num / 10;
}
// If (n == rev) then num is a palindrome
I check for palindromes by converting the integer to a string, then reversing the string, then comparing equality. This will be the best approach for you since you're just starting out.
Since you're working in C# and this is homework, I'll use very obscure-looking Python that won't help you:
def is_palindrome(i):
s = str(i)
return s[::-1] == s
Convert that to C# and you'll have your answer.
Main idea:
Input number: 12321
Splitting the digits of the number, put them into an array
=> array [1, 2, 3, 2, 1]
Check if array[x] = array[arr_length - x] for all x = 0..arr_length / 2
If check passed => palindrome
There are many ways. Probably the simplest is to have 2 indexes, i at beginning and j at end of number. You check to see if a[i] == a[j]. If so, increment i and decrement j. You stop when i > j. When looping if you ever reach a point where a[i] != a[j], then it's not a palindrome.
Here's some working code. The first function tests if a number is palidromic by converting it to a string then an IEnumerable and testing if it is equal to its reverse. This is enough to answer your question. The main function simply iterates over the integers testing them one by one.
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
public static bool IsPalindromic(long l)
{
IEnumerable<char> forwards = l.ToString().ToCharArray();
return forwards.SequenceEqual(forwards.Reverse());
}
public static void Main()
{
long n = 0;
while (true)
{
if (IsPalindromic(n))
Console.WriteLine("" + n);
n++;
}
}
}
Update: Here is a more direct method of generating palindromes. It doesn't test numbers individually, it just generates palindromes directly. It's not really useful for answering your homework, but perhaps you will find this interesting anyway:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
public static void Main()
{
bool oddLength = true;
ulong start = 1;
while (true)
{
for (ulong i = start; i < start * 10; ++i)
{
string forwards = i.ToString();
string reverse = new string(forwards.ToCharArray()
.Reverse()
.Skip(oddLength ? 1 : 0)
.ToArray());
Console.WriteLine(forwards + reverse);
}
oddLength = !oddLength;
if (oddLength)
start *= 10;
}
}
}
My solution:
bool IsPalindrome(string str)
{
if(str.Length == 1 || str.Length == 0) return true;
return str[0] == str[str.Length-1] && IsPalindrome(str.Substring(1,str.Length-2));
}
Here's some pseudocode:
function isPalindrome(number) returns boolean
index = 0
while number != 0
array[index] = number mod 10
number = number div 10
index = index + 1
startIndex = 0;
endIndex = index - 1
while startIndex > endIndex
if array[endIndex] != array[startIndex]
return false
endIndex = endIndex - 1
startIndex = startIndex + 1
return true
Note that that's for base 10. Change the two 10s in the first while loop for other bases.
The following function will work for both numbers as well as for strings.
public bool IsPalindrome(string stringToCheck)
{
char[] rev = stringToCheck.Reverse().ToArray();
return (stringToCheck.Equals(new string(rev), StringComparison.OrdinalIgnoreCase));
}
zamirsblog.blogspot.com
in theory you want to convert the number to a string. then convet the string to an array of characters and loop the array comparing character (i) with character (array length - i) if the two characters are not equal exit the loop and return false. if it makes it all the way through the loop it is a Palindrome.
Interesting. I'd probably convert the number to a string, and then write a recursive function to decide whether any given string is a palendrome.
int n = check_textbox.Text.Length;
int check = Convert.ToInt32(check_textbox.Text);
int m = 0;
double latest=0;
for (int i = n - 1; i>-1; i--)
{
double exp = Math.Pow(10, i);
double rem = check / exp;
string rem_s = rem.ToString().Substring(0, 1);
int ret_rem = Convert.ToInt32(rem_s);
double exp2 = Math.Pow(10, m);
double new_num = ret_rem * exp2;
m=m+1;
latest = latest + new_num;
double my_value = ret_rem * exp;
int myvalue_int = Convert.ToInt32(my_value);
check = check - myvalue_int;
}
int latest_int=Convert.ToInt32(latest);
if (latest_int == Convert.ToInt32(check_textbox.Text))
{
MessageBox.Show("The number is a Palindrome number","SUCCESS",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
else
{
MessageBox.Show("The number is not a Palindrome number","FAILED",MessageBoxButtons.OK,MessageBoxIcon.Exclamation);
}
public class Main {
public static boolean Ispalindromic(String word) {
if (word.length() < 2) {
return true;
}
else if (word.charAt(0) != word.charAt(word.length() - 1)) {
return false;
} else {
Ispalindromic(word.substring(1, word.length() - 1));
}
return true;
}
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
String word = sc.nextLine();
System.out.println(Ispalindromic(word) ? "it is palidromic" : "it is not palidromic");
}
}
This is my solution coming from a beginner:
Console.Write("Enter a number to check if palindrome: ");
bool palindrome = true;
int x = int.Parse(Console.ReadLine());
/* c is x length minus 1 because when counting the strings
length it starts from 1 when it should start from 0*/
int c = x.ToString().Length - 1;
string b = x.ToString();
for (int i = 0; i < c; i++)
if (b[i] != b[c - i])
palindrome = false;
if (palindrome == true)
Console.Write("Yes");
else Console.Write("No");
Console.ReadKey();
You need to reverse the number then compare the result to the original number.
If it matches, you have a palindrome. It should work irrespective of the number being even, odd or symmetric.
public static bool IsNumberAPalindrome(long num)
{
return long.Parse(string.Join("", num.ToString().ToCharArray().Reverse().ToArray())) == num ? true : false;
}
The implementation is bellow:
public bool IsPalindrome(int x) {
string test = string.Empty;
string res = string.Empty;
test = x.ToString();
var reverse = test.Reverse();
foreach (var c in reverse)
{
res += c.ToString();
}
return test == res;
}
You have a string, it can have integers, it can have characters, does not matter.
You convert this string to an array, depending on what types of characters the strings consist of, this may use to toCharArray method or any other related method.
You then use the reverse method that .NET provides to reverse your array, now you have two arrays, the original one and the one you reversed.
You then use the comparison operator (NOT THE ASSIGNMENT OPERATOR!) to check if the reversed one is the same as the original.
something like this
bool IsPalindrome(int num)
{
var str = num.ToString();
var length = str.Length;
for (int i = 0, j = length - 1; length/2 > i; i++, j-- ){
if (str[i] != str[j])
return false;
}
return true;
}
you could even optimise it

Categories