Calculate / add to hex values with only certain characters - vb.net

Hi i am working on a program communicating with a SPS via SerialPort.
There's some values i need to calculate and send to the SPS.
This SPS does it the following: It only uses A-F, 8, 9. So A,B,C....F,8,9, then starts with "A" again.
That means if the SPS does F + 2 it will be 9.
F + 3 would be A.
Obviously F + 2 in vb.net gives me "11".
I am just doing "[Value] + &Hxx".
What would be a simple way to get it calculating as the SPS does? (A-F, 8, 9 only)
TiA

E.g.
Private values As Byte() = {&HA, &HB, &HC, &HD, &HE, &HF, &H8, &H9}
Sub Main()
Console.WriteLine(Add(&HA, 3).ToString("X"))
Console.WriteLine(Add(&HF, 5).ToString("X"))
Console.WriteLine(Add(&H9, 25).ToString("X"))
End Sub
Private Function Add(startingValue As Byte, steps As Integer) As Byte
Dim startingIndex = Array.IndexOf(values, startingValue)
Dim finalIndex = (startingIndex + steps) Mod values.Length
Dim finalValue = values(finalIndex)
Return finalValue
End Function

Related

How do i pick out specific strings from a user input?

I want to make the user input a 3 digit number (100 - 999), then take out the 1st digit, 2nd and 3rd and say what unit it belongs to
e.g.
567 will make
5 hundreds
6 tens
7 ones
I've tried mid and right but mid shows me all my units and right only works for the ones
Im stuck on the tens
Module Module1
Dim Num As Integer
Sub Main()
Console.WriteLine("Enter a number between 100 and 999")
Num = CStr(Console.ReadLine)
Console.Write(Left(Num, 1))
Console.Write(" Hundreds")
Console.WriteLine(Mid(Num, 1))
Console.Write(" Tens")
Console.WriteLine(Right(Num, 1))
Console.Write(" One's")
Console.ReadKey()
End Sub
End Module
Use string.SubString.
For example:
Dim strNumber As String = Num.ToString()
Dim hundreds As String = strNumber.SubString(0, 1) 'shows the hundreds.
Dim tens As String = strNumber.SubString(1, 1) 'shows the tens.
Dim ones As String = strNumber.SubString(2, 1) 'the ones.
As somebody commented on your question:
In your case since you only want one digit to return you can access the strings char array and return the char at position X like so:
Dim strNumber As String = Num.ToString()
Dim hundreds As String = strNumber(0)
Dim tens As String = strNumber(1)
Dim ones As String = strNumber(2)

Convert 32-bit signed integer to 64-bit integer while preserving the exact bits

I have a 32-bit value that is stored in the VB.Net type Integer (i.e. Int32.) I am only interested in the bits - not the numerical value. Sometimes the 32nd bit is a one which is interpreted as a negative number. My goal is to reverse the actual bits. My original data is encoded into bits right-to-left (LSB right-most) and is read back in left-to-right (MSB left-most.) I am adapting someone else's code and design. One thought I had was maybe to convert to a long temporarily but I don't know how to do that and preserve the 32nd bit correctly.
Public Shared Function ReverseBits32(ByVal n As Integer) As Integer
Dim result As Integer = 0
For i As Integer = 0 To 32 - 1
result = result * 2 + n Mod 2
n = n >> 1 'n Or 2
Next
Return result
End Function
If you had a method to reverse the bits of a byte you could apply it four times to the bytes of an integer. A little research finds Bit Twiddling Hacks.
Module Module1
Sub ShowBits(a As Integer)
Dim aa = BitConverter.GetBytes(a)
Console.WriteLine(String.Join(" ", aa.Select(Function(b) Convert.ToString(b, 2).PadLeft(8, "0"c))))
End Sub
Function ReverseBits(b As Byte) As Byte
' From https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits
Dim c = CULng(b)
Return CByte((((c * &H802UL And &H22110UL) Or (c * &H8020UL And &H88440UL)) * &H10101UL >> 16) And &HFFUL)
End Function
Function ReverseBits(a As Integer) As Integer
Dim bb = BitConverter.GetBytes(a)
Dim cc(3) As Byte
For i = 0 To 3
cc(3 - i) = ReverseBits(bb(i))
Next
Return BitConverter.ToInt32(cc, 0)
End Function
Sub Main()
Dim y = -762334566
ShowBits(y)
y = ReverseBits(y)
ShowBits(y)
Console.ReadLine()
End Sub
End Module
Output from test value:
10011010 10110010 10001111 11010010
01001011 11110001 01001101 01011001
I used the "no 64-bit" method because it is written for a language where arithmetic overflow is ignored - the methods using 64-bit operations rely on that but it is not the default for VB.NET.

VB6 comparing only numeric characters in srings

