确定字符串是否是C中的有效IPv4地址

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了确定字符串是否是C中的有效IPv4地址相关的知识,希望对你有一定的参考价值。

确定字符串是否包含IPv4地址的好方法是什么?我应该使用isdigit()吗?

答案

我问a similar question for C++。您应该能够使用我当时提出的稍微修改过的(对于C)版本。

bool isValidIpAddress(char *ipAddress)
{
    struct sockaddr_in sa;
    int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr));
    return result != 0;
}

你需要使用#include <arpa/inet.h>来使用inet_pton()函数。

根据对问题的评论进行更新:如果您想知道C风格的字符串是否包含IP地址,那么您应该结合到目前为止给出的两个答案。使用正则表达式查找与IP地址大致匹配的模式,然后使用上面的函数检查匹配项以查看它是否真实。

另一答案

这是我一直在努力的功能的开始,虽然不完整,它可能会引发想法或评论。功能背后的思想是;

  1. 检查传递的char指针或字符串是否是一个没有端口的IPv4地址,使用其最小/最大大小,字符串中有多少个点,以及冒号:字符是否存在。
  2. 如果字符串不是带有或没有端口的IPv4,那么检查该字符串是否为IPv6,如果不是IPv6,则无法识别IP格式,因为它尚未实现。

我认为这取决于你想要深入研究这个问题的深度,你想要了解可能会出现什么样的问题。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>

