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