题目:输入一个IPv4字符串,如“1.2.3.4”,输出对应的无符号整数,如本例输出为 0x01020304。

来源:某500强企业面试题目

思路:从尾部扫描到头部,一旦发现无法转换,立即返回,减少无谓操作。

#include "stdio.h"
#include "stdlib.h"
#include "string.h" bool ConvertIPv4ToUInt(const char *strIP, unsigned int *ip)
{
if (!strIP) {
return false;
} int Len = strlen(strIP); // min len is 7, e.g. 1.2.3.4; max len is 15, e.g. 123.234.121.254
if ((Len < ) || (Len > )) {
return false;
} int num[] = { }; // 4 parts of number
int partNum = ; // 1 part of number
int base = ; // 10^base
int dotCount = ; // dot count // from right to left
for (int i = Len - ; i >= ; --i) {
char ch = strIP[i];
if (ch == '.') {
// if the first char of last char is ".", e.g. ".1.2.3.4" or "1.2.", exit
if ((i == ) || (i == Len - )){
return false;
}
dotCount++; // if more than 3 dot found, e.g. "1.2.3.4.5", exit
if (dotCount > ) {
return false;
} // save partNum to num[]
num[dotCount - ] = partNum;
partNum = ;
base = ;
}
else if ((ch < '') || (ch > '')) {
// if illeagal char inside, exit
return false;
}
else {
// handle digit char
partNum += (ch - '') * base;
base *= ; if (partNum > ) {
return false;
} // handle first part num
if (i == ) {
// if count of "." is not enough, exit
if (dotCount != ) {
return false;
}
num[dotCount] = partNum;
}
}
} // output ip
*ip = ;
for (int i = ; i < ; ++i) {
*ip += num[i] << (i * );
} return true;
} int main(int argc, char* argv[])
{
char* strIP[] = {
"",
"1.2",
"1.2.3",
"111.222.113",
"1.2.3.",
".1.2.3",
"256.1.2.3",
"1.2.3.4",
"1.2.3.4.5",
"12.234.45.6",
"12.2345.45.6",
"1.a.2.3",
"1.2.3.4 ",
"1.2. 3.4",
"1,2,3,4",
}; for (int i = ; i < sizeof(strIP) / sizeof(char *); ++i){
unsigned int ip = ;
if (ConvertIPv4ToUInt(strIP[i], &ip)){
printf("%s -> %08X\n", strIP[i], ip);
}
else {
printf("%s is not valid\n", strIP[i]);
}
} getchar();
return ;
}

输出结果为:

 is not valid
1.2 is not valid
1.2. is not valid
111.222. is not valid
1.2.. is not valid
.1.2. is not valid
256.1.2.3 is not valid
1.2.3.4 ->
1.2.3.4. is not valid
12.234.45.6 -> 0CEA2D06
12.2345.45.6 is not valid
.a.2.3 is not valid
1.2.3.4 is not valid
1.2. 3.4 is not valid
,,, is not valid

从工程化角度考虑,有几点需要注意:

1、输入的字符串是否有效?
    不但要判断输入字符串是否为空,还要在处理过程中随时检查中间结果值,快速返回。
    需要考虑“.”的非法位置,如开头和结尾不能有“.”。
    需要考虑某段数字过长(超过255)。
    需要考虑“.”的个数,必须有且只有3个。

2、快速识别错误并退出
    发现有问题就快速退出,不需要进行无谓的多余计算。

3、考虑到转换失败的情况,所以返回值设定为bool,通过参数指针来返回转换结果。
    如果设定UInt为返回值,则无法通过返回值判断转换是否成功。
    需要的话,可以将bool的返回值改为enum,从而返回各种错误类型供调用者使用。

从编程角度考虑,有几点需要注意:

1、从后向前扫描字符串时,需要注意处理顺序。
    先判断字符是否为“.”,然后判断是否为非数字,剩下的就是数字了。
    这样的顺序逻辑清晰,便于在发现问题时快速退出。

2、对于类似问题,可以将测试集先列出来,写代码时候就可以有的放矢的进行容错处理了。

