[笔记]一道C语言面试题:IPv4字符串转为UInt整数

题目:输入一个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 < 7) || (Len > 15)) {
        return false;
    }

    int num[4] = { 0 };     // 4 parts of number
    int partNum = 0;        // 1 part of number
    int base = 1;           // 10^base
    int dotCount = 0;       // dot count

    // from right to left
    for (int i = Len - 1; i >= 0; --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 == 0) || (i == Len - 1)){
                return false;
            }
            dotCount++;

            // if more than 3 dot found, e.g. "1.2.3.4.5", exit
            if (dotCount > 3) {
                return false;
            }

            // save partNum to num[]
            num[dotCount - 1] = partNum;
            partNum = 0;
            base = 1;
        }
        else if ((ch < ‘0‘) || (ch > ‘9‘)) {
            // if illeagal char inside, exit
            return false;
        }
        else {
            // handle digit char
            partNum += (ch - ‘0‘) * base;
            base *= 10;

            if (partNum > 255) {
                return false;
            }

            // handle first part num
            if (i == 0) {
                // if count of "." is not enough, exit
                if (dotCount != 3) {
                    return false;
                }
                num[dotCount] = partNum;
            }
        }
    }

    // output ip
    *ip = 0;
    for (int i = 0; i < 4; ++i) {
        *ip += num[i] << (i * 8);
    }

    return true;
}

int main(int argc, char* argv[])
{
    char* strIP[] = {
        "1",
        "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 = 0; i < sizeof(strIP) / sizeof(char *); ++i){
        unsigned int ip = 0;
        if (ConvertIPv4ToUInt(strIP[i], &ip)){
            printf("%s -> %08X\n", strIP[i], ip);
        }
        else {
            printf("%s is not valid\n", strIP[i]);
        }
    }

    getchar();
    return 0;
}

输出结果为:

1 is not valid
1.2 is not valid
1.2.3 is not valid
111.222.113 is not valid
1.2.3. is not valid
.1.2.3 is not valid
256.1.2.3 is not valid
1.2.3.4 -> 01020304
1.2.3.4.5 is not valid
12.234.45.6 -> 0CEA2D06
12.2345.45.6 is not valid
1.a.2.3 is not valid
1.2.3.4  is not valid
1.2. 3.4 is not valid
1,2,3,4 is not valid

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

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

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

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

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

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

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

[笔记]一道C语言面试题:IPv4字符串转为UInt整数

时间: 2024-08-07 08:39:32

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

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

题目:输入两个数字字符串,如“1234567890”和“987654321”,返回二者相乘的结果字符串,如本例返回为“1219326311126352690”. 来源:某500强企业面试题目 思路:从尾部到头部,对两个字串的每个数字分别相乘,并放入结果字符串相应的位置. #include "stdio.h" #include "stdlib.h" #include "string.h" char *BigNumMultiply(const cha

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

这个系列是我在学习Python语言的过程中记录的笔记,主要是一些知识点汇总,而非学习教程,可供有一定编程基础者参考.文中偏见和不足难以避免,仅供参考,欢迎批评指正. 本系列笔记主要参考文献是官网文档:http://docs.python.org/.在此向文档编辑者致谢.请勿将本文用于商业用途. 一.Python语言介绍 首先,Python是一种广泛应用的通用高级编程语言,具有较高的抽象层次,支持面向对象的编程方法.其具有高级的数据结构和许多方便的库文件,可以完成文件IO.系统调用.网络编程,甚至

一道字节跳动面试题——判断字符串交错

判断字符串交错 给定三个字符串a, b, c, 判断c是否可以通过字符串a, b的子串按顺序交错组成. 例如: a: "btdne" b: "yeac" c: "bytedance" 返回: True a: "bytece" b: "dan" c: "bytedance" 返回: True a: "bytec" b: "dan" c: "

C语言将一个字符串转换成整数

1.环境 ubuntu16.04 Eclipse C语言 2.问题 用C语言编写程序,将一个字符串转换成整数. 3.解决方法 程序代码:https://github.com/southeast02/JZOF/blob/master/chap01_page12_1.c

C语言面试题大汇总

C语言面试题大汇总 1.局部变量能否和全局变量重名? 答:能,局部会屏蔽全局.要用全局变量,需要使用"::" ;局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量.对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内. 2.如何引用一个已经定义过的全局变量? 答: extern 可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引

华为C语言笔试题集合

①华为笔试题搜集 1.static有什么用途?(请至少说明两种)    1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变.    2) 在模块内(但在函数体外),一个被声明为静态的变量能够被模块内所用函数訪问,但不能被模块外其他函数訪问.它是一个本地的全局变量.    3) 在模块内,一个被声明为静态的函数仅仅可被这一模块内的其他函数调用.那就是,这个函数被限制在声明它的模块的本地范围内使用 2.引用与指针有什么差别?    1) 引用必须被初始化,指针不必.    2)

12个有趣的C语言面试题及答案

12个C语言面试题,涉及指针.进程.运算.结构体.函数.内存,看看你能做出几个! 1.gets()函数 问:请找出下面代码里的问题: #include<stdio.h> int main(void) { char buff[10]; memset(buff,0,sizeof(buff)); gets(buff); printf("\n The buffer entered is [%s]\n",buff); return 0; } 答:上面代码里的问题在于函数gets()的

Python源码剖析笔记0 ——C语言基础

python源码剖析笔记0--C语言基础回顾 要分析python源码,C语言的基础不能少,特别是指针和结构体等知识.这篇文章先回顾C语言基础,方便后续代码的阅读. 1 关于ELF文件 linux中的C编译得到的目标文件和可执行文件都是ELF格式的,可执行文件中以segment来划分,目标文件中,我们是以section划分.一个segment包含一个或多个section,通过readelf命令可以看到完整的section和segment信息.看一个栗子: char pear[40]; static

Go语言学习笔记(一) [Go语言的HelloWorld]

日期:2014年7月18日 1.简介 Go 编程语言是一个使得程序员更加有效率的开源项目.Go 是有表达力.简 洁.清晰和有效率的.它的并行机制使其很容易编写多核和网络应用,而新奇的类型系统允许构建有性的模块化程序.Go 编译到机器码非常快 速,同时具有便利的垃圾回收和强大的运行时反射.它是快速的.静态类型编译语言,但是感觉上是动态类型的,解释型语言. Go 是第一个实现了简单的(或更加简单的)并行开发,且跨平台的类 C 语言. 2.Go语言文档查看 安装好Go语言之后,其文档可以通过go do