在C ++中,如何验证字符串是有效的IPv4地址?

我不需要验证IP地址是否可达或类似的地址。 我只想验证字符串为点分四进制(xxx.xxx.xxx.xxx)IPv4格式,其中xxx在0到255之间。

Bill the Lizard asked 2020-02-29T17:44:43Z
17个解决方案
52 votes

您可能需要inet_pton,对于无效的AF参数返回-1,对于无效的地址返回0,对于有效的IP地址返回+1。 它同时支持IPv4和将来的IPv6地址。 如果仍然需要编写自己的IP地址处理程序,请记住,标准的32位十六进制数字是有效的IP地址。 并非所有IPv4地址都以点分十进制表示。

此功能不仅可以验证地址,还可以让您在相关的套接字调用中使用相同的地址。

Raymond Martineau answered 2020-02-29T17:44:59Z
47 votes

Boost.Asio提供了ip :: address类。 如果只想验证字符串,则可以这样使用它:

std::string ipAddress = "127.0.0.1";
boost::system::error_code ec;
boost::asio::ip::address::from_string( ipAddress, ec );
if ( ec )
    std::cerr << ec.message( ) << std::endl;

这也适用于十六进制和八进制四边形。 这也是一种更加可移植的解决方案。

Björn Pollex answered 2020-02-29T17:45:24Z
36 votes

我选择的解决方案是:

bool Config::validateIpAddress(const string &ipAddress)
{
    struct sockaddr_in sa;
    int result = inet_pton(AF_INET, ipAddress.c_str(), &(sa.sin_addr));
    return result != 0;
}

这适用于其他答案中提到的大多数情况。 它无法识别八进制或十六进制格式的IP地址,但是对于我的应用程序来说是可以接受的。

Bill the Lizard answered 2020-02-29T17:45:48Z
17 votes

这看似简单,但有一些陷阱。 例如,先前答案中发布的许多解决方案都假定四边形以10为底,但是必须将以零开头的四边形视为以8(八进制)为底的数字,因此,例如,任何以零和 包含数字8或9的数字无效。 也就是说,IP编号192.168.1.10不是0xc0a8010a,但实际上是192.168.1.8,并且IP编号192.168.019.14无效,因为第三个四元组包含无效的基数8位9。

我强烈建议您使用操作系统或编译器环境中包含的套接字库提供的功能。

编辑:(认为是隐式的,但是)当然,您也可以具有十六进制四边形,即192.168.1.10的la 192.168.1.10,当然,您可以使用大写和小写愉快地混合并匹配到您的施虐内容,例如la 0xc0a8010a 为192.168.1.8。 如果您想获得乐趣,请尝试使用ping的一些示例。 这在跨平台上很好用(在Linux,NetBSD和Win32下宣誓就职时进行了测试。)

根据KaluSingh Gabbar的请求进行进一步编辑:例如,您可以将192.168.1.10指定为0xc0a8010a,它仍然表示一个有效的IP地址,例如:

[mihailim@home ~]$ ping 0xc0a8010a
PING 0xc0a8010a (192.168.1.10) 56(84) bytes of data.
^C
--- 0xc0a8010a ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2479ms
Mihai Limbășan answered 2020-02-29T17:46:23Z
8 votes

这是一种简单的方法。

bool IsIPAddress(std::string & ipaddr)
    {    

    StringTokenizer quads(ipaddr,".");

    if (quads.countTokens() != 4) return false;

    for (int i=0; i < 4; i++)
      {
      std::string quad = quads.nextToken();
      for (int j=0; j < quad.length(); j++
         if (!isdigit(quad[j])) return false;

      int quad = atoi(quads.GetTokenAt(i));
      if (quad < 0) || (quad > 255)) return false;
      }

    return true;
    }
Steve answered 2020-02-29T17:46:43Z
5 votes

如果您在Windows上,则可以使用WSAStringToAddress,并根据返回值(我们知道)确定传递的参数是否为有效IP。 从Windows 2000开始,这同时支持IPv4和IPv6。

user1740538 answered 2020-02-29T17:47:03Z
2 votes

Boost.Regex是合适的。

