7

I have an IP address in char type Like char ip = "192.123.34.134" I want increment the last value (134). Does anyone how should i do it? I think, i should convert it to an integer, and then back, but unfortunately i don't know how? :( I'm using C++.

Please help me!

Thanks, kampi

0

7 Answers 7

26

You can convert the IP address from a string to an integer using inet_addr, then, after manipulating it, convert it back to a string with inet_ntoa.

See the documentation for these functions for more info on how to use them.

Here's a small function that will do what you want:

// NOTE: only works for IPv4.  Check out inet_pton/inet_ntop for IPv6 support.
char* increment_address(const char* address_string)
{
    // convert the input IP address to an integer
    in_addr_t address = inet_addr(address_string);

    // add one to the value (making sure to get the correct byte orders)
    address = ntohl(address);
    address += 1;
    address = htonl(address);

    // pack the address into the struct inet_ntoa expects
    struct in_addr address_struct;
    address_struct.s_addr = address;

    // convert back to a string
    return inet_ntoa(address_struct);
}

Include <arpa/inet.h> on *nix systems, or <winsock2.h> on Windows.

Sign up to request clarification or add additional context in comments.

5 Comments

I know mine is going to be faster execution, but this answer is definitely more correct.
I'm just going to assume you mean inet_ntop instead of the deprecated inet_ntoa, right? Right?
@R. Bemrose IPv6 just complicates this question unnecessarily; the original question stated that the address would be in dotted quad format which implies IPv4 only. I'll gladly update the code if you have any suggestions for replacing the htonl/ntohl calls with something that'll work for IPv6 addresses.
I'm using Dev-C++ under Windows. If i try to compile your code, than i get an error for "in_addr_t". It seemd, that Dev-C++ doesn't recognize this type. Could you tell me, how can i solve this problem? Thanks in advance!
Just use unsigned long instead of in_addr_t. You'll also probably have to capitalize the S in s_addr (so it should look like S_addr.) I don't have access to a Windows computer at the moment, so I hope that does it.
4

Quick/Dirty!

void increment(std::string& ip)
{
    std::string::size_type dot = ip.find_last_of('.');
    std::stringstream stream(ip.substr(dot+1));
    int part = 0;

    stream >> part;

    part++;

    stream.str(""); stream.clear();

    stream << part;

    ip.replace(dot+1, std::string::npos, stream.str());
}

1 Comment

I was typing as you were coding :) My C++ skills are rusty but yours look spot on. Good show.
3
int a,b,c,d;
sscanf(str, "%d.%d.%d.%d", &a,&b,&c,&d);
sprintf(str, "%d.%d.%d.%d\0", a,b,c,d+1);

Comments

2

I would write a method that accepts a string in that format.
Convert it to 4 integers. increment. (Important Check range)
Then convert back to a string.

If you want somthing more long term and robust a class representing the IP address. Then you maintain the class an manipulate as appropraite and convert to string when needed.

#include <iostream>
#include <istream>
#include <sstream>
#include <string>
#include <stdexcept>



