Как сформировать словарь TCL в виде строки, чтобы передать его как строковую переменную? - PullRequest
2 голосов
/ 25 марта 2020

Мне нужно отформатировать строку, которая может быть интерпретирована как словарь TCL. В основном строка формируется в C ++, затем передается как значение строковой переменной в интерпретатор TCL, и интерпретатор TCL должен иметь возможность обрабатывать это строковое значение как словарь. Возможно ли это, и если да, то как отформатировать эту строку?

Ответы [ 2 ]

2 голосов
/ 25 марта 2020

Любая строка с четным числом слов (как определено в 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
1 голос
/ 26 марта 2020

Если у вас есть доступ к C API Tcl, используйте операции dict (вместе с другими соответствующими). ​​

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 с четным числом элементов, то это будет интерпретироваться как словарь (строковые представления намеренно совпадают). Предполагая, что вы не хотите использовать операции Tcl_Obj, есть также низкоуровневые динамические c строки (более старый 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. Вам нужно будет взять копию, если вы хотите, чтобы она сохранялась после освобождения буфера. (Обратите внимание, что API Tcl_Obj потенциально более эффективен, за исключением того, что на самом деле все, что вы в конечном итоге делаете, это строит из него строку.)

Если вы хотите сами управлять распределением памяти есть абсолютный базовый уровень API 1019 *. В частности, Tcl_ScanElement позволит вашему коду решить, как эффективно отформатировать определенную строку элемента (он возвращает оценку требуемого пространства и, с помощью параметра OUT, инструкции о том, как выполнить форматирование), а Tcl_ConvertElement выполните форматирование в буфер, который вы подготовили. Их использование немного затруднительно, поэтому я просто сошлюсь на , как сам Tcl использует их (это часть реализации объектов списка Tcl).


Если вы не tcl C API вообще не доступен, знайте, что вы хотите создать последовательность слов, разделенных пробелами. Для простых слов (например, только с буквенно-цифровыми или большинством пунктуации c) вы можете просто вставить слова непосредственно. Для чего-либо более сложного (т. Е. Если оно содержит метасимвол Tcl, такой как [, $, \ или любой другой пробел), вам необходимо либо заключить их в { фигурные скобки }, либо поставить обратную косую черту перед оскорбительные персонажи. Установка скобок работает в большинстве случаев (основной, в которой она не работает, это несбалансированные скобки; есть несколько других). Использование обратной косой черты в работах во всех случаях, но безобразно; это тот тип вещей, который довольно легко генерировать для кода, но на самом деле ужасный для чтения и отладки, особенно с вложенными списками.

Это правила для списки. Словари по формату эквивалентны спискам с четным количеством элементов. Существует два требования к каноничности словарей: пробелы, разделяющие слова, должны быть единичными пробелами (это форма канонического списка), а ключи словаря (первый, третий, пятый ... элементы) должны быть уникальными. Неканонические словари работают и точно определены (предпочтение отдается ключу last ), но могут иногда удивлять, если вы не продумываете внимание. Собственный кодовый словарь Tcl всегда канонизирует словарь, когда записывает в него (потому что внутренняя модель - это таблица ha sh; ваш код C не не требует его построения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...