• 面试题: 字符串转整型 终结者


    前言

    很久之前写过一篇奶头乐,关于简单面试题总结.  重新翻阅看到这个题目.

    /*
     * 写一个函数 "将整数字符串转成整数"
     */

    随着代码手感增强, 想为这个问题写个终结者系列.  缅怀下曾经的自己. 

    奇奇怪怪编码 - https://www.emojiall.com/zh-hans/code/1F64F

    正文

    我们审视下这个问题, 整数字符串转成整数. 那么意味着有效字符仅有 "+-0123456789". 

    其中整数常见有 short, int , long, long long 等对吧. 大部分人会写成 string convert int. 

    这里存在一个潜在模糊知识是, C 标准规定 sizeof(long long) >= sizeof (long) >= sizeof(int) >= sizeof(short).

    但没有明说具体多大, 这就意味着不同平台实现上可以自由发挥. 例如 sizeof (long) 多数 linux 平台是 8, window 是 4.

    所以这里不写那么复杂. 简单点 string convet int32.

    因此写题目开始可以和对方一块交流探讨下. 有了 string convert int32 经验加一些平台分支宏搞出 string convert int 也容易. 

    那我们开始吧. 

    相关素材 : https://github.com/wangzhione/temp/blob/master/code/offer1/67_string_int.c#L17-L75

    #include <stdio.h>
    #include <limits.h>
    #include <stddef.h>
    #include <stdint.h>
    #include <assert.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdbool.h>
    
    /* describe : 
    
       写一个完整 string to int32_t
     */
    
    #define NUMBER_SUCCESS  0    // 转换成功
    #define NUMBER_INVALID -2    // 非法字符
    #define NUMBER_BORDER  -3    // 数值越界
    
    int str2int32(const char * str, int32_t * res) {
        if (str == NULL) {
            return NUMBER_INVALID;
        }
    
        if (*str == 0) {
            if (res) *res = 0;
            return NUMBER_SUCCESS;
        }
    
        // int32_t    int    Signed    32    4    -2,147,483,648    2,147,483,647
        // + - 1 字节, 后面 max size = 10
        // 如果 max size = 10, 那么 max size = 9 的时候最大值为 2,147,483,64
    
        int32_t num = 0;
        bool minus = false; // 标识负数
        if (*str == '+' || *str == '-') {
            minus = *str++ == '-';
        }
    
        char c;
        int count = 0;
        while (++count < 10 && (c = *str++) != 0) {
            if (c >= '0' && c <= '9') {
                // 合理字符
                num = 10 * num + c - '0';
            } else {
                return NUMBER_INVALID;
            }
        }
        if (c != 0) {
            if (num > 214748364) {
                // size = 9 时候最大值
                return NUMBER_BORDER;
            }
            c = *str++;
            if (*str != 0) {
                // size > 10 越界
                return NUMBER_BORDER;
            }
            if ((c >= '0' && c <= '7') || (c == '8' && minus)) {
                if (c == '8') {
                    if (res) *res = -2147483648;
                    return NUMBER_SUCCESS;
                }
                num = 10 * num + c - '0';
            } else {
                return NUMBER_BORDER;
            }
        }
    
        num = minus ? -num : num;
        if (res) *res = num;
        return NUMBER_SUCCESS;
    }
    
    
    // build:
    // gcc -g -O3 -Wall -Wextra -Werror -o 67_string_int 67_string_int.c
    //
    int main(void) {
        int code;
        int32_t num;
        const char * str;
    
        num = 0;
        str = NULL;
        code = str2int32(str, &num);
        printf("code = %d, str = %s, num = %d\n", code, str, num);
        assert(code == NUMBER_INVALID && num == 0);
    
        num = 0;
        str = "-1";
        code = str2int32(str, &num);
        printf("code = %d, str = %s, num = %d\n", code, str, num);
        assert(code == NUMBER_SUCCESS && num == -1);
    
        num = 0;
        str = "1234A";
        code = str2int32(str, &num);
        printf("code = %d, str = %s, num = %d\n", code, str, num);
        assert(code == NUMBER_INVALID);
    
        num = 0;
        str = "2147483647";
        code = str2int32(str, &num);
        printf("code = %d, str = %s, num = %d\n", code, str, num);
        assert(code == NUMBER_SUCCESS && num == 2147483647);
    
        num = 0;
        str = "-2147483648";
        code = str2int32(str, &num);
        printf("code = %d, str = %s, num = %d\n", code, str, num);
        assert(code == NUMBER_SUCCESS && num == -2147483648);
    
        num = 0;
        str = "-2147483649";
        code = str2int32(str, &num);
        printf("code = %d, str = %s, num = %d\n", code, str, num);
        assert(code == NUMBER_BORDER);
    
        num = 0;
        str = "2147483648";
        code = str2int32(str, &num);
        printf("code = %d, str = %s, num = %d\n", code, str, num);
        assert(code == NUMBER_BORDER);
    
        exit(EXIT_SUCCESS);
    }

    整体代码分两部分实现 str2int32 和 assert 单元测试 . 单元测试怎么强调都不为过, 这是成为高手必经之路.

    其中实现围绕核心思路是下面这些数学知识. 

    int32_t    int    Signed    32    4    -2,147,483,648    2,147,483,647

    实现层面没有借助 long 来判断越界, 当然这种做法前头已经说了, 存在潜在问题, 不推荐.  

    这类数据转换函数很多是跨学科, 对于普通工程师而言有点吃力, 感谢相关科学家或专业人士铸就了今天的基础. 

    希望以上思路能终结这个面试题. 欢迎大家补充更优更完备

  • 相关阅读:
    8.02_python_lx_day14
    8.02_python_lx_day13<2>
    8.02_python_lx_day13<1>
    7.30_python_lx_day20
    7.29_python_lx_da19
    7.29_python_lx_day12
    Docker镜像
    Docker学习Ⅱ
    Docker学习Ⅰ
    2-3树的插入和删除原理
  • 原文地址:https://www.cnblogs.com/life2refuel/p/15981687.html
Copyright © 2020-2023  润新知