使用sscanf将字符串转换为GUID

时间:2010-05-13 04:43:16

标签: c++ c guid scanf

我正在尝试使用sscanf将字符串转换为GUID:

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]);

但是,在运行时,它会失败并以“错误:命令失败”退出。为什么?如何解决?

我不想用/ clr编译,所以不能使用System

5 个答案:

答案 0 :(得分:8)

我认为你正在破坏堆栈。 X类型说明符需要指向int的指针,该指针至少为4个字节,因此从& guid.Data [4]参数开始,你已经搞砸了。为sscanf提供足够的空间,你应该没问题。最终代码如下所示:

    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;

答案 1 :(得分:5)

“错误:命令失败”来自何处?这不是标准错误消息......

您可以使用UuidFromString函数在本机C ++中执行此操作。

答案 2 :(得分:2)

由于C ++ 11和C99已经存在,现在可以使用argument size specifiers(例如e)将GUID字符串解析为GUID结构。 G。 hh代表单字节数据。但是,正确且可移植的方式不依赖于longintshort的平台大小,而是使用<inttypes.h>(或<cinttypes>中提供的宏对于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

<inttypes.h>中的宏可能由不同的编译器和系统位数来定义;仅仅为了举例,在我的系统中,它们在<inttypes.h>中被定义为

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

最后的%n说明符返回解析后的字符串的长度&#34;到目前为止&#34;,所以如果字符串缺少尾随的}%n会没有到达,nchars将具有-1的初始值,否则它将返回GUID字符串的长度,该字符串必须为38(否则,例如,即使它是单个十六进制,最后一个字节也可以解析字符,对于GUID无效)。 %n本身不算作&#34;字段&#34;出于sscanf的返回值。

这仍然不是非常正确,因为解析器接受空格来代替每个组件的前导零,以便具有战略性放置空格的字符串

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

仍将解析为

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

但这可能只有一个sscanf

答案 3 :(得分:2)

工作且不会损坏堆栈:

GUID guid;

sscanf_s(AliasName.c_str(), "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",
        &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]);

答案 4 :(得分:0)

如果你想避免RPCRT4.DLL依赖,你也可以使用CLSIDFromString - CLSID只是一个GUID,所以尽管名称有些混乱,它仍然有效。