編寫C++函式:識別一段string字串是IPv4還是IPv6
今天做到Calix(南京凱易迅)的筆試題,其中有一題大致意思是:vector<string>
中存有string字串,識別每一個字串是否是ip地址,三種可能:IPv4、IPv6、Neither,將每個字串的識別結果依次存入一個vector<string>
中返回。
編寫函式:vector<string> checkIP(vector<string> &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<iostream>
#include<vector>
#include<string>
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
請按任意鍵繼續. . .