编写C++函数:识别一段string字符串是IPv4还是IPv6

今天做到Calix(南京凯易迅)的笔试题,其中有一题大致意思是:vector中存有string字符串,识别每一个字符串是否是ip地址,三种可能:IPv4、IPv6、Neither,将每个字符串的识别结果依次存入一个vector中返回。
编写函数:vector checkIP(vector &ip_array{ }
如:
输入:
This is not an ip_address!
192.168.1.1
0000: 0123: ff00: 00: ff: 0: 00ff: 1111
输出:
3
Neither
IPv4
IPv6

输入:
192.168.1.1
输出:
1
IPv4

思路如下
1)首先区分IPv4和IPv6,IPv4是通过4段32bits表示出来,每一段对应8bits,十进制范围为0~255,每一段用点”.”隔开;
IPv6是通过8段128bits表示出来的,每一段对应16bits,十六进制范围为0000~ffff,每一段用冒号”:”隔开。
2)根据段数可以确认可能是IPv4还是IPv6,但只是可能,因为每一段的表示都要进行合法性检测:如256.168.1.1就是不合法的表示,而gg00显然也不能表示十六进制数。那问题来了,如何进行ip_address的每一段检查呢,很遗憾C++标准库里面没有字符分割函数split(),只有我们可以自己创造了:代码如下

#include
#include
#include
using namespace std;

//***函数名:str_split
//***str:待分隔的字符串
//***sign:分隔符,如"."、":"等
//***results:将每一段存入results中,特别的当不存在sign时,str整体存入results中

void str_split(const string &str, const string &sign, vector<string> &results)
{
    string::size_type pos;
    size_t size = str.size();
    for (size_t i = 0; i < size; ++i)
    {
        pos = str.find(sign, i); //从第i个位置查找sign分割符第一次出现的位置,没有找到则返回npos;
        if (pos == str.npos)
        {//将剩余部分存入
            string s = str.substr(i, size);
            results.push_back(s);
            break;
        }
        if (pos < size)
        {
            string s = str.substr(i, pos - i);//把从i开始,长度为pos-i的元素拷贝给s;  
            results.push_back(s);
            i = pos;
        }
    }
}

3)理清了前两点,第三点关于什么情况下结果是Neither也就清楚了:
a.不存在”.”和”:”,即只有一段,段数不合法;
b.存在间隔符,但是段数不够(4或8段),段数不合法;
c.存在间隔符,且段数合法,但是每一段表示不合法
代码如下:

vector<string> checkIP(vector<string> ip_array)
{
    size_t n = ip_array.size();
    vector<string> results_vec;  //保存结果

    //vector为空
    if (n == 0)
    {
        results_vec.push_back("Empty");
        return results_vec;
    }

    //存入元素个数
    results_vec.push_back(to_string(n));

    vector<string>::iterator it = ip_array.begin();
    for (; it != ip_array.end(); ++it)
    {
        vector<string> results_4, results_6;
        str_split(*it, ".", results_4);  //results_4存储ipv4的每段
        str_split(*it, ":", results_6);  //results_6存储ipv6的每段

        //地址段数不合法
        if(results_4.size() != 4 && results_6.size() != 8)
        {
            results_vec.push_back("Neither");
            continue;
        }

        //段数合法(4段),可能是IPv4,接下来判断每一段的合法性
        if (results_4.size() == 4)  
        {
            vector<string>::iterator it_4 = results_4.begin();

            for (; it_4 != results_4.end(); ++it_4)
            {
                int a = atoi((*it_4).c_str());
                if (a < 0 || a > 255)
                    break;
            }
            if (it_4 == results_4.end())
                results_vec.push_back("IPv4");
            else
                results_vec.push_back("Neither");
        }

        //段数合法(8段),可能是IPv6,接下来判断每一段的合法性
        if (results_6.size() == 8)
        {
            vector<string>::iterator it_6 = results_6.begin();

            for (; it_6 != results_6.end(); ++it_6)
            {
                size_t it6_size = (*it_6).size();
                if (it6_size <= 0 || it6_size > 4)  //IPv6的每段的十六进制数的位数不合法
                    break;

                size_t j = 0;
                while(j < it6_size)
                {//十六进制表示的合法性检测
                    char s = (*it_6)[j];
                    if ((s >= '0' && s <= '9') ||
                        (s >= 'a' && s <= 'f') ||
                        (s >= 'A' && s <= 'F'))
                        ++j;
                    else
                        break;
                }
                if (j != it6_size)  //存在某一位的十六进制表示不合法
                    break;
            }
            if (it_6 == results_6.end())  //所有位的十六进制表示均合法
                results_vec.push_back("IPv6");
            else
                results_vec.push_back("Neither");
        }
    }

    return results_vec;  
}

接下来main函数测试一下代码:

int main()
{
    vector<string> ip_array = { "This is not an ip_address!", "192.168.1.1", "256.168.1.1", "0000:0123:ff00:00:ff:1234:00ff:1111" ,"0000:0123:ff00:00:ff:1234:00ff" };
    vector<string> results;
    results = checkIP(ip_array);
    for (vector<string>::iterator it = results.begin(); it != results.end(); ++it)
        cout << *it << endl;

    return 0;
}

结果

//***output:
5
Neither
IPv4
Neither
IPv6
Neither
请按任意键继续. . .

你可能感兴趣的:(C++编程)