Подтвердить что ты не робот

Как вы подтверждаете, что строка является допустимым адресом IPv4 в С++?

Мне не нужно проверять, доступен ли IP-адрес или что-то в этом роде. Я просто хочу проверить, что строка находится в формате dotv-quad (xxx.xxx.xxx.xxx) IPv4, где xxx находится между 0 и 255.

4b9b3361

Ответ 1

Возможно, вам нужен inet_pton, который возвращает -1 для недопустимого аргумента AF, 0 для недопустимого адреса и +1 для действительного IP-адреса. Он поддерживает как IPv4, так и будущие IPv6-адреса. Если вам все еще нужно написать собственную обработку IP-адреса, помните, что стандартное 32-разрядное шестнадцатеричное число является действительным IP-адресом. Не все адреса IPv4 указаны в десятичном формате с точками.

Эта функция одновременно проверяет адрес, а также позволяет использовать один и тот же адрес в связанных вызовах сокетов.

Ответ 2

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;

Это также работает для шестнадцатеричных и восьмеричных квадроциклов. Это также гораздо более портативное решение.

Ответ 3

Решение, на котором я остановился, было:

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-адреса с восьмеричным или шестнадцатеричным форматированием, но это приемлемо для моего приложения.

Ответ 4

Это выглядит обманчиво простым, но имеет несколько подводных камней. Например, многие из решений, опубликованных в предыдущих ответах, предполагают, что квадрациклы находятся в базе 10, но квад, начинающийся с нуля должен, рассматриваться как базовое 8 (восьмеричное) число, следовательно, например любая квадратная часть, начинающаяся с нуля и содержащая цифры 8 или 9, недопустима. I.e, номер IP 192.168.1.010 не 192.168.1.10, но на самом деле это 192.168.1.8, а IP-номер 192.168.019.14 недействителен, поскольку третий четвертый содержит недопустимую базовую 8-разрядную цифру 9.

Я настоятельно рекомендую вам использовать функции, предоставляемые библиотекой сокетов, включенными в вашу операционную систему или среду компилятора.

Изменить: (Думал, что это было неявно, но), конечно, вы также можете иметь шестнадцатеричные квадроциклы, la 192.168.1.0x0A для 192.168.1.10, и, конечно же, вы можете смешать и сопоставить свое садистское содержание с удовольствием, используя верхний и нижний case, a la 0xC0.0xa8.1.010 для 192.168.1.8. Попробуйте несколько примеров, используя ping, если вы хотите повеселиться. Это работает просто кросс-платформенная (протестирована некоторое время назад, ругаясь под Linux, NetBSD и Win32.)

Дальнейшее редактирование в ответ на запрос KaluSingh Gabbar: Например, вы можете указать 192.168.1.10 как 0xc0a8010a и он по-прежнему представляет действительный номер IP, a la:

[[email protected] ~]$ 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

Ответ 5

Вот один простой метод.

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;
    }

Ответ 6

Если вы находитесь в окнах, вы можете использовать WSAStringToAddress и на основе возвращаемого значения, которое мы знаем, если переданный аргумент действителен IP или нет. Это поддерживает как IPv4, так и IPv6 с Windows 2000 и далее.

Ответ 7

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);
}

Ответ 8

Если вы хотите написать это самостоятельно, а не использовать библиотеку, то

atoi(), чтобы преобразовать символы в int, позволит вам проверить диапазон каждого числа и некоторый strcmp между ".". Вы также можете выполнить некоторые быстрые проверки, такие как длина строки (должно быть меньше 16 символов (не включая нулевой ограничитель), количество точек и т.д.

Но, возможно, намного проще использовать существующий код.

Ответ 9

Я сделал то же самое, используя только функции C stdlib, хотя он не поддерживает восьмеричные квадроциклы, как упоминалось выше, но это не должно быть проблемой, я могу легко добавить эту часть и передать ее вам. Будучи новичком (учеником), я до сих пор не знаю, что в вашем ip можно получить восьмеричное число. Я думал, что это должно быть десятичное.

Ответ 10

Вот C-программа для проверки заданного IPV4-адреса. Я предположил, что 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");
    }
}

Ответ 12

Если вам не нужны накладные расходы Boost или TR1, вы можете искать точки и проверять, являются ли символы между ними числами от 0 до 255.

Ответ 13

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;
 }

Ответ 14

некоторые незначительные исправления, чтобы исправить некоторые случаи как 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;
    }

Ответ 15

Вы можете написать свою собственную функцию следующим образом:

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() очень полезны в некоторых ситуациях. :))

Ответ 16

Если вы хотите получить IP-адрес в обычной форме (8.8.8.8, 192.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");
    }
}

Причина в том, что если вы передадите IP, такой как 8.88.8 или 12345 (десятичная форма), ответ Bjorn не выдаст ошибку. (по крайней мере, с Boost 1.68) Мой код преобразует любую форму во внутреннюю структуру в Boost, затем преобразует ее обратно в десятичный формат с точками, затем мы сравниваем его с первым IP-адресом, который мы получили, чтобы увидеть, равны ли они, если нет, мы точно знаем, что вход не так, как мы хотели.