Почему не были новыми (разрядная конкретная ширина) printf (), параметр формата представляет adoped в виде строки как часть C99?

В Bash, пуленепробиваемый способ, который будет работать, даже если ваша переменная содержит символы новой строки:

IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")

Посмотрите:

$ in= 

Хитрость для этого заключается в использовании опция -d для read (разделитель) с пустым разделителем, так что read вынужден читать все, что ему дано. И мы наполняем read точно содержимым переменной in, без завершающей строки, благодаря printf. Обратите внимание, что мы также помещаем разделитель в printf, чтобы строка, переданная в read, имела конечный разделитель. Без этого read обрезал бы потенциальные конечные пустые поля:

$ in='one;two;three;'    # there's an empty field
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two" [2]="three" [3]="")'

сохраняется конечное пустое поле.


Обновление для Bash≥4.4

Начиная с Bash 4.4, встроенный модуль mapfile (он же readarray) поддерживает опцию -d для указания разделителя. Отсюда другой канонический путь:

mapfile -d ';' -t array < <(printf '%s;' "$in")
one;two three;*;there is\na newline\nin this field' $ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in") $ declare -p array declare -a array='([0]="one" [1]="two three" [2]="*" [3]="there is a newline in this field")'

Хитрость для этого заключается в использовании опция -d для read (разделитель) с пустым разделителем, так что read вынужден читать все, что ему дано. И мы наполняем read точно содержимым переменной in, без завершающей строки, благодаря printf. Обратите внимание, что мы также помещаем разделитель в printf, чтобы строка, переданная в read, имела конечный разделитель. Без этого read обрезал бы потенциальные конечные пустые поля:

$ in='one;two;three;'    # there's an empty field
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two" [2]="three" [3]="")'

сохраняется конечное пустое поле.


Обновление для Bash≥4.4

Начиная с Bash 4.4, встроенный модуль mapfile (он же readarray) поддерживает опцию -d для указания разделителя. Отсюда другой канонический путь:

mapfile -d ';' -t array < <(printf '%s;' "$in")
17
задан hippietrail 6 April 2011 в 13:17
поделиться

3 ответа

Обоснование C, кажется, подразумевает, что стандартизирует существующую практику:

был получен из заголовок с таким же названием встречается в нескольких существующих 64-битных системах.

но в остальной части текста не говорится об этих макросах, и я не помню, чтобы они существовали в то время.

Что Следующее - просто предположение, но основанное на опыте работы комитетов по стандартизации.

Одним из преимуществ макросов C99 перед стандартизацией дополнительных спецификаторов формата для printf (обратите внимание, что C99 также добавил некоторые из них) является то, что они предоставляют и , когда у вас уже есть реализация, поддерживающая требуемые функции специфическим для реализации способом, это просто запись двух файлов с адекватным typedef и макросами. Это снижает затраты на приведение существующей реализации в соответствие, снижает риск нарушения существующих программ, в которых используются особенности существующих особенностей реализации (стандартный способ не мешает), и облегчает перенос совместимых программ в реализацию, у которых их нет. заголовки (они могут быть предоставлены программой). Кроме того, если конкретные способы реализации уже варьировались в то время, это не

16
ответ дан 30 November 2019 в 12:51
поделиться

Correct, this is how the C99 standard says you should use them. If you want truly portablt code that is 100% standards-conformant to the letter, you should always print an int using "%d" and an int32_t using "%"PRId32.

Most people won't bother, though, since there are very few cases where failure to do so would matter. Unless you're porting your code to Win16 or DOS, you can assume that sizeof(int32_t) <= sizeof(int), so it's harmless to accidentally printf an int32_t as an int. Likewise, a long long is pretty much universally 64 bits (although it is not guaranteed to be so), so printing an int64_t as a long long (e.g. with a %llx specifier) is safe as well.

The types int_fast32_t, int_least32_t, et al are hardly ever used, so you can imagine that their corresponding format specifiers are used even more rarely.

8
ответ дан 30 November 2019 в 12:51
поделиться

Я могу только догадываться, почему. Мне нравится ответ AProgrammer выше, но упускается один аспект: что вы собираетесь добавить в printf в качестве модификатора формата? Уже существует два различных способа использования чисел в строке формата printf (ширина и точность). Было бы неплохо добавить третий вид числа, чтобы сказать, сколько бит точности в аргументе, но где вы собираетесь его поставить, чтобы не запутать людей? К сожалению, одним из недостатков C является то, что printf не предназначен для расширения.

Макросы ужасны, но когда вам нужно написать код, переносимый на 32-битные и 64-битные платформы, они просто находка. Определенно спас мой бекон.

Я думаю, что ответ на ваш вопрос почему либо

  • Никто не мог придумать лучшего способа сделать это, либо
  • Комитет по стандартам не смог прийти к согласию. все, что они чувствовали, было явно лучше.
1
ответ дан 30 November 2019 в 12:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: