Что означает% d в struct.pack? - PullRequest
       4

Что означает% d в struct.pack?

2 голосов
/ 18 августа 2010

Я читал хотя бы библиотеку кода Python, и я озадачен этим утверждением:

struct.pack( "<ii%ds"%len(value), ParameterTypes.String, len(value), value.encode("UTF8") )

Я все понимаю, кроме %d, и я не уверен, почему длина value упаковывается дважды.

Насколько я понимаю, структура будет иметь кодирование с прямым порядком байтов (<) и будет содержать два целых числа (ii), за которыми следует% d, за которым следует строка(s).

Какое значение имеет %d?

Ответы [ 5 ]

2 голосов
/ 18 августа 2010

Aarrrgh уму непостижимо ....

@S.Lott: "" "Я не думаю, что число особенно важно, так как Python будет иметь тенденцию правильно упаковываться без него." "" -1 . Не думай; исследовать. Без числа означает просто, что число по умолчанию равно 1. Имеет тенденцию упаковывать правильно ??? Возможно, вы думаете, что struct.pack("s", foo) работает так же, как "%s" % foo? Это не так; docs say "" " Для символа формата 's' число интерпретируется как размер строки, а не число повторений, как для других символов формата, например, 10s означает одну 10-байтовую строку, в то время как '10c' означает 10 символов. Для упаковки строка усекается или дополняется нулевыми байтами, в зависимости от ситуации."" "

@ Брендан: -1 . value не является массивом (что бы это ни было); очевидно, что она явно должна быть строкой в ​​юникоде ... вот здесь: value.encode("UTF8")

@ Мэтт Эллен: Строка кода, которую вы цитируете, сильно нарушена. Если в value есть какие-либо не-ASCII символы, данные будут потеряны.

Давайте разберемся:

`struct.pack("<ii%ds"%len(value), ParameterTypes.String, len(value), value.encode("UTF8"))`  

Уменьшите проблемное пространство, удалив первый элемент

struct.pack("<i%ds"%len(value), len(value), value.encode("UTF8"))

Теперь давайте предположим, что value равно u'\xff\xff', поэтому len(value) равно 2.

Пусть v8 = value.encode('UTF8'), т.е. '\xc3\xbf\xc3\xbf'.

Обратите внимание, что len(v8) равно 4. Пенни уже понизилась?

Итак, теперь у нас есть

struct.pack("<i2s", 2, v8)

Число 2 упаковано как 4 байта, 02 00 00 00. 4-байтовая строка v8 обрезается (длиной 2 в «2s») до длины два. ПОТЕРИ ДАННЫХ. СБОЙ.

Правильный способ сделать то, что, по-видимому, требуется:

v8 = value.encode('UTF8')
struct.pack("<ii%ds" % len(v8), ParameterTypes.String, len(v8), v8)
1 голос
/ 18 августа 2010

Это обычный формат строки , который используется для создания формата структуры

Попробуйте прочитать его для начала как обычную строку (на данный момент забудьте struct)...

"<ii%ds" % len(value)

Если, например, длина итерируемого значения равна 4, тогда строка будет <ii4s.Затем он передается в struct.pack, готовый для упаковки двух целых чисел, за которыми следует строка длиной четыре байта из итерируемой value

0 голосов
/ 18 августа 2010

Значение %d в том, что это параметр форматирования для строк:
Операции форматирования строки

Когда разбит на части, "<ii%ds" % len(value) немного легче понять. Он заменяет индикатор преобразования% d в строке на возвращаемое значение len(value), приведенное соответственно.

>>> str = "<ii%ds"
>>> str % 5
'<ii5s'
>>> str % 3
'<ii3s'
0 голосов
/ 18 августа 2010

Используется для указания того, что строка (value) из len(value) символов должна быть упакована после этих двух целых чисел.

Если, например, value содержит "boo", тогда фактический спецификатор формата для pack будет "<ii3s".

0 голосов
/ 18 августа 2010

%d означает, что это работает в два этапа.

Шаг 1.

"<ii%ds"%len(value) 

Создает строку форматирования структуры "<ii...some number...s".

Шаг 2.

Полученная строка форматирования применяется к трем значениям

ParameterTypes.String, len(value), value.encode("UTF8")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...