简体   繁体   中英

The function sscanf_s fail when I use several strings

I don't understand why the code below fail :

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

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

or

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

My problem is only with strings (float, int, double etc. its ok) and I use Visual 2010.

Does anyone have an idea? Thanks a lot in advance for your answer.

From the sscanf_s() reference page:

The sscanf_s function reads data from buffer into the location given by each argument. The arguments after the format string specify pointers to variables with a type that corresponds to a type specifier in format. Unlike the less secure version sscanf, a buffer size parameter is required when using the type field characters c, C, s, S and [. The buffer size in characters must be supplied as an additional parameter after each buffer which requires it. For more information, see scanf_s, _scanf_s_l, wscanf_s, _wscanf_s_l and scanf Type Field Characters.

Meaning each buffer must be followed by its size:

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

Additionally, - is not a whitespace character will not act as a terminator for "%s" format specifier so if line contained hello-world then it would be read into toto and titi would not be assigned. To use - as a terminator use a scan set:

if (2 == sscanf_s(line, "%[^-]-%s", toto, sizeof(toto), titi, sizeof(titi)))
{
    /* Both 'toto' and 'titi' where assigned. */
}

Unless sscanf_s() is distincly weird, you don't want to pass a pointer to the array ( &toto ) but a pointer to the first element of the array ( toto ). Also, the goal of the secure functions is to avoid buffer overruns, ie, you need to specify for each individual buffer how many characters it contains:

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

(error handling because attempts to read should always check whether an error occured before processing the data)

Personally, I would use an std::istringstream together with strings and a suitable custom manipulator and avoid the issue entirely:

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)) {
    ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM