Elr*_*nnd 16 c string number-formatting
检查它是否可以是一个int很容易 - 只需检查每个数字是否在'0'和之间'9'.但浮动更难.我找到了这个,但没有一个答案真的有效.请考虑此代码段,基于顶部(已接受)答案:
float f;
int ret = sscanf("5.23.fkdj", "%f", &f);
printf("%d", ret);
Run Code Online (Sandbox Code Playgroud)
1 将被打印.
另一个答案建议使用strpbrk,检查是否存在某些非法字符,但这不会起作用,因为5fin7这不合法,但inf会.
另一个答案建议检查strtod的输出.但考虑一下:
char *number = "5.53 garbanzo beans"
char *foo;
strtod(number, &foo);
printf("%d", isspace(*foo) || *foo == '\0'));
Run Code Online (Sandbox Code Playgroud)
它会打印出来1.但我不想isspace完全删除呼叫,因为" 5.53 "应该是一个有效的号码.
有没有一种优雅,优雅,惯用的方式去做我想做的事情?
das*_*ght 12
第一个答案应该有效,如果你把它与%n它结合起来,这是读取的字符数:
int len;
float ignore;
char *str = "5.23.fkdj";
int ret = sscanf(str, "%f %n", &ignore, &len);
printf("%d", ret==1 && !str[len]);
Run Code Online (Sandbox Code Playgroud)
!str[len]如果字符串包含未包含的字符,则表达式将为false float.还要注意%f后跟空格的空格.
Ste*_*ner 10
您可以检查 - 在使用读取值后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, " \t\r\n")] != '\0') {
printf("invalid (non-white-space) trailing characters.");
}
else {
printf("valid number: %lf", d);
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法检查字符串是否可以是浮点数?
该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;
}
Run Code Online (Sandbox Code Playgroud)
该代码密切基于dasblinkenlight的答案。我将其提供给大家深思。它给出的一些答案可能不是你想要的。
\n\n#include <stdio.h>\n#include <string.h>\n\nstatic void test_float(const char *str)\n{\n int len;\n float dummy = 0.0;\n if (sscanf(str, "%f %n", &dummy, &len) == 1 && len == (int)strlen(str))\n printf("[%s] is valid (%.7g)\\n", str, dummy);\n else\n printf("[%s] is not valid (%.7g)\\n", str, dummy);\n}\n\nint main(void)\n{\n test_float("5.23.fkdj"); // Invalid\n test_float(" 255. "); // Valid\n test_float("255.123456"); // Valid\n test_float("255.12E456"); // Valid\n test_float(" .255 "); // Valid\n test_float(" Inf "); // Valid\n test_float(" Infinity "); // Valid\n test_float(" Nan "); // Valid\n test_float(" 255 "); // Valid\n test_float(" 0x1.23P-24 "); // Valid\n test_float(" 0x1.23 "); // Valid\n test_float(" 0x123 "); // Valid\n test_float("abc"); // Invalid\n test_float(""); // Invalid\n test_float(" "); // Invalid\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n使用 GCC 7.1.0 作为编译器在运行 macOS Sierra 10.12.6 的 Mac 上进行测试,得到输出:
\n\n[5.23.fkdj] is not valid (5.23)\n[ 255. ] is valid (255)\n[255.123456] is valid (255.1235)\n[255.12E456] is valid (inf)\n[ .255 ] is valid (0.255)\n[ Inf ] is valid (inf)\n[ Infinity ] is valid (inf)\n[ Nan ] is valid (nan)\n[ 255 ] is valid (255)\n[ 0x1.23P-24 ] is valid (6.775372e-08)\n[ 0x1.23 ] is valid (1.136719)\n[ 0x123 ] is valid (291)\n[abc] is not valid (0)\n[] is not valid (0)\n[ ] is not valid (0)\nRun Code Online (Sandbox Code Playgroud)\n\n十六进制数字可能特别有问题。各种形式的无穷大和非数字也可能很麻烦。255.12E456带有指数 ( )的示例溢出float并生成无穷大 \xe2\x80\x94 真的可以吗?
这里提出的大多数问题都是定义性的\xe2\x80\x94,即你如何定义你想要接受的内容。但请注意,strtod()它将接受所有有效字符串(以及一些无效字符串,但其他测试会揭示这些问题)。
显然,可以修改测试代码以使用包含字符串和所需结果的结构数组,并且这可以用于迭代显示的测试用例以及您添加的任何额外内容。
\n\n对结果的强制转换strlen()避免了编译警告(错误,因为我使用 编译-Werror) \xe2\x80\x94 comparison between signed and unsigned integer expressions [-Werror=sign-compare]。如果您的字符串足够长,导致结果strlen()溢出有符号的int,那么您会遇到其他问题,假装它们是有效值。OTOH,您可能想尝试小数点 \xe2\x80\x94 后有效的 500 位数字。
此代码记录了对 dasblinkenlight 的答案的评论:
\n\n