Separating IP nodes
John W. Baxter
jwbnews at scandaroon.com
Mon Sep 4 12:46:53 EDT 2000
In article <8ovl6i0h2p at news2.newsguy.com>, "Alex Martelli"
<aleaxit at yahoo.com> wrote:
> "Kevin Breit" <battery841 at remove.for.no.spam.mypad.com> wrote in message
> news:SnFs5.137$1U.21639 at elnws01...
> > Hey,
> > In my app, I have a user enter an IP address. Great. Now, I want to
> > increment the last number. For example:
> > 1.1.1.1 becomes 1.1.1.2 (yes...thats an odd IP)
> > What is the best way to separate that and increment only the last
> > number?
> > I'm thinking some sort of regex, but not sure.
>
> The simplest approach (and simplest is often close to best:-) is
> to divide the task into steps:
> a) split the IP-address string into dot-separated components
> b) increment the rightmost number component
> c) join the components up again
>
> In pseudocode, using [-1] to indicate the last item of a list and
> taking into account integer/string distinctions:
> components = string.split(IPaddress, '.')
> components[-1] = str(1+int(components[-1]))
> IPaddress = string.join(components, '.')
I, the user, elected to enter "1.1.1.255". Oops. If 1.1.1.256 is going
to be caught later, no problem. And it should be caught later, after
dealing with the user error of putting in
"192.168.270.10"
instead of the intended
"192.168.27.10"
My temptation would be to convert the dotted string form of the IP
address to a (long) integer, catching errors, add one, and convert back
to a dotted string (catching the error that the user put in
255.255.255.255 which has become the pseudo IP 1.0.0.0.0).
Functions (methods) to do this are in...(oops, as I've never needed
them, I had to try to find the code...and I've failed so far).
In that case, one can easily write the needed checking code in string
form, which would go before the increment, and then manage the possible
overflow.
It may be tempting to say that "a trailing 255 byte is an error, since
it is the broadcast address for a class C". But it may not be a
broadcast, if we're not in a Class C environment...I got an x.y.z.255 IP
address assigned by one of my ISPs (I was making repeated connections to
learn the extent of their IP pool, and got lucky: their Ascend Max has
a supernetted pool (four C's, I think)).
But '255.255.255.255' is an error (both before and after the increment).
>
> As it happens, this so-called pseudocode is perfectly valid Python
> code. Just slap a 'def inclast(IPaddress):' first line, and a
> 'return IPaddress' last line, and you have a working Python function
> (actually, you'll "return string.join" at the end rather than binding
> the result to IPaddress and returning it -- more concise & readable).
>
> Of course, one can do better -- if it's worth it (it normally isn't:
> will saving a microsecond's worth of execution time on this function
> substantially increase your quality of life...?). Here, we split
> the IP address into 4 parts, while we're only really interested in
> _two_ parts -- everything up to the *last* dot, and, everything
> *after* it. In more detail (and, in "pseudocode" again:-)...:
> startOfLast = 1 + string.rindex(IPaddress, '.')
> lastComponent = 1 + int(IPaddress[startOfLast:])
> IPaddress = IPaddress[:startOfLast] + str(lastComponent)
> here, too, it's easy to make this 'pseudocode' a working Python function.
>
> I find both solutions equally acceptable in terms of clarity and
> directness; which one you come up with will depend on how you
> conceptualize the problem. Performance, if it matters, should be
> *MEASURED*, *NOT* "guessed-at": program performance characteristics
> more often than not surprise even 'trained' intuition... there is
> really no substitute for measurement. I have a slight preference
> for the latter approach, but that may be because it's the _second_
> one that came to mind:-); I've done no measurements, because I think
> it's unlikely that performance matters here (and no tests, because
> I'm a pretty lazy guy:-).
Um...we just waited several million microseconds for the user to type in
an IP address. Does a difference of a few microseconds in processing
time matter here? The best perfomance enhancement here is to get a
faster, more accurate user.
[At the same time, we don't want such poor performance that the user
sees a delay after hitting Enter, before whatever is next. Won't
happen, at least as a result of the incrementing and checking] ;-)]
>
> Don't use regular expressions unless you truly need them for clear
> and simple solution of a given problem; they're often overkill, when
> something, as here, can be handled via string-level manipulation.
>
> Each solution can of course be expressed more compactly (shortening
> variable names, merging expressions into one, ...), but there is
> really no advantage in this. The readability and self-documenting
> qualities can easily be lost, without compensating advantage.
And, as an afterthought related to design, it's probably time to provide
for IPv6 addresses, or at least to note in a comment that the code has
to be revisited when IPv6 is needed.
--John
--
John W. Baxter Port Ludlow, WA USA jwbnews at scandaroon.com
More information about the Python-list
mailing list