当我使用多个字符串时,函数sscanf_s失败

时间:2012-11-07 22:16:23

标签: c visual-studio-2010 parsing scanf

我不明白为什么下面的代码失败了:

char    toto[54], titi[54]; //I already tried with allocations

sscanf_s(line, "%s-%s", &toto, &titi, sizeof(toto) + sizeof(titi));

sscanf_s(line, "%s-%s", &toto, &titi, sizeof(toto) + sizeof(titi));

我的问题只有字符串(float,int,double等等),我使用Visual 2010。

有没有人有想法? 非常感谢您的回答。

2 个答案:

答案 0 :(得分:5)

来自sscanf_s()参考页:

  

sscanf_s函数将数据从缓冲区读入每个参数给出的位置。格式字符串后面的参数指定指向变量的指针,其类型与格式中的类型说明符相对应。 与安全性较低的版本sscanf不同,使用类型字段c,C,s,S和[时,需要一个缓冲区大小参数。在每个需要它的缓冲区之后,必须以字符形式提供缓冲区大小作为附加参数。有关更多信息,请参阅scanf_s,_scanf_s_l,wscanf_s,_wscanf_s_l和scanf类型字段字符。

意味着每个缓冲区必须跟其大小:

sscanf_s(line, "%s-%s", toto, sizeof(toto), titi, sizeof(titi));

此外,-不是空白字符,不会充当"%s"格式说明符的终止符,因此如果line包含hello-world,则会将其读入{{不会分配1}}和toto。要使用titi作为终结符,请使用扫描集:

-

答案 1 :(得分:0)

除非sscanf_s()非常奇怪,否则您不希望传递指向数组(&toto)的指针,而是指向数组的第一个元素(toto)的指针。此外,安全功能的目标是避免缓冲区溢出,即,您需要为每个缓冲区指定它包含的字符数:

if (sscanf_s(line, "%s-%s", toto, sizeof(toto), titi, sizeof(titi)) == 2) {
    ...
}

(错误处理,因为尝试读取时应始终检查在处理数据之前是否发生错误)

就个人而言,我会将std::istringstream与字符串和合适的自定义操纵器一起使用,并完全避免这个问题:

std::istream& minus(std::istream& in) {
    if ((in >> std::ws).peek() != std::char_traits<char>::to_int_type('-')) {
        in.setstate(std::ios_base::failbit);
    }
    else {
        in.ignore();
    }
    return in;
}

std::string toto, titi;
if (std::istringstream(line) >> std::skipws >> toto >> minus >> titi)) {
    ...
}