如何将 TCL 字典形成为字符串以将其作为字符串变量传递?
How to form a TCL dictionary as a string to pass it around as a string variable?
我需要格式化一个可以解释为 TCL 字典的字符串。基本上,字符串是在 C++ 中形成的,然后作为字符串变量值传递给 TCL 解释器,TCL 解释器应该能够将该字符串值视为字典。这可能吗?如果可以,该字符串应该如何格式化?
任何包含偶数个单词(由 tcl 定义)的字符串都是字典。
示例 tclsh
会话:
% set demo "a silly example string"
a silly example string
% dict get $demo a
silly
% dict get $demo example
string
如果您有多个单词的键或元素,则应将它们括在大括号中:
% set example "a {multi word value} {multi word key} test"
a {multi word value} {multi word key} test
% dict get $example a
multi word value
% dict get $example "multi word key"
test
如果您可以访问 Tcl 的 C API,请使用 the dict operations(以及其他适当的)。
Tcl_Obj *dict = Tcl_NewDictObj();
Tcl_IncrRefCount(dict);
Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj(key1, -1), Tcl_NewStringObj(value1, -1));
// etc, to build the dictionary; you need more care if you have duplicated keys
// Now, get the string value; note that the dict object OWNS the string memory
const char *stringValue = Tcl_GetString(dict);
// and once you don't need stringValue or dict any more
Tcl_DecrRefCount(dict);
否则,如果您可以形成一个包含偶数个元素的 Tcl 列表,那么它将被解释为 table 字典(字符串表示是故意重合的)。假设您不想使用基于 Tcl_Obj
的操作,还有 the low level dynamic strings(较旧的 API 在内部使用得相当多,但现在不特别推荐):
Tcl_DString buffer;
Tcl_DStringInit(&buffer);
Tcl_DStringAppendElement(&buffer, key1);
Tcl_DStringAppendElement(&buffer, value1);
// ...
const char *stringValue = Tcl_DStringValue(&buffer);
// and once you're done with everything
Tcl_DStringFree(&buffer);
在您询问之前,与 Tcl_Obj
一样,Tcl_DString
拥有与 stringValue
关联的内存。如果您希望它在释放缓冲区后仍然存在,则需要复制一份。 (请注意,Tcl_Obj
API 可能更有效,但实际上并非如此,因为您最终所做的只是从中构建一个字符串。)
如果您想自己管理内存分配,可以使用 absolute base level API. In particular, Tcl_ScanElement
will let your code work out how to format a particular element string efficiently (it returns an estimate of the space required and, via an OUT parameter, the instructions on how to do the formatting) and Tcl_ConvertElement
will do the formatting into the buffer you have prepared. Their use is a bit fiddly, so I'll just link to how Tcl itself uses them(这是 Tcl 列表对象实现的一部分)。
如果您根本没有可用的 Tcl C API,请知道您要生成一系列以空格分隔的单词。对于简单的单词(例如,只有字母数字或最基本的标点符号),您可以直接输入单词。对于任何更复杂的东西(即,如果它包含像 [
、$
、\
或任何空格这样的 Tcl 元字符),您需要将它们括在 {
大括号 }
或在违规字符前加反斜杠。在 大多数 情况下,将大括号放在周围是有效的(它失败的主要原因是不平衡的大括号;还有其他一些)。在 所有 情况下都可以使用反斜杠,但很难看;这种东西代码很容易生成,但阅读和调试起来确实可怕,尤其是嵌套列表。
这些是列表的规则。字典在格式上等同于包含偶数项的列表。字典的规范性有两个要求:分隔单词的空格应该是单个空格(这是规范的列表形式),并且字典的键(第一、第三、第五……元素)应该是唯一的。非规范词典可以工作,并且定义精确(首选出现 last 键),但当您不仔细考虑时,偶尔可能会感到惊讶。 Tcl 自己的字典代码在写入字典时总是规范化字典(因为内部模型是散列 table;您的 C 代码 不需要 需要构建它)。
我需要格式化一个可以解释为 TCL 字典的字符串。基本上,字符串是在 C++ 中形成的,然后作为字符串变量值传递给 TCL 解释器,TCL 解释器应该能够将该字符串值视为字典。这可能吗?如果可以,该字符串应该如何格式化?
任何包含偶数个单词(由 tcl 定义)的字符串都是字典。
示例 tclsh
会话:
% set demo "a silly example string"
a silly example string
% dict get $demo a
silly
% dict get $demo example
string
如果您有多个单词的键或元素,则应将它们括在大括号中:
% set example "a {multi word value} {multi word key} test"
a {multi word value} {multi word key} test
% dict get $example a
multi word value
% dict get $example "multi word key"
test
如果您可以访问 Tcl 的 C API,请使用 the dict operations(以及其他适当的)。
Tcl_Obj *dict = Tcl_NewDictObj();
Tcl_IncrRefCount(dict);
Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj(key1, -1), Tcl_NewStringObj(value1, -1));
// etc, to build the dictionary; you need more care if you have duplicated keys
// Now, get the string value; note that the dict object OWNS the string memory
const char *stringValue = Tcl_GetString(dict);
// and once you don't need stringValue or dict any more
Tcl_DecrRefCount(dict);
否则,如果您可以形成一个包含偶数个元素的 Tcl 列表,那么它将被解释为 table 字典(字符串表示是故意重合的)。假设您不想使用基于 Tcl_Obj
的操作,还有 the low level dynamic strings(较旧的 API 在内部使用得相当多,但现在不特别推荐):
Tcl_DString buffer;
Tcl_DStringInit(&buffer);
Tcl_DStringAppendElement(&buffer, key1);
Tcl_DStringAppendElement(&buffer, value1);
// ...
const char *stringValue = Tcl_DStringValue(&buffer);
// and once you're done with everything
Tcl_DStringFree(&buffer);
在您询问之前,与 Tcl_Obj
一样,Tcl_DString
拥有与 stringValue
关联的内存。如果您希望它在释放缓冲区后仍然存在,则需要复制一份。 (请注意,Tcl_Obj
API 可能更有效,但实际上并非如此,因为您最终所做的只是从中构建一个字符串。)
如果您想自己管理内存分配,可以使用 absolute base level API. In particular, Tcl_ScanElement
will let your code work out how to format a particular element string efficiently (it returns an estimate of the space required and, via an OUT parameter, the instructions on how to do the formatting) and Tcl_ConvertElement
will do the formatting into the buffer you have prepared. Their use is a bit fiddly, so I'll just link to how Tcl itself uses them(这是 Tcl 列表对象实现的一部分)。
如果您根本没有可用的 Tcl C API,请知道您要生成一系列以空格分隔的单词。对于简单的单词(例如,只有字母数字或最基本的标点符号),您可以直接输入单词。对于任何更复杂的东西(即,如果它包含像 [
、$
、\
或任何空格这样的 Tcl 元字符),您需要将它们括在 {
大括号 }
或在违规字符前加反斜杠。在 大多数 情况下,将大括号放在周围是有效的(它失败的主要原因是不平衡的大括号;还有其他一些)。在 所有 情况下都可以使用反斜杠,但很难看;这种东西代码很容易生成,但阅读和调试起来确实可怕,尤其是嵌套列表。
这些是列表的规则。字典在格式上等同于包含偶数项的列表。字典的规范性有两个要求:分隔单词的空格应该是单个空格(这是规范的列表形式),并且字典的键(第一、第三、第五……元素)应该是唯一的。非规范词典可以工作,并且定义精确(首选出现 last 键),但当您不仔细考虑时,偶尔可能会感到惊讶。 Tcl 自己的字典代码在写入字典时总是规范化字典(因为内部模型是散列 table;您的 C 代码 不需要 需要构建它)。