[笔记]一道C语言面试题:IPv4字符串转为UInt整数的更多相关文章

  1. [笔记]一道C语言面试题:大整数乘法

    题目:输入两个数字字符串,如“1234567890”和“987654321”,返回二者相乘的结果字符串,如本例返回为“1219326311126352690”. 来源:某500强企业面试题目 思路:从 ...

  2. 一道C语言面试题:得到整数的M进制表示字符串

    题目:输入整数n和M,输出n在M进制下的表示字符串.如n=3000,M=16,输出16进制下3000的表示字符串,为“BB8” 来源:某500强企业面试题目 思路:对n取模M,将得到的数字压入栈中,再 ...

  3. [Python学习笔记1]Python语言基础 数学运算符 字符串 列表

    这个系列是我在学习Python语言的过程中记录的笔记,主要是一些知识点汇总,而非学习教程,可供有一定编程基础者参考.文中偏见和不足难以避免,仅供参考,欢迎批评指正. 本系列笔记主要参考文献是官网文档: ...

  4. 一道C语言面试题:判断字串是否可以通过重新排列字母使之对称

    题目:输入一个字符串,如“adcaeceeed”,判断是否可以通过重新排列使之可以输出对称字符串,如本例可以输出“adceeeecda”,返回True. 来源:某500强企业面试题目 思路:扫描字串, ...

  5. C语言面试题分类->字符串处理

    1.strlen:计算字符串长度(不包含'\0') 实现想法:遍历字符串,直到'\0'结束 #include<stdio.h> #include<stdlib.h> #incl ...

  6. 一道C语言面试题:写一个宏,将16位的整数转为Big Endian

    题目:输入16位整数x,如0x1234,将其转为Big Endian格式再输出,此例为输出 0x3412 来源:某500强企业面试题目 思路:将x左移8位得到a,将x右移8位得到b,a+b即为所得 / ...

  7. 【R笔记】R语言中的字符串处理函数

    内容概览 尽管R是一门以数值向量和矩阵为核心的统计语言,但字符串同样极为重要.从医疗研究数据里的出生日期到文本挖掘的应用,字符串数据在R程序中使用的频率非常高.R语言提供了很多字符串操作函数,本文仅简 ...

  8. C语言面试题大汇总之华为面试题 Eddy整理

    1.局部变量能否和全局变量重名? 答:能,局部会屏蔽全局.要用全局变量,需要使用"::" ;局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局 ...

  9. 12个有趣的C语言面试题

    摘要:12个C语言面试题,涉及指针.进程.运算.结构体.函数.内存,看看你能做出几个! 1.gets()函数 问:请找出下面代码里的问题: #include<stdio.h> int ma ...

随机推荐

  1. mysql之load语句

    LOAD DATA LOCAL INFILE 'data.txt' INTO TABLE tbl_name

  2. iOS大文件分片上传和断点续传

    总结一下大文件分片上传和断点续传的问题.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件 ...

  3. error: memcached support requires ZLIB. Use --with-zlib-dir=<DIR> to specify the prefix where ZLIB

    yum install zlib-devel

  4. spark 1.3 发布了

    悄悄地,spark 还是像往常一样,发布了1.3版本,从release notes可以看出,这一版本比较大的变化是1. 增加了DataFrame API,这样以后操作一些结构化的数据集时将会变的非常方 ...

  5. Eclipse 创建 Java 接口

    打开新建 Java 接口向导 新建 Java 接口向导可以创建新的 Java 接口.打开向导的方式有: 点击 File 菜单并选择 New > Interface 在 Package Explo ...

  6. char * const p和const char *p的区别

    1. 前者定义P为常量,即只能单向赋值一次,P++展开为p=p+1,重复赋值给常量,出错,后者P为地址变量,地址变量是指向该变量的存储地址值如:4B3F6A,不能赋给一个字符值(字符相当于ascii表 ...

  7. cocos2d-2.0-x-2.0.4生成vs2010项目模板的解决方法

    cocos2d教学书籍还有网上好多博主都说仅仅要执行一下install-templates-msvc.bat这个批处理文件即可了.但是我按了半天vs2010就是不出现令小伙伴惊喜的cocos2d wi ...

  8. 【转载】C#时间差的计算,精确输出“年月天时分秒”

    ======================== 感谢“不忘初心”大神的分享======================== 原博地址:http://www.cnblogs.com/IT-Bear/a ...

  9. week 5: ;Lasso regression & coordinate descent

    笔记. 岭回归, 计算回归系数时使( RSS(w)+λ||w||2) 最小 岭回归的结果会是所有的特征的weight都较小,但大多数又不完全为零. 而实际情况中,有的特征的确与输出值相关程度很高,we ...

  10. OpenCV学习笔记十六:opencv_calib3d模块

    一,简介: 该库用于3D信息重建,姿态估计,摄像机标定等.