Reputation: 2748
#include <cstdio>
#include <cstdint>
#include <cassert>
int main() {
std::uint64_t ui;
char c;
auto ret = std::sscanf("111K", "%lu64%[B, K, M, G]", &ui, &c);
assert(ret == 2);
assert(ui == 111);
}
I tried to use sscanf
to read a uint64_t
and a char
from one string, but it only read it ui
(assertion ret == 2
fails) every time I tried this.
Upvotes: 1
Views: 3006
Reputation: 180935
You have two issues here. First
%lu64
should be
"%" SCNu64
to read in a 64 bit integer.
The second issue is
%[B, K, M, G]
requires a char*
or wchar_t*
as its output parameter as it populates a c-string. You need to change
char c;
to at least
char c[2] // 2 because it adds a null terminator
in order capture K
. We put that all together and we get
auto ret = std::sscanf("111K", "%" SCNu64 "%[B, K, M, G]", &ui, c);
Do note that
%[B, K, M, G]
is actually trying to match all of the spaces and comma inside the brackets. You could also write it as
%[BKMG]
and get the same results.
Upvotes: 6
Reputation: 38062
Your format string is invalid.
It should go like this on 64 bit builds: "%lu%1[BKMG]"
and "%llu%1[BKMG]"
when building for 32 bits.
The universal solution uses SCNu64
macro: "%" SCNu64 "%1[BKMG]"
. This macro is defined in cinttypes
header file.
Also your last parameter is passed incorrectly. It have to be an array of characters since zero will be appended at the end. Your code leads to undefined behavior since when c
value will be written, something beyond this variable also will be written.
#include <cstdio>
#include <cstdint>
#include <cassert>
#include <iostream>
int main() {
std::uint64_t ui;
char s[32];
auto ret = std::sscanf("111K", "%lu%1[BKMG]", &ui, s);
std::cout << "ret=" << ret << " ui=" << ui << " s=" << s << "\n";
return 0;
}
https://wandbox.org/permlink/17vZ8OkydJ7zQmP4
https://wandbox.org/permlink/z21Rbsu4mAseZyS4
Upvotes: 3
Reputation: 52591
Your format string expects characters 64
to follow the integer. %lu
is the format specifier; 64
are literal characters.
Upvotes: 3