bool validate_ip_address(const std::string& s)
{
   static const boost::regex e("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
   return regex_match(s, e);
}
Martin Cote answered 2020-02-29T17:47:23Z
2 votes

如果您想自己编写而不是使用库,则

atoi()将字符转换为int可以让您测试每个数字的范围,以及“。”之间的一些strcmp。 您还可以进行一些快速检查,例如字符串的长度(应少于16个字符(不包括空终止符),点数等)。

但是,使用现有代码可能要容易得多。

xan answered 2020-02-29T17:47:52Z
2 votes

这是验证给定IPV4地址的C程序。 我假设IP地址为十进制格式。 请给我您的想法。

  // strTokenFunction.cpp : Check if the specified address is a valid numeric IP address.
  // This function is equavalent to the IPAddress.TryParse() method in C#

#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#include <string.h>

bool isValidIpAddress(char *st)
{
    int num, i, len;
    char *ch;

    //counting number of quads present in a given IP address
    int quadsCnt=0;

    printf("Split IP: \"%s\"\n", st);

    len = strlen(st);

    //  Check if the string is valid
    if(len<7 || len>15)
        return false;

    ch = strtok(st, ".");

    while (ch != NULL) 
    {
        quadsCnt++;
        printf("Quald %d is %s\n", quadsCnt, ch);

        num = 0;
        i = 0;

        //  Get the current token and convert to an integer value
        while(ch[i]!='\0')
        {
            num = num*10;
            num = num+(ch[i]-'0');
            i++;
        }

        if(num<0 || num>255)
        {
            printf("Not a valid ip\n");
            return false;
        }

        if( (quadsCnt == 1 && num == 0) || (quadsCnt == 4 && num == 0))
        {
            printf("Not a valid ip, quad: %d AND/OR quad:%d is zero\n", quadsCnt, quadsCnt);
            return false;
        }

        ch = strtok(NULL, ".");
    }

    //  Check the address string, should be n.n.n.n format
    if(quadsCnt!=4)
    {
        return false;
    }

    //  Looks like a valid IP address
    return true;
}

int main() 
{
    char st[] = "192.255.20.30";
    //char st[] = "255.255.255.255";
    //char st[] = "0.255.255.0";

    if(isValidIpAddress(st))
    {
        printf("The given IP is a valid IP address\n"); 
    }
    else
    {
        printf("The given IP is not a valid IP address\n");
    }
}
Savi answered 2020-02-29T17:48:13Z
2 votes

我仅使用C stdlib函数进行了相同的操作,尽管它不支持如上所述的八进制四边形,但这不应该成为问题,我可以轻松地添加该部分并将其提供给您。 作为一个初学者(学生),直到现在我什至不知道可以在您的ip中获取一个八进制数字。 我以为必须是小数。

Ramadheer Singh answered 2020-02-29T17:48:33Z
2 votes

您可以这样编写自己的函数:

bool isValidIPv4(const char *IPAddress)
{
   unsigned char a,b,c,d;
   return sscanf(IPAddress,"%d.%d.%d.%d", &a, &b, &c, &d) == 4;
}

sscanf()sprintf()在某些情况下非常有用。 :))

Kim Ninh answered 2020-02-29T17:48:57Z
1 votes

您可以使用boost tokenizer和boost char_separator轻松完成此操作。

