检查它是否可以是一个int很容易 – 只需检查每个数字是否在'0'
和'9'
。 但浮动更难。 我找到了这个 ,但没有一个答案真的有效。 请考虑此代码段,基于顶部(已接受)答案:
float f; int ret = sscanf("5.23.fkdj", "%f", &f); printf("%d", ret);
1
将被打印。
另一个答案建议使用strpbrk
,检查是否存在某些非法字符,但这不起作用,因为5fin7
不合法,但inf
会。
另一个答案建议检查strtod的输出。 但考虑一下:
char *number = "5.53 garbanzo beans" char *foo; strtod(number, &foo); printf("%d", isspace(*foo) || *foo == ' '));
它会打印1
。 但我不想完全删除isspace
调用,因为" 5.53 "
应该是一个有效的数字。
是否有一种优秀,优雅,惯用的方式来做我想做的事情?
如果将它与%n
(即读取的字符数)组合,第一个答案应该有效:
int len; float ignore; char *str = "5.23.fkdj"; int ret = sscanf(str, "%f %n", &ignore, &len); printf("%d", ret==1 && !str[len]);
如果字符串包含float
未包含的字符,则!str[len]
表达式将为false。 还要注意%f
之后的空格以处理尾随空格。
演示
您可以检查 – 在使用strtod
读取值后 – 其余部分仅由空格组成。 函数strspn
可以在这里提供帮助,你甚至可以定义“你的个人空白区域”来考虑:
int main() { char *number = "5.53 garbanzo beans"; char *foo; double d = strtod(number, &foo); if (foo == number) { printf("invalid number."); } else if (foo[strspn(foo, " trn")] != ' ') { printf("invalid (non-white-space) trailing characters."); } else { printf("valid number: %lf", d); } }
有没有办法检查字符串是否可以是浮点数?
sscanf(...,"%f")
方法的问题是溢出,即UB。 然而,它通常很好地处理。
而是使用float strtof(const char * restrict nptr, char ** restrict endptr);
int float_test(const char *s) { char *ednptr; errno = 0; float f = strtof(s, &endptr); if (s == endptr) { return No_Conversion; } while (isspace((unsigned char) *endptr)) { // look past the number for junk endptr++; } if (*endptr) { return Extra_Junk_At_End; } // If desired // Special cases with with underflow not considered here. if (errno) { return errno; // likely under/overflow } return Success; }
此代码非常基于dasblinkenlight的答案 。 我把它作为思考的食物。 它给出的一些答案可能不是你想要的。
#include #include static void test_float(const char *str) { int len; float dummy = 0.0; if (sscanf(str, "%f %n", &dummy, &len) == 1 && len == (int)strlen(str)) printf("[%s] is valid (%.7g)n", str, dummy); else printf("[%s] is not valid (%.7g)n", str, dummy); } int main(void) { test_float("5.23.fkdj"); // Invalid test_float(" 255. "); // Valid test_float("255.123456"); // Valid test_float("255.12E456"); // Valid test_float(" .255 "); // Valid test_float(" Inf "); // Valid test_float(" Infinity "); // Valid test_float(" Nan "); // Valid test_float(" 255 "); // Valid test_float(" 0x1.23P-24 "); // Valid test_float(" 0x1.23 "); // Valid test_float(" 0x123 "); // Valid test_float("abc"); // Invalid test_float(""); // Invalid test_float(" "); // Invalid return 0; }
使用GCC 7.1.0作为编译器在运行macOS Sierra 10.12.6的Mac上进行测试,得到输出:
[5.23.fkdj] is not valid (5.23) [ 255. ] is valid (255) [255.123456] is valid (255.1235) [255.12E456] is valid (inf) [ .255 ] is valid (0.255) [ Inf ] is valid (inf) [ Infinity ] is valid (inf) [ Nan ] is valid (nan) [ 255 ] is valid (255) [ 0x1.23P-24 ] is valid (6.775372e-08) [ 0x1.23 ] is valid (1.136719) [ 0x123 ] is valid (291) [abc] is not valid (0) [] is not valid (0) [ ] is not valid (0)
hex数可能特别成问题。 各种forms的无限和非数字也可能很麻烦。 并且带有指数( 255.12E456
)的一个示例溢出float
并生成无穷大 – 这真的没问题吗?
这里提出的大多数问题都是定义性的 – 也就是说,你如何定义你想要接受的东西。 但请注意, strtod()
将接受所有有效字符串(以及一些无效字符串,但其他测试会显示这些问题)。
显然,可以修改测试代码以使用包含字符串和所需结果的结构数组,这可以用于迭代显示的测试用例和您添加的任何额外内容。
strlen()
结果的-Werror
避免了编译警告(因为我使用-Werror
编译时-Werror
) – 有comparison between signed and unsigned integer expressions [-Werror=sign-compare]
。 如果你的字符串足够长, strlen()
的结果溢出了一个signed int
,你就会遇到其他问题,假装它们是有效的值。 OTOH,您可能想要在小数点后试验500位数 – 这是有效的。
此代码注释了对dasblinkenlight的回答的评论:
这是由dasblinkenlight发布的代码片段的变体,由于strlen(str)
可能代价高昂,因此稍微简单且效率更高:
const char *str = "5.23.fkdj"; float ignore; char c; int ret = sscanf(str, "%f %c", &ignore, &c); printf("%d", ret == 1);
说明:当且仅当转换了float时, sscanf()
返回1
,后跟可选的空格而没有其他字符。
也许这个? 不太好,但可以做这个工作。 在没有完成转换的情况下,在错误0上返回-1,在设置了转换数字标志的情
#define INT_CONVERTED (1 << 0) #define FLOAT_CONVERTED (1 << 1) int ReadNumber(const char *str, double *db, int *in) { int result = (str == NULL || db == NULL || in == NULL) * -1; int len = 0; char *tmp; if (result != -1) { tmp = (char *)malloc(strlen(str) + 1); strcpy(tmp, str); for (int i = strlen(str) - 1; i >= 0; i--) { if (isspace(tmp[i])) { tmp[i] = 0; continue; } break; } if (strlen(tmp)) { if (sscanf(tmp, "%lf%n", db, &len) == 1 && strlen(tmp) == len) { result |= FLOAT_CONVERTED; } if (sscanf(tmp, "%d%n", in, &len) == 1 && strlen(tmp) == len) { result |= INT_CONVERTED; } } free(tmp); } return result; }
以上就是c/c++开发分享有没有办法检查字符串是否可以是C中的浮点数?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/560836.html