zoukankan      html  css  js  c++  java
  • 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";
    	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!=ipSecs.end(); 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的代码量只有前两者的一半,要清爽得多 

    运行实例

    三个例子所实现的交互都是一模一样的,运行截个例子

  • 相关阅读:
    wince串口打印信息的屏蔽与打开
    2440 6.0BSP 移植过程之OAL
    2440 6.0BSP移植过程之电池驱动
    2440 6.0BSP移植过程之SD卡驱动
    如何在wince6.0 模拟器上跑以前编译好的EVC MFC程序
    2440 休眠唤醒的实现过程(作者:wogoyixikexie@gliet)
    CETK的使用(USB连接方式)
    如何扩展ARM内存(OEMGetExtensionDRAM和pNKEnumExtensionDRAM函数可以解决问题)
    ZLG7290(wince下)驱动之不停执行同一动作的解决办法(作者:wogoyixikexie@gliet)
    2440 中断优先级问题(作者wogoyixikexie@gliet)
  • 原文地址:https://www.cnblogs.com/livingintruth/p/2839187.html
Copyright © 2011-2022 走看看