how to replace sscanf in c++?

Jul 26, 2021 at 5:31pm
I am just wondering if there any replacement in c++ for sscanf?
Below is the lines of code which I need to replace sscanf. Any idea? Should I use std::sscanf?

1
2
3
4

 bool outputdetails = argc < 5 ||
        (sscanf(argv[3], "%.2f%%", &percentage) != 1) ||
        (sscanf(argv[4], "%i", &degree) != 1);
Jul 26, 2021 at 5:59pm
I suppose one should point out that you don't need to replace anything. "If it ain't broke, don't fix it."

Should I use std::sscanf?
It's the same function, just wrapped in the std namespace, so you wouldn't be changing any functionality by doing this.

The high-performance, C++ method for this type of parsing would probably be std::from_chars, but it isn't really one-to-one with sscanf, since I don't think it let's you parse 42 out of "ijk 42 xyz".
https://en.cppreference.com/w/cpp/utility/from_chars
But for your purposes, if it's a simple float or int you need to parse, it will still work.

Perhaps simpler would be to use std::stoi or std::stod (string-to-int, string-to-double)
https://en.cppreference.com/w/cpp/string/basic_string/stol
https://en.cppreference.com/w/cpp/string/basic_string/stof

There's multiple ways to do it. Command-line argument parsing is a once-and-done thing, so the method you choose isn't really important.
Last edited on Jul 26, 2021 at 6:18pm
Jul 26, 2021 at 6:40pm
do you mean to say I should not use std::sscanf instead of sscanf?
I thought of using this way..Anything wrong in it?

1
2
3
4
bool outputdetails = argc < 5 ||
        (std::sscanf(argv[3], "%.2f%%", &percentage) != 1) ||
        (std::sscanf(argv[4], "%i", &degree) != 1);
Jul 26, 2021 at 8:31pm
It's the same as your original post. Not better or worse. It's the same functionality.

If we want to get into the nitty gritty (not necessary, probably will just confuse you): Strictly speaking, if you are #including <cstdio>, then it's not guaranteed that those functions will be in the global namespace, so prepending std:: is safer, but all compilers that you'll ever encounter will be perfectly fine without the std::.

Here is a complete C++20 (17?) example using from_chars:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Example program
#include <iostream>
#include <string>
#include <charconv>

template <typename T>
bool parse(const std::string& str, T& result)
{
    result = T();
    
    // https://en.cppreference.com/w/cpp/utility/from_chars
    auto [p, ec] = std::from_chars(str.data(), str.data() + str.size(), result);
    return (ec == std::errc()); // true if no errors
}

int main(int argc, char* argv[])
{
    double percentage;
    int degree;

    bool failure = argc < 5 ||
        !parse(argv[3], percentage) ||
        !parse(argv[4], degree);

    if (!failure)
    {
        std::cout << "Percentage: " << percentage << '\n'
                  << "Degree: " << degree << '\n';
    }
    else
    {
        std::cout << "Failure parsing arguments\n";   
    }
}

Percentage: 3.14
Degree: 42


You can run it on https://wandbox.org/
Enter each runtime argument as a separate line, e.g.
blah
blah
3.14
42


If you don't have C++17/20 support, you can refactor the code to use std::stoi or std::stod like I previously mentioned. Or stick with std::sccanf.
Last edited on Jul 26, 2021 at 8:55pm
Jul 27, 2021 at 5:32am
It's also worth bearing in mind for robust code that scanf type functions do not detect numeric overflow or underflow, which these methods do (as Ganado shows).

You can also add from C land.
https://en.cppreference.com/w/c/string/byte/strtol
https://en.cppreference.com/w/c/string/byte/strtoul
https://en.cppreference.com/w/c/string/byte/strtof
Jul 28, 2021 at 4:11am
I dont have C++17/20 support. So I shall go ahead and use std::sscanf.
Topic archived. No new replies allowed.