int isIP(char *ip)
{
    char *data_ptr = ip;    // Create a pointer to passed data
    int orig_str_size = 0;  // Create an int to hold passed data size
    int str_index = 0;      // Create an int to iterate individual ip characters
    int dot_count = 0;      // Create an int to check for the number of dots

    // Count the number of characters in data_ptr
    while (*data_ptr++ != ''){ orig_str_size++; }

    if(orig_str_size <= 0) // If nothing
    {
        printf("Get a grip, ip is empty

");
        exit(0);
    }
    else // If within IPv4 size range
    if(orig_str_size >= 7 && orig_str_size <= INET_ADDRSTRLEN)
    {
        char *data1_ptr = ip; // Create a pointer to passed data
        printf("Within IPv4 range, %i characters in length

", orig_str_size);

        // Count the number of dots in the string, 3 for IPv4
        for(str_index; str_index < orig_str_size; str_index++)
        {
            if(data1_ptr[str_index] == '.'){ dot_count++; }
        }

        // If theres 3 dots, while ignoring dots, check each char is a digit 
        if(dot_count == 3)
        {

            printf("There's three dots in the string

");
            data1_ptr = ip;
            str_index = 0;

            // Iterate the string char by char
            for(str_index; str_index < orig_str_size; str_index++)
            {
                // Ignoring dots
                if(data1_ptr[str_index] != '.')
                { 
                    // If isdigit() is happy its a digit and isalpha() happy not alphabetic
                    if(isdigit(data1_ptr[str_index]) && !isalpha(data1_ptr[str_index]))
                    {
                        printf("Digit found and is not alphabetic

");
                        continue;
                    }
                    else
                    if(!isdigit(data1_ptr[str_index]) && isalpha(data1_ptr[str_index]))
                    {
                        printf("Not a recognised IPv4 address, character detected in string

");
                        exit(0);
                    }
                }
            }

            return 0;
        }
    }
    else // If IPv6
    if(orig_str_size > 0 && orig_str_size > INET_ADDRSTRLEN && orig_str_size <= INET6_ADDRSTRLEN)
    {
        printf("Within IPv6 range %i

", orig_str_size);
        return 0;
    }
    else
    {
        printf("Unknown target format, the format you provided as a target is not implemented

");
        exit(0);
    }

}

TCP / IP网络互联

RFC791 - 互联网协议 - https://tools.ietf.org/html/rfc791

CISCO网络互联手册http://docwiki.cisco.com/wiki/Internetworking_Technology_Handbook

开放系统互连参考模型http://docwiki.cisco.com/wiki/Internetworking_Basics#Open_Systems_Interconnection_Reference_Model

CISCO故障排除TCP / IP网络https://www.cisco.com/en/US/docs/internetworking/troubleshooting/guide/tr1907.pdf

What is the largest TCP/IP network port number allowable for IPv4?

另一答案
//  you can even use the v value array to return the unsigned int 
//  version of the IP if desired in an unsigned int reference.   

bool isvalidip(const char * s) 
{
  char t[8];
  int p = 0;
  int v[8];
  int numnum = 0;
  for (int i = 0; i < (int) strlen(s); i++) {
    char c = s[i];
    int cgood = 0;
    if (c >= '0' && c <= '9' && p < 4) {
      t[p++] = c;
      t[p] = 0;
      cgood++;
      continue;
    }
    if (p == 4) return false;
    if (c == '.') {
      if (!p) return false;
      v[numnum++] = atoi(t);
      p = 0;
      cgood++;
      continue;
    }
    if (!cgood) return false; // not a valid character
    if (numnum > 4) return false; // we have a lot of dots....
  }
  v[numnum++] = atoi(t); // we did not have a dot, we had a NULL.....
  if (numnum != 4) return false; // we must have had 4 valid numbers....
  for (int i = 0; i < 4; i++)
  {
    if (v[i] < 0 || v[i] > 255) return false; // octet values out-of-range
  }
  return true; //we good..
}
另一答案

我修改了其中一个答案,使其更加完整并附上所有代码(包括测试)

#include <stdio.h>
#include <assert.h>
#include <string.h>

int validateIP4Dotted(char *str, unsigned int pIPAddress[])
{
    int segs = 0; /* Segment count. */
    int chcnt = 0; /* Character count within segment. */
    int accum = 0; /* Accumulator for segment. */

    /* Catch NULL pointer. */

    if (str == NULL)
        return 0;

    /* Process every character in string. */

    while (*str != '')
    {
        /* Segment changeover. */

        if (*str == '.')
        {
            pIPAddress[segs] = accum;
            /* Must have some digits in segment. */

            if (chcnt == 0 || chcnt > 3)
                return 0;

            /* Limit number of segments. */

            if (++segs == 4)
                return 0;

            /* Reset segment values and restart loop. */

            chcnt = accum = 0;
            str++;
            continue;
        }
        /* Check numeric. */

        if ((*str < '0') || (*str > '9'))
            return 0;

        /* Accumulate and check segment. */

        if ((accum = accum * 10 + *str - '0') > 255)
            return 0;

        /* Advance other segment specific stuff and continue loop. */

        chcnt++;
        str++;
    }

    /* Check enough segments and enough characters in last segment. */
    pIPAddress[segs] = accum;

    if (segs != 3)
        return 0;

    if (chcnt == 0 || chcnt > 3)
        return 0;

    if (pIPAddress[0] >=224)
        return 0;
    /* Address okay. */

    return 1;
}


int main()
{
    unsigned int IpAddress[4];
    char str_ip[128];

    strcpy(str_ip, "192.168.1.10");
    assert(validateIP4Dotted(str_ip, IpAddress));
    assert(
            IpAddress[0] == 192 && IpAddress[1] == 168 && IpAddress[2] == 1
                    && IpAddress[3] == 10);

    strcpy(str_ip, "0.0.0.0");
    assert(validateIP4Dotted(str_ip, IpAddress));
    assert(
            IpAddress[0] == 0 && IpAddress[1] == 0 && IpAddre

以上是关于确定字符串是否是C中的有效IPv4地址的主要内容,如果未能解决你的问题,请参考以下文章

是否有库函数来确定 IP 地址(IPv4 和 IPv6)在 C/C++ 中是否为私有/本地?

确定C字符串是否是C中的有效int

如何批量验证字符串是有效的 IPv4 或 IPv6 地址?

从字符串中获取 IPv4 地址的最快方法

字符串中的 IP 地址检测 (C++)

验证IPv4 IP地址是否有效