strtol函数不符合预期:含前置点号的字符串转长整型返回0
问题原因分析
这是strtol的标准行为导致的:它会从字符串的起始位置开始扫描,寻找合法的整数起始字符(也就是正负号+/-,或者0-9的数字)。一旦遇到第一个不符合要求的字符,它就会停止解析,并且返回0(因为此时没有找到任何有效整数)。
在你的例子里,字符串开头是空格,strtol会先跳过空白字符,但接下来遇到的是.,这并不是合法的整数起始字符,所以它直接停止解析,返回0。
解决方案
要解决这个问题,你需要先手动定位到字符串中第一个合法的整数起始位置,再调用strtol。这里有两种常用的实现方式:
方式一:针对性跳过前置的点号和空白
如果你的场景里前置字符主要是空白和.,可以写个简单的循环跳过这些字符:
#include <stdio.h> #include <stdlib.h> #include <ctype.h> int main () { char str[20] = " . 3456\r\n"; char *ptr = str; // 先跳过所有空白字符 while (isspace((unsigned char)*ptr)) { ptr++; } // 如果遇到点号,再跳过它 if (*ptr == '.') { ptr++; // 跳过点号之后可能存在的空白 while (isspace((unsigned char)*ptr)) { ptr++; } } long ret = strtol(ptr, NULL, 10); printf("ret is %ld\n", ret); return(0); }
方式二:通用的合法起始字符定位
如果你的字符串可能有各种非整数起始字符,更通用的方式是找到第一个数字或正负号的位置:
#include <stdio.h> #include <stdlib.h> #include <ctype.h> int main () { char str[20] = " . 3456\r\n"; char *ptr = str; // 移动指针,直到找到合法的整数起始字符或字符串结束 while (*ptr != '\0' && !isdigit((unsigned char)*ptr) && *ptr != '+' && *ptr != '-') { ptr++; } long ret = strtol(ptr, NULL, 10); printf("ret is %ld\n", ret); return(0); }
额外说明
如果你的字符串里是类似.3456这样的小数形式,strtol依然只会在.处停止解析。如果需要处理这类小数并转成整数,你可以先用strtod把它转成双精度浮点数,再转成长整型(注意精度丢失的风险):
double d = strtod(str, NULL); long ret = (long)d;
内容的提问来源于stack exchange,提问作者homeGrown
相关产品推荐
相关产品推荐

