Convert string to GUID using sscanf

I am trying to convert a string to a GUID using sscanf:

GUID guid; sscanf( "11111111-2222-3333-4455-667788995511", "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", &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]); 

However, at runtime it crashes and fails with the error "Error: command". What for? How to fix it?

I do not want to compile with / clr, so I can not use System .

+4
source share
4 answers

Where does the Error: Command error come from? This is not a standard error message ...

You can use the UuidFromString function to do this in native C ++.

+5
source

I think you are damaging the stack. An X type specifier requires an int pointer that is at least 4 bytes long, therefore, starting with the & guid.Data [4] parameter that you messed up. Provide enough space for sscanf and everything should be in order. The final code is as follows:

  GUID guid; unsigned long p0; int p1, p2, p3, p4, p5, p6, p7, p8, p9, p10; int err = sscanf_s(s.c_str(), "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", &p0, &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10); guid.Data1 = p0; guid.Data2 = p1; guid.Data3 = p2; guid.Data4[0] = p3; guid.Data4[1] = p4; guid.Data4[2] = p5; guid.Data4[3] = p6; guid.Data4[4] = p7; guid.Data4[5] = p8; guid.Data4[6] = p9; guid.Data4[7] = p10; 
+7
source

You can also use CLSIDFromString if you want to avoid the dependency on RPCRT4.DLL. The CLSID is just a GUID, so it will work despite a somewhat confusing name.

0
source

Since C ++ 11 and C99 are there, you can now parse the GUID string directly in the GUID structure using argument size specifiers like e. d. hh , which denotes single-byte data. However, the correct and portable way, which does not depend on the platform sizes 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 

Macros in <inttypes.h> can be defined differently by different compilers and bit systems; just for example, on my system they

 #define SCNx8 "hhx" #define SCNx16 "hx" #define SCNx32 "x" #define SCNx64 "llx" 

The %n at the end returns the length of the string processed so far, so if there is no line ending } , %n will not be reached, and nchars will have an initial value of -1, otherwise it will return the length of the GUID string, which must be 38 (otherwise, for example, the last byte can be parsed, even if it is one hexadecimal character that would not be valid for the GUID). %n itself is not considered a "field" for the sscanf return value.

This is still not fantastically correct, since the parser accepts spaces instead of leading zeros for each component, so there is a line with strategically placed spaces

 { FACFFB- C-4DF3-A06C-D4 1 A 2 B 3} 

will still be sorted out as if he were

 {00FACFFB-000C-4DF3-A06C-D4010A020B03} 

but this is probably only possible with one sscanf .

0
source

Source: https://habr.com/ru/post/1309622/


All Articles