惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threatpost
S
Schneier on Security
P
Palo Alto Networks Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
S
Securelist
T
Threat Research - Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Vulnerabilities – Threatpost
AI
AI
C
CERT Recently Published Vulnerability Notes
C
Cyber Attacks, Cyber Crime and Cyber Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Know Your Adversary
Know Your Adversary
AWS News Blog
AWS News Blog
TaoSecurity Blog
TaoSecurity Blog
O
OpenAI News
Cyberwarzone
Cyberwarzone
G
GRAHAM CLULEY
SecWiki News
SecWiki News
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
I
Intezer
C
CXSECURITY Database RSS Feed - CXSecurity.com
C
Cisco Blogs
K
Kaspersky official blog
Spread Privacy
Spread Privacy
S
Security @ Cisco Blogs
Hacker News - Newest:
Hacker News - Newest: "LLM"
IT之家
IT之家
有赞技术团队
有赞技术团队
B
Blog
T
Tailwind CSS Blog
PCI Perspectives
PCI Perspectives
P
Privacy & Cybersecurity Law Blog
Last Week in AI
Last Week in AI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Webroot Blog
Webroot Blog
博客园 - 叶小钗
Cisco Talos Blog
Cisco Talos Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Hacker News: Front Page
The Cloudflare Blog
C
Cybersecurity and Infrastructure Security Agency CISA
美团技术团队
V
V2EX
腾讯CDC
S
SegmentFault 最新的问题
Security Archives - TechRepublic
Security Archives - TechRepublic

博客园 - 喜欢Ⅰ

先避免毁灭性错误,再谈聪明决策 通往天堂的三个阶梯 人类随机数趣闻 - 即使人们会觉得它更随机,但实际上它更不随机 C 里面如何使用链表 list 项目代码套路 墨菲定律 - 人类一种误判心理 消息队列, 一种取舍的选择 Redis Stream CORS 跨域请求一种后端适配解决方案 自我的智慧 市场教父 André Kostolany Exception Handling Considered Harmful MySQL CREATE TABLE Template 模板设计简单交流 atomic 原子自增工程案例 HTTP 尝试获取 Client IP 对炒股看法 吃饱年代 我是个怎样的人 格林童话之祖父和孙子 Linux 守护进程 智慧 ~ 引子 ~ 三则故事 交易人生 大道至简
字符串转整型
喜欢Ⅰ · 2022-03-08 · via 博客园 - 喜欢Ⅰ

🙏

奇奇怪怪编码 - 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.

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 来判断越界, 当然这种做法前头已经说了, 不同平台兼容性上, 存在潜在问题, 不推荐.  

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