今天心血来潮准备写一个端口扫描器。记得之前写MFC程序里面CString类有个方法可以以某一字符分割CString对象,但是C++中string似乎没有这样的方法。所以我要自己实现一个方法(函数),将输入的IP地址分割成4个数字,保存在数组中。
函数如下:
void GetIpString(string strIpAdd,int iIp[]) { int OppPos = 0 , nowPos = 0 , i = 0; while (OppPos = strIpAdd.find_first_of('.',nowPos)) { if (string::npos == OppPos) { iIp[i] = atoi(strIpAdd.substr(nowPos).c_str()); break; } iIp[i] = atoi(strIpAdd.substr(nowPos,OppPos - nowPos).c_str()); nowPos = OppPos + 1; i++; } return ; }
传入的参数是一个保存着IP地址的string对象,第二个参数是数组。
首先用到string中的一个方法,:find_first_of,四个重载函数:
size_type find_first_of( const basic_string &str, size_type index = 0 ); size_type find_first_of( const char *str, size_type index = 0 ); size_type find_first_of( const char *str, size_type index, size_type num ); size_type find_first_of( char ch, size_type index = 0 ); |
我用到第四个,作用是从位置pos开始,查找第一个出现ch的位置。如果没找到则返回string::npos。
我定义了两个记录位置的整型,OppPos和nowPos,将find_first_of的返回值赋给OppPos.这就是我们的目标位置,所以现在,从nowPos到(OppPos - 1)的子串就是我们要的第一个数字。(比如192.168.1.1执行find_first_of,得到的OppPos == 3,从0到2即是我们要的"192")
进入while循环体,首先一个判断句,如果OppPos == string::npos就不能再找下去了。因为当最后找不到'.'时,就是最后一个数字了。
如果OppPos != string::npos则说明找到了'.',则执行这一句:
iIp[i] = atoi(strIpAdd.substr(nowPos,OppPos - nowPos).c_str());
substr这个方法作用是获得子串,获取从索引nowPos开始,向后OppPos-nowPos个位置的子串。其实就是获得从nowPos到OppPos-1位置的子串。
大家要是弄不清逻辑,可以自己在纸上画一画,就知道这几个位置的关系了。
获得了子串之后我又用了子串的c_str()方法。这个方法作用是将string转换成char * 类型。因为我们需要把"192"转换成数字192,需要用到atoi函数。而atoi函数的参数是char *类型(也就是C语言里的字符串)。
我们将atoi的结果返回到数组里,也就是把192保存在了iIp[0]里,168保存在iIp[1]里……
我们返回去看那个if语句中,当我们最后一次找不到'.'时,进入到这个if语句,但其实iIp[3]还没有赋值,所以iIp[i] = atoi(strIpAdd.substr(nowPos).c_str());是为了把最后一个数字放到iIp[3]中。你们可以看到我这次用的substr方法中只调用了一个参数,这是个重载函数,substr(nowPos)表示获得从nowPos开始到最后一个字符截止的子串。
我发现自己现在越来越罗嗦……一个破函数写了这么多。。
再写个main函数验证一下把:
int _tmain(int argc, _TCHAR* argv[]) { string strIP; int arrIP[4]; cin>>strIP; GetIpString(strIP,arrIP); for (int i = 0 ; i < 4 ; i++) { cout<<arrIP[i]<<endl; } return 0; }
结果是:
最后把数组输出,每行一个数。
注意要使用string类需要包含c++的字符串头文件:#include <string>