ip地址和int类型的相互转换
这是我最近看到的⼀个⾯试题,还⽐较常见,于是⽤c, c++和python分别实现了 ip2int 和 int2ip, 因为我把main函数都写上了,代码显得有点杂乱,看的时候请重点看函数实现,忽略main函数
ipv4的地址本来就是⽤32位来表⽰的,分成4个8位来书写, 所以ipv4和地址是可以和32位unsigned int⼀⼀对应的,转换的算法就很显然了,把32位的整型4个字节的数分别计算出来;反之则是ip地址4个节的数乘上对应的权值(256^3, 256^2, 256^1, 256^0)加起来即可
C的
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
unsigned int ip2int(char * ipStr);
const char* int2ip(unsigned int ipInt);
const int IP_STR_LEN= 15;
const int TOKEN_LEN = 4;
int main(){
printf("1)ip2int 2)int2ip\nothers, quit\n");
int choice = 0;
scanf("%d", &choice);
while(choice ==1 || choice ==2){
char * pipStr = malloc(IP_STR_LEN);
if(choice == 1){
printf("ipStr : ");
scanf("%s", pipStr);
int ipInt = ip2int(pipStr);
printf("ipInt : %d\n", ipInt);
}else{
printf("ipInt : ");
int ipInt = 0;
scanf("%d", &ipInt);
pipStr = int2ip(ipInt);
printf("ipStr : %s\n", pipStr);
}
printf("--------------\n1)ip2int 2)int2ip\nothers, quit\n");
choice = 0; //choice must be set to 0 , or unexpected thing happend
scanf("%d", &choice);
}
printf("quit\n");
}
unsigned int ip2int(char* ipStr){
unsigned int ipInt = 0;
int tokenInt = 0;
char * token;
token = strtok(ipStr, ".");
int i = 3;
while(token != NULL){
// tokenInt = strtol(token, NULL, 10); //strtol comes from stdlib.h
tokenInt = atoi(token);
ipInt += tokenInt * pow(256, i);
token = strtok(NULL, ".");
i--;
}
return ipInt;
}
const char* int2ip(unsigned int ipInt){
int tokenInt = 0;
unsigned int leftValue = ipInt;
char * ipStr = malloc(IP_STR_LEN);
char * ipToken = malloc(TOKEN_LEN);
for(int i=0; i<4; i++){
int temp = pow(256, 3-i);
tokenInt = leftValue / temp;
leftValue %= temp;
// itoa(tokenInt, ipToken, 10); //non-standard function
snprintf(ipToken, TOKEN_LEN, "%d", tokenInt);
if(i != 3){
strcat(ipToken, ".");
}
strncat(ipStr, ipToken, strlen(ipToken));
}
return ipStr;
1. c编译的时候⽐较特别,要如下才能编译成功
gcc -std=c99 ip2int.c -lm -o ip2int
若把 ip2int.c放到最后是不能编过的,会提⽰pow()⽆法链接. -lm是链接上<math.h>这个头⽂件中声明的函数的库
2. c中的幂需要调⽤<math.h>中的pow()函数才⾏.
3. <stdlib.h>中有提供atoi以及⼀系列的strtol标准函数来实现从string到int(atoi)或是long(strtol)的转换, 但是itoa并不是<stdlib.h>中的标准函数,即不是c library的标准函数, 从整型到string标准的⽅案是使⽤snprintf或sprintf
4.在c中实现string的split使⽤的是<string.h>中的strtok函数, 上⾯ip2int中对strtok的使⽤是⼀个典型的例⼦.
C++的
#include<iostream>
#include<string>
#include<vector>
#include<sstream>
#include<cmath>
#include<boost/algorithm/string.hpp>
using namespace std;
using namespace boost;
unsigned int ip2int(string& ip);
string int2ip(unsigned int ipInt);
int main(){
cout << "1)ip2int 2)int2ip\nothers,quit\n";
c++string类型char choice = 0;
cin >> choice;
while (string("12").find(choice) != string::npos){
if (choice == '1'){
cout << "ipStr : ";
string ip;
cin >> ip;
unsigned int ipInt = ip2int(ip);
cout << "ipInt : " << ipInt << "\n";
} else if (choice == '2'){
cout << "ipInt : ";
unsigned int ipInt = 0;
cin >> ipInt;
string ip = int2ip(ipInt);
cout << "ipStr : " << ip << endl;
}
cout << "-------------\n1)ip2int 2)int2ip\nothers,quit\n";
cin >> choice;
}
cout << "quit";
}
unsigned int ip2int(string& ip){
vector<string> ipSecs;
split(ipSecs, ip, is_any_of("."));
vector<string>::iterator it = ipSecs.begin();
unsigned int ipInt = 0;
int i = 3;
stringstream ss;
for (; it!=d(); it++){
int ipSecInt = 0;
ss << *it;
ss >> ipSecInt;
//must ss.clear()
ss.clear();
ipInt += ipSecInt * pow(256,i);
i--;
}
return ipInt;
}
string int2ip(unsigned int ipInt){
string ip;
string ipSec;
stringstream ss;
int leftValue = ipInt;
for(int i=3; i>=0; i--){
int temp = pow(256,i);
int sectionValue = leftValue / temp;
leftValue %= temp;
ss << sectionValue;
ss >> ipSec;
ss.clear();
if(i!=0){
ipSec.append(".");
}
ip.append(ipSec);
ipSec.clear();
}
return ip;
}
1.在C++中,string到整型的互转使⽤的是io库中的stringstream, 这也是C++标准库的解决⽅案, 当然boost库中也有解决⽅案,但我倾向于使⽤这个.
2.上⾯两个函数实现中对于stringstream的使⽤,当我调整了流的⽅向后,必须调⽤ss.clear(), 才能继续正常使⽤ss.还没有去研究这是为什么
3.对于string的split, 我使⽤了boost库中的东西,这个在中有提及.C++的标准库并没有对string的split提
供直接的解决⽅案
Python的
import string
def ip2int(ipStr):
ipInt = 0
i = 3
ipTokens = str(ipStr).split('.')
for ipToken in ipTokens:
ipInt += int(ipToken) * (256 ** i) # or pow(256, i)
i -= 1
return ipInt
def int2ip(ipInt):
ipStr = ''
leftValue = ipInt
for i in [3, 2, 1, 0]:
ipTokenInt = leftValue / 256**i
ipStr = ipStr + str(ipTokenInt)
if i!=0:
ipStr = ipStr + '.'
leftValue %= 256**i
return ipStr
if __name__ == "__main__":
choice = raw_input('1)ip2int 2)int2ip\nothers, quit\nyour choice : ')
while choice in ['1', '2']:
if choice == '1':
ipStr = raw_input('ipStr :')
ipInt = ip2int(ipStr)
print 'ipInt : ', ipInt
elif choice == '2':
ipInt = input('ipInt : ')
ipStr = int2ip(ipInt)
print 'ipStr : ', ipStr
choice = raw_input('-------------------\n1)ip2int 2)int2ip\nothers, quit\nyour choice : ')
print 'quit'
1. Python中的幂既可以⽤**也可以⽤pow(), 如第8⾏.
2. input⽤到了两种, input和raw_input, raw_input就是输⼊的的字符串, ⽽input其实是⽤raw_input实现的,它会处理输⼊的东西,若是数字,则转换为相应的类型
3. string的分隔⽤的是string.split,实际上这个⽅法已经被废弃了,但还是会在python3中⽀持,但新的⽅法怎么使⽤我没看明⽩, string concatination⽤的是 + . 可以看到6,7⾏string的split和遍历是多么简洁的代码就搞定了
其实上⾯三个实现⽤到的实现算法都是⼀模⼀样的, 可以很明显的看到,Python的代码量只有前两者的⼀半,要清爽得多
运⾏实例
三个例⼦所实现的交互都是⼀模⼀样的,运⾏截个例⼦
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论