Since C++11 and C99 are out there, it is now possible to parse a GUID string right into the GUID structure, using argument size specifiers such as e. g. hh
which stands for a single byte data. However, the correct and portable way that does not depend on the platform sizes of long
, int
and short
is to use macros provided in <inttypes.h>
(or <cinttypes>
for C++11):
#include <inttypes.h>
#define G32 "%8" SCNx32
#define G16 "%4" SCNx16
#define G8 "%2" SCNx8
bool to_guid(const char* str, GUID* guid) {
int nchars = -1;
int nfields =
sscanf(str, "{" G32 "-" G16 "-" G16 "-" G8 G8 "-" G8 G8 G8 G8 G8 G8 "}%n",
&guid->Data1, &guid->Data2, &guid->Data3,
&guid->Data4[0], &guid->Data4[1], &guid->Data4[2], &guid->Data4[3],
&guid->Data4[4], &guid->Data4[5], &guid->Data4[6], &guid->Data4[7],
&nchars);
return nfields == 11 && nchars == 38;
}
#undef G8
#undef G16
#undef G32
The macros in the <inttypes.h>
may be defined differently by different compilers and system bitness; just for the sake of an example, on my system they are defined in <inttypes.h>
as
#define SCNx8 "hhx"
#define SCNx16 "hx"
#define SCNx32 "x"
#define SCNx64 "llx"
The %n
specifier at the end returns the length of the string parsed "so far", so if the string is missing the trailing }
, %n
would not be reached, and nchars
will have the initial value of -1, otherwise it will return the length of the GUID string, which must be 38 (otherwise, e. g. the last byte may parse even if it is a single hex character, which would be invalid for a GUID). The %n
itself is not counted as a "field" for the purposes of sscanf
's return value.
This is still not fantastically correct, as the parser accepts spaces in lieu of leading zeroes for each component, so that the string with strategically placed spaces
{ FACFFB- C-4DF3-A06C-D4 1 A 2 B 3}
will still parse as if it was
{00FACFFB-000C-4DF3-A06C-D4010A020B03}
but this is probably as far as one can get with a single sscanf
.
UuidFromString("11111111-2222-3333-4455-667788995511",&guid);
it sayserror C2664: 'UuidFromStringA' : cannot convert parameter 1 fr om 'const char *' to 'RPC_CSTR'
... – Feebleminded