防止sscanf将double解析为int

r6hnlfcb  于 2023-04-19  发布在  其他
关注(0)|答案(2)|浏览(203)

当输入字符串是例如“4.5”时,我希望sscanf不要将其解析为整数。但现在它这样做了。
我的代码看起来像这样:if (sscanf(str, "%d", &val) == 0) { return NULL; }这当然不起作用,因为sscanf将“4.5”解析为4,并且不返回NULL
多谢帮忙

nxagd54h

nxagd54h1#

sscanf("4.5", "%d", &val)不会将“4.5”解析为4。它将“4”解析为4,而不解析“.5”。您可以验证sscanf不会解析字符串中的任何其他字符:

int val;
char c;
if (sscanf(str, "%d%c", &val, &c) != 1) { return NULL; }
6rqinv9w

6rqinv9w2#

sscanf()将跳过白色。它将解析前缀(在本例中为4)并忽略后缀(在本例中为.5)。如果转换的结果无法在对象中表示,则该行为未定义。
1.我建议写一个函数来解析一个整数;您可以使用strtol()进行额外的边界检查:

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>

#define FS " "

const char *parse_int(const char *s, int *v) {
    if(!s)
        return NULL;
    int sign = 1;
    if(*s == '-') {
        sign = -1;
        s++;
    }
    if(!isdigit(*s))
        return NULL;
    *v = 0;
    for(; isdigit(*s); s++) {
        int d = sign * (*s - '0');
        if(*v < (INT_MIN + d) / 10 || *v > (INT_MAX + d) / 10)
            return NULL;
        *v = *v * 10 + d;
    }
    return s;
}

const char *parse_str(const char *s, const char *expect) {
    if(!s || strncmp(s, expect, strlen(expect)))
        return NULL;
    return s + strlen(expect);
}

int main() {
    const char *str = "4.5 ";
    int d;
    // note: str will be set to NULL on parse failure; use different `const char *` variables to keep track of progress.
    (str = parse_int(str, &d)) &&
    (str = parse_str(str, FS));
    if(!str) {
        printf("parse failed");
        return 1;
    }
}

如果这对你不起作用,我有两个建议:
1.使用%n来计算字符串的剩余部分,丢弃它,因为它不是字段分隔符:

#include <stdio.h>
#include <string.h>

#define FS " "

int main() {
    char *str = "4.5";
    int val;
    int pos;
    int rv = sscanf(str, "%d%n", &val, &pos);
    if(rv != 1 || strncmp(str + pos, FS, sizeof FS - 1)) {
        printf("parse failed\n");
        return 1;
    }
}

1.读取double而不是int,并检查它是否是整数且在正确的范围内:

#include <limits.h>
#include <stdio.h>
#include <string.h>

#define delta 1e-6

int main() {
    char *str = "4.5";
    double d;
    int rv = sscanf(str, "%lf", &d);
    if(d - (int) d > delta || d > INT_MAX || d < INT_MIN) {
        printf("parse failed\n");
        return 1;
    }
}

相关问题