Caffeinated
Caffeinated

Reputation: 12484

In C, what is a safe alternative to sscanf?

I found online that in C++ there's an alternative, but what about plain-old C? I appreciate any tips or advice.

Upvotes: 11

Views: 30331

Answers (3)

Fries
Fries

Reputation: 359

Under Windows, you can use sscanf_s (see https://msdn.microsoft.com/en-us/library/t6z7bya3.aspx) which require you to provide the buffer length for every %s match as an argument right after the buffer argument.

For example, sscanf_s( tokenstring, "%s", s, (unsigned)_countof(s) );.

Upvotes: 4

ulatekh
ulatekh

Reputation: 1490

I believe you're looking for the "m" modifier. It dynamically allocates memory to hold the extracted string, so as to avoid buffer overflows. The only drawback is that it's a GNU extension, so e.g. MSVC probably won't recognize it.

Here is an existing Stack Overflow answer on that topic.

Here's an example of how to use it:

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

int main(void)
{
    char *str;
    printf("Enter your name:\n");
    scanf("%ms", &str);

    printf("Hello %s!\n", str);
    free(str);
    return 0;
}

Upvotes: 6

Keith Thompson
Keith Thompson

Reputation: 263247

It depends on what you want to do with it.

Since you have the string in memory, you can safely avoid buffer overflows by being careful about the arguments you pass. For example, if you're scanning into a string, using "%s", just use a target buffer big enough to hold the biggest string that could possibly be there (and make sure that the source buffer is a valid string, i.e., that it's '\0'-terminated).

One danger of all the *scanf() functions is that if you're scanning a numeric value, and the input value is too big to be represented in the target type, the behavior is undefined. For example, this program:

#include <stdio.h>
int main(void) {
    const char *s = "999999999999999999999999999";
    int n;
    sscanf(s, "%d", &n);
    printf("n = %d\n", n);
    return 0;
}

has undefined behavior (unless INT_MAX is really really big).

You can safely scan numeric values using the strto*() functions: strtol(), strtoll(), strtoul(), strtoull(), strtof(), strtod(), strtold(). Their behavior on errors is a bit tricky, but at least it's well defined.

Upvotes: 10

Related Questions