I need to compare phone numbers from a CSV file to phone numbers in an SSMS database in VB6 without using the .Net Library. One may have a number as 555-555-5555 and the other may have the same number as (555) 555-5555 which obviously kicks back as different when strings are compared.
I know I can use for loops and a buffer to pull out only numeric characters like:
Public Function PhoneNumberNumeric(PhoneNumberCSV As String) As String
Dim CharNdx As Integer
Dim buffer As String
For CharNdx = 1 To Len(PhoneNumberCSV) Step 1
If IsNumeric(Mid(PhoneNumberCSV, CharNdx, 1)) Then
buffer = buffer + Mid(PhoneNumberCSV, CharNdx, 1)
End If
Next
PhoneNumberNumeric = buffer
End Function
but this is expensive. Is there a less expensive way to do this?
This should be a bit quicker:
Private Function Clean(ByRef Original As String) As String
Dim I As Long
Dim J As Long
Dim Char As Long
Clean = Space$(10)
For I = 1 To Len(Original)
Char = AscW(Mid$(Original, I, 1))
If 48 <= Char And Char <= 57 Then
J = J + 1
If J > 10 Then Exit For 'Or raise an exception.
Mid$(Clean, J, 1) = ChrW$(Char)
End If
Next
End Function
It avoids string concatenation, ANSI conversions, and VBScript-form "pigeon VB" (use of slow Variant functions).

Read binary values (such 1000, 1001, 1010, 1011...) as an array of digits

I am in search of a solution for the following task:
General environment: I am working on a toolbox of VBA functions to process data in an Access database of educational offers. This includes various string operations and operations with database fields mostly via SQL.
In one of my functions, I have to deal with different states of four database fields in a row, their values being NULL or not NULL. As each field can be either NULL or not NULL, we have 16 possible situations:
0-0-0-0, 0-0-0-1, 0-0-1-0, 0-0-1-1 and so on,
which is obviously quite the same as:
0000, 0001, 0010, 0011, 0100, ..., 1111, i.e. binary representation of decimal 0-15.
In order to not hard code every single case, I want make use of the binary representations of numbers 0-15 by counting up from 0 to 15.
In pseudocode:
i = 0
For i = 0 To 15
arrX(): 0000
StateOfField01 = arrX(0) [which is 0, in this case]
StateofField02 = arrX(1) [dito]
StateOfField03 = arrX(2) [dito]
StateofField04 = arrX(3) [dito]
Do something with the fields, depending on their state
i = i + 1
Next i
So far I am happy with my idea, but there is one thing I have no idea how to solve:
How can I get from the binary representations of i an array containing four digits each?
Here is a function which will convert a Decimal number to Binary String.
Public Function GetBinary(Number As Long) As String
'********************
'Code Courtesy of
' Paul Eugin
'********************
Dim resultStr As String, nLen As Integer
Do While Number > 0
resultStr = resultStr & (Number Mod 2)
Number = Int(Number / 2)
Loop
GetBinary = Format(StrReverse(resultStr), "0000")
End Function
The function will take in a "Number" as argument for which you want to find the Binary equivalent. The Format function at the end of the code will make sure the return would be a minimum of 4 literal representation. So if you pass the example,
? GetBinary(5)
0101
Based on PaulFrancis' input, I found the following solution answering my proper needs.
Important additions are 1) "ByVal" for the argument in the call so that the function can be called from inside another procedure whose for-next counter should be preserved; 2) a test for "Number" being 0 which was not covered previously.
Public Function GetBinary(ByVal Number As Integer) As String
Dim resultStr As String
If Number = 0 Then
resultStr = "0"
Else
Do While Number > 0
resultStr = resultStr & (Number Mod 2)
Number = Int(Number / 2)
Loop
End If
GetBinary = Format(StrReverse(resultStr), "0000")
End Function
'-----------------------------------
Public Sub TestBinaryToString()
'Purpose: Testing the GetBinary() function:
'output will be displayed in the Immediate Window
Dim i As Integer
Dim strBin As String
For i = 0 To 15
strBin = GetBinary(i)
Debug.Print i; " --> "; strBin
Next i
End Sub

