Convert IPv4 dotted quad into four decimal values
#1
A trivially easy way to enter an IPv4 address into qb64, and extract the four decimals values 0-255 which make up the address, is to use commas as delimiters for each byte of the address. I've done that, and my program (to convert an IP multicast address into its derived MAC group address, per RFC 1112) works fine that way.

What would be even better is to be able to enter the IP address in its conventional form, with . instead of , for delimiters. So for example, given the multicast address

239.255.128.1

I'm now entering it as

239,255,128,1

It's okay, super easy to parse, but not really nice.

So far, I have this. It inputs the dotted quad as a single string variable, then changes the dots into commas, so that hopefully the four decimal numbers can be easily parsed by qb64. Just trying to figure out an easy way to make the ASCII list of numbers and commas, which you see in the output, into four separate decimal numbers. I'm not proficient in all the niceties of how numbers and characters can be converted in qb64. Any super clever ideas out there? There usually are.

Code: (Select All)
Dim num(100), char$(100)
Input "Enter quad decimal IP multicast group ->", addr$
Print addr$
length = Len(addr$)
i = 0
Do
    i = i + 1
    num(i) = Asc(addr$, i)
    If num(i) = 46 Then num(i) = 44
    If i = length Then Exit Do
Loop
For i = 1 To length
    char$(i) = Chr$(num(i))
    Print num(i), char$(i)
Next i
Reply
#2
Ah, I figured out one way to do this. Break up the string variable into its separate characters, as I have already done, then use

digit(j) = Val(char$(i))

to build up the decimal value of each byte of the address. I don't even need to change every dot to a comma. I loop through each address byte until I reach a dot delimiter, and build up the decimal value of that byte. Then move on from there to the next dot delimiter, build up that decimal value. There might be a more clever way, but at least I got this way to work perfectly. Not that much code, once I'm done cleaning it up. Also have to build in checks, to make sure not to exceed valid values.
Reply
#3
If all you need to do is break it up into byte values, then something simple like this:

Code: (Select All)
_Font _LoadFont("courbd.ttf", 32, "monospace")




Do
    Input "Enter quad decimal IP multicast group ->", addr$

    GetIPv4 addr$, a, b, c, d
    Print a, b, c, d
Loop until addr$ = ""
SYSTEM

Sub GetIPv4 (temp$, a1, a2, a3, a4)
    text$ = temp$
    GoSub find_v
    a1 = V
    GoSub find_v
    a2 = V
    GoSub find_v
    a3 = V
    GoSub find_v
    a4 = V
    Exit Sub


    find_v:
    p = InStr(text$, ".")
    If p <> 0 Then
        V = Val(Left$(text$, p))
        text$ = Mid$(text$, p + 1)
    Else
        V = Val(text$)
    End If
    Return
End Sub


(And you could simplify that even more, if you just passed it an array to store the values and then ran it in a simple FOR loop.)
Reply
#4
Thanks Steve. That works really well too.  (Except for the gymongous font you use.) I have to save it for future use. Thanks again.
Reply
#5
Sorry. The version of QB64-PE that I've been testing stuff on doesn't have any DPI Awareness on it, so images don't scale to my 4k screen. An itsy-bitsy 16x8 font is much too small to read anything on, so I've got to scale them up manually like that. Wink

The good thing about the above is your error checking -- you only need a single line for IF v < 0 OR v > 255 THEN ERROR 5: EXIT SUB
Reply
#6
@bert22306 Hi! Here is some Win32 code you can use to convert a string IPv4 address to a 4 byte representation:

Code: (Select All)
Option Explicit
$NoPrefix
$Console:Only

Type in_addr
    As Unsigned Byte b1, b2, b3, b4
End Type

Declare Dynamic Library "ntdll"
    Sub RtlIpv4StringToAddress Alias "RtlIpv4StringToAddressA" (ByVal S As Offset, Byval Strict As Byte, Byval Terminator As Offset, Byval Addr As Offset)
End Declare

'Dim As Unsigned Byte ipv4(0 To 3)   'you can also just pass in the offset to this array and just iterate through it
Dim As in_addr ipv4
Dim As String Terminator

Dim As String ip: ip = "192.168.0.1" + Chr$(0)
RtlIpv4StringToAddress Offset(ip), 0, Offset(Terminator), Offset(ipv4)

'Dim As Unsigned Long i 'if you plan on iterating through the array
'For i = 0 to 3
'Print ipv4(i),
'Next

Print ipv4.b1, ipv4.b2, ipv4.b3, ipv4.b4
Ask me about Windows API and maybe some Linux stuff
Reply
#7
Thanks, Spriggsy, I did make this work after I posted that, in a somewhat different way.
Reply




Users browsing this thread: 2 Guest(s)