[HTTP://呜呜呜.boost.org/doc/礼拜四/1_37_0/礼拜四/tokenizer/插入_separator.htm]

Marcin answered 2020-02-29T17:49:21Z
1 votes

如果不想使用Boost或TR1的开销,则可以搜索点并检查它们之间的字符是否为0到255之间的数字。

EricSchaefer answered 2020-02-29T17:49:42Z
1 votes
vector<string> &split(const string &s, char delim, vector<string> &elems) {
    stringstream ss(s);
    string item;
    while(getline(ss, item, delim)) {
       elems.push_back(item);
    }
    return elems;
}

vector<string> split(const string &s, char delim) {
   vector<string> elems;
   return split(s, delim, elems);
}


bool isIPAddress(string  ipaddr){

    if (ipaddr.length()){
            vector<string> _ip=split(ipaddr,'.');
            if (_ip.size()==4){
                    for (int i=0; i < 4; i++){
                            for (int j=0; j < _ip[i].length(); j++)
                                    if (!isdigit(_ip[i][j])) return false;
                            if ((atoi(_ip[i].c_str()) < 0) || (atoi(_ip[i].c_str()) > 255)) return false;
                    }
            return true;
            }
    }
    return false;
 }
Amir answered 2020-02-29T17:49:57Z
1 votes

一些较小的修复程序,将某些情况修复为127..0.1、127.0.0 ..,并在出现以下情况时删除空格:




    #include <iostream>
    #include <vector>
    #include <string>
    #include <sstream>
    #include <algorithm>
    #include <iterator>
    #include <stdio.h>

    using namespace std;

    vector split(char* str, char delimiter)
    {
        const string data(str);
        vector elements;
        string element;
        for(int i = 0; i  0) {//resolve problem: 127.0..1
                    elements.push_back(element);
                    element.clear();
                }
            }
            else if (data[i] != ' ')
            {
                element += data[i];
            }

        }
        if (element.length() > 0)//resolve problem: 127.0..1
            elements.push_back(element);
        return elements;
    }

    bool toInt(const string& str, int* result)
    {
        if (str.find_first_not_of("0123456789") != string::npos)
            return false;

        stringstream stream(str);
        stream >> *result; // Should probably check the return value here
        return true;
    }

    /** ipResult: the good ip address, e.g. spaces are removed */
    bool validate(char* ip, string *ipResult)
    {
        const static char delimiter = '.';
        const vector parts = split(ip, delimiter);
        *ipResult = "";
        if (parts.size() != 4)
            return NULL;

        for(int i = 0; i  255)
                return NULL;

            if (i == 3) {
                *ipResult += parts[i];
            } else {
                *ipResult += (parts[i] +".");
            }

        }
        return true;
    }

    int main()
    {
        string ip;
        printf("right %d\n", validate("127.0.0.1", &ip));
        printf("good ip: %s\n", ip.c_str());
        printf("wrong %d\n", validate("127.0.0.-1", &ip));
        printf("good ip: %s\n", ip.c_str());
        printf("wrong %d\n", validate("127..0.1", &ip));
        printf("good ip: %s\n", ip.c_str());
        printf("wrong %d\n", validate("...0.1", &ip));
        printf("good ip: %s\n", ip.c_str());
        printf("wrong %d\n", validate("127.0.0.", &ip));
        printf("good ip: %s\n", ip.c_str());
        printf("right %d\n", validate("192.168.170.99", &ip));
        printf("good ip: %s\n", ip.c_str());
        printf("right %d\n", validate("127.0 .0  .1", &ip));
        printf("good ip: %s\n", ip.c_str());
        printf("\n");

        system("pause");

        return 0;
    }

user2314327 answered 2020-02-29T17:50:17Z
0 votes

如果您希望以常规形式接收IP地址(8.8.8.8192.168.1.1等...)然后,我编写了以下代码,扩展了Bjorn的答案:

void validateIP(const std::string &IPv4_address)
{
    boost::system::error_code error_code;
    auto raw_ipv4_address = boost::asio::ip::address::from_string(IPv4_address, error_code);
    if (error_code)
    {
        throw std::invalid_argument(error_code.message());
    }

    std::string raw_to_string_form = raw_ipv4_address.to_string();
    if (raw_to_string_form.compare(IPv4_address))
    {
        throw std::invalid_argument("Input IPv4 address is invalid");
    }
}

原因是,如果您传递8.88.8或12345(十进制格式)之类的IP,Bjorn的答案将不会引发错误。 (至少提升1.68)我的代码将任何形式转换为Boost中的内部结构,然后将其转换回点分十进制格式,然后将其与接收到的第一个IP进行比较,看它们是否相等,如果不相等,我们肯定知道输入 这不是我们想要的方式。

A. Smoliak answered 2020-02-29T17:50:42Z
0 votes
void validate_ip_address(const std::string& s) {
    const std::string number_0_255 = "((([0-9])|([1-9][0-9])|(1[0-9][0-9]|2[0-4][0-9]|25[0-5])){1})";
    const std::string dot = "(\\.){1}";
    static const boost::regex e(number_0_255 + dot + number_0_255 + dot + number_0_255 + dot + number_0_255);
    if (!regex_match(s, e)) {
        throw std::runtime_error(std::string("Uncorrect address IP: ") + s);
    }
}
Piotr K answered 2020-02-29T17:50:58Z
translate from https://stackoverflow.com:/questions/318236/how-do-you-validate-that-a-string-is-a-valid-ipv4-address-in-c