How to reverse this algorithm to get back the original text? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
Can anyone please explain with the easy coding how to reverse this algorithm so that I get back the original text string?
Public Function CreateIntChecksum(ByVal s As String) As Integer
Dim r As Integer = 0
For i As Integer = 0 To (s.Length() - 1)
Dim bchar As Byte = Convert.ToByte(s(i))
r = bchar + ((r << 5) - r)
Next
Return r
End Function
Although it is impossible to find the original text, it is possible find a preimage easily. The crucial point is
r = bchar + ((r << 5) - r)
which is equivalent to
r = bchar + r*31
Therefore, the hash encodes the string in base-31. To find a preimage, just rewrite the integer in base 31.
For instance, if the result is 3456, we know 3456 = 3 × 312 + 18 × 31 + 15, so one possible original text is "\x03\x12\x0f". Of course, we could rearrange the numbers to give 110 × 31 + 46 ("n.") or 109 × 31 + 77 ("mM") etc, which shows there is no unique preimage.
You can't. What you have here is a Checksum, which is a basic hashing function. The the whole point of a hashing function is that it is irreversible. Hashing functions map a set of inputs (usually infinite) to a smaller set of outputs - so multiple inputs can end up with the same output, and thus this makes reversing a hash impossible (assuming the hash is correctly done). This is why they are used to store passwords - there is no way to read a hash and go "Oh, that is password XYZ".
One way of trying to find out the original value is to use a Rainbow Table. This is merely a massive table of inputs and their equivalent hashed (or in this case checksummed) values. If you have the hashed value of your unknown string you can search for it in the table and get the set of possible inputs. This is not a way to reverse a hash function, which is impossible; it is merely a brute force guessing method. Note also that in this case (assuming the hashing function is not biased) there are an infinite number of strings that match each checksummed value, as a visual basic string can be of arbitrary length. This would make a rainbow table for this very impractical - you could cover the set of probably inputs for a hashing (as most normal users won't enter more than a 10 character code), but nothing stops the user using a 67 character code, or 109, or...
Read the wikipedia articles for Hash Functions, Checksums and Rainbow Tables.
how to reverse this algorithm so that I get back the original text string?
You can't, by design.
This is a (simple) checksum or hashing function.
Take a look at the size of the information going in and out: the function transforms a string s of arbitrary length into a 32-bit Integer. For each integer value there will be many input strings that will yield that result.
Edit: Apparently you want a shuffling algorithm. Maybe take a look at ROT13. Be advised this is not a (very) safe form of encryption.
You simply can't reverse it. It's a checksum which is not reversible.
You can't. If nothing else, then simply because Integer contains only 32 bits of data and String can have any length.
First of all the code as posted will throw an exception for anything but the shortest of strings.
The following code includes the OP's original code, plus a simple checksum, and a guess at how the checksum might be used.
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Dim buffer() As Byte
Dim tstString As String = "Calculate a checksum for a given string"
Dim chkSumFix As Integer = CreateIntChecksumFixed(tstString) 'get a checksum
buffer = SendPacket(tstString, chkSumFix) 'create a byte buffer to send
tstString = decodePacket(buffer)
'do the same using the OP's original code
Dim chkSum As Integer = CreateIntChecksum(tstString) 'error
buffer = SendPacket(tstString, chkSum)
End Sub
'OP
Public Function CreateIntChecksum(ByVal s As String) As Integer
Dim r As Integer = 0
For i As Integer = 0 To (s.Length() - 1)
Dim bchar As Byte = Convert.ToByte(s(i))
r = bchar + ((r << 5) - r)
Next
Return r
End Function
'a very simple checksum
Public Function CreateIntChecksumFixed(ByVal s As String) As Integer
Dim r As Integer = 0
For i As Integer = 0 To (s.Length() - 1)
Dim bchar As Byte = Convert.ToByte(s(i))
r = (r And &HFFFF) + bchar
Next
Return r
End Function
Private Function SendPacket(ByVal aString As String, _
ByVal aChecksum As Integer) As Byte()
'construct a packet to be sent
'Packet format
'returns a byte buffer
'byte(0 -3) = length of original string - use BitConverter.ToInt32 to extract
'byte(4-n) = original string. n = (4 + string length) - 1
'byte(n + 1, n + 2, n + 3, n + 4) = checksum
Dim length As Integer
Dim retV As New List(Of Byte)
retV.AddRange(System.Text.Encoding.ASCII.GetBytes(aString)) 'add string to packet
length = retV.Count 'get length - use this length in case a different encoding is used
retV.AddRange(BitConverter.GetBytes(aChecksum)) 'add checksum
retV.InsertRange(0, BitConverter.GetBytes(length)) 'insert length at start of packet
Return retV.ToArray
End Function
Private Function decodePacket(ByVal buffer As Byte()) As String
Dim sLen As Integer = BitConverter.ToInt32(buffer, 0)
If sLen + 8 <> buffer.Length Then Throw New ArgumentOutOfRangeException
Dim s As String = System.Text.Encoding.ASCII.GetChars(buffer, 4, sLen)
Dim chksum As Integer = CreateIntChecksumFixed(s)
Dim embeddedChecksum As Integer = BitConverter.ToInt32(buffer, sLen + 4)
If chksum <> embeddedChecksum Then Throw New ArgumentException("Invalid checksum")
Return s
End Function