class MyIp
{
    struct Dot
    {};
    struct Byte
    {
        Byte(unsigned char& val)
            :m_val(val)
        {}
        unsigned char&  m_val;
    };
    friend std::istream& operator>>(std::istream& str,MyIp::Dot const& d);
    friend std::istream& operator>>(std::istream& str,MyIp::Byte const& b);
    friend std::ostream& operator<<(std::ostream& str,MyIp const& ip);
    public:
        MyIp(std::string const& ip)
        {
            std::stringstream str(ip);
            str >> Byte(ad[0]) >> Dot() >> Byte(ad[1]) >> Dot() >> Byte(ad[2]) >> Dot() >> Byte(ad[3]);
            std::string leftover;
            if (str >> leftover)
            {   throw std::runtime_error("InvalidIP: Long");
            }
        }
        void inc(int index)
        {
            if ((index >= 0) && (index <=3))
            {
                ++ad[index];
                if (ad[index] == 0)
                {
                    inc(index-1);
                }
            }
        }
    private:
        unsigned char   ad[4];
};
std::istream& operator>>(std::istream& str,MyIp::Dot const& d)
{
    char x  = str.get();
    if (x != '.')
    {   throw std::runtime_error("Invalid IP: Dot");
    }
    return str;
}
std::istream& operator>>(std::istream& str,MyIp::Byte const& b)
{
    unsigned int val;
    str >> val;
    if (!str || val > 255)
    {   throw std::runtime_error("Invalid IP: Val");
    }
    b.m_val = static_cast<unsigned char>(val);
    return str;
}
std::ostream& operator<<(std::ostream& str,MyIp const& ip)
{
    return str  << static_cast<unsigned int>(ip.ad[0])
                << "." << static_cast<unsigned int>(ip.ad[1])
                << "." << static_cast<unsigned int>(ip.ad[2])
                << "." << static_cast<unsigned int>(ip.ad[3]);
}

int main()
{
    try
    {
        std::string ip("127.0.0.1");

        MyIp    addr(ip);

        std::cout << addr << "\n";
        addr.inc(3);
        std::cout << addr << "\n";
    }
    catch(std::exception const& e)
    {
        std::cout << "What: " << e.what() << "\n";
    }
}

Comments

0

You can also use the location of the last "." and take from there to the end to convert to an int, bump it up 1, check boundaries and then convert it to a string and append to the base part.

Comments

0

This probably isn't very sane but it was fun to think about.

Since the IP address space is 32-bits you could write a function to convert IP addresses into unsigned 32-bit integers. Then you can add or subtract 1 or as much as you want, and convert back into an IP address. You wouldn't have to worry about range checking.

In pseduo-code for 192.123.34.134 you'd do:

int i = (192 << 24) + (123 << 16) + (34 << 8) + 134

More generally, for a.b.c.d:

int i = (a << 24) + (b << 16) + (c << 8) + d

Now change i as much as you want (i++, i+=10000) and convert back:

String ip = (i >> 24) + "." + 
            ((i >> 16) mod 256) + "." + 
            ((i >> 8) mod 256) + "." + 
            (i mod 256);

Excuse the syntax - I couldn't write C++ to save myself.

MK

2 Comments

That's exactly what inet_addr_t is, as in Neil's answer, so no need to roll your own. So whether it's sane or not, it's what C programmers have been doing for years...
I guess I've been in a Java world too long if I'm thinking bit-twiddling is a bit too hardcore, Thanks for the pointer! (Pun not originally intended but kept when spotted.)
-3

This site ate my tabs, so I'll try again. I'm sure there is a library to do something like this, but this should work (assuming my syntax isn't messed up) enough to get the idea across.

Pseudo Code:

char[] ipAddress= "192.123.34.134";

if (ipAddress[ipAddress.Length-1] == '9')
{
    if(ipAddress[ipAddress.Length-2]=='9')
    {
        ipAddress[ipAddress.Length-1]='0';
        ipAddress[ipAddress.Length-2]='0';
        ipAddress[ipAddress.Length-3]=(char)ipAddress[ipAddress.Length-3]+1;
    }
    else
    {
        ipAddress[ipAddress.Length-2]=(char)ipAddress[ipAddress.Length-2]+1;
        ipAddress[ipAddress.Length-1]='0';
    }
}
else
{
     ipAddress[ipAddress.Length-1]=(char)ipAddress[ipAddress.Length-1]+1;
}

3 Comments

What about 192.123.34.255 ?
At this point, I figured that sort of range checking had already been handled. To me, I don't think it would make sense to turn 192.123.34.255 into 192.123.35.0, which I think the other solutions would by going through an integer.
Eh, now that you mention it, x.x.x.99, or x.x.x.9 doesn't work either. I could fix these, but in reality, the above answers using socket library functions are more correct anway.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.