форматирование строки в стиле printf

9

Вызов

Напишите функцию, которая реализует printfформатирование строки в стиле C.

правила

  1. Вы должны реализовать , по крайней мере %%, %c, %s, %dи %f.
  2. Вы не должны использовать встроенный метод форматирования строки.
  3. Вы не должны запускать внешние программы или подключаться к Интернету из вашей программы.
  4. Вам решать, как обрабатывать неверный ввод, но ваша программа не должна завершаться ненормально.
  5. Вы должны написать переменную функцию, если это возможно.

Ключевые слова «ДОЛЖЕН», «НЕ ДОЛЖЕН», «ТРЕБУЕТСЯ», «ДОЛЖЕН», «НЕ ДОЛЖЕН», «СЛЕДУЕТ», «НЕ ДОЛЖЕН», «РЕКОМЕНДУЕТСЯ», «МОЖЕТ» и «ДОПОЛНИТЕЛЬНО» в этом документе интерпретироваться как описано в RFC 2119 .

nyuszika7h
источник
Что делает %c? Довольно уверен %s, %dи %fдля строк, целых и плавающих соответственно, но не уверен %c.
Sumurai8
%cотображает значение ASCII переданного int IIRC
marinus
Он печатает символ, поэтому 97и 'a'стал бы aна выходе.
nyuszika7h
нет необходимости поддерживать какую-то форму, как %-02dправильно? только три% c,% s,% d?
ВЫ
@YOU Правильно. Достаточно.
nyuszika7h

Ответы:

4

APL (73)

{⊃,/,⌿↑(⊂2∘↓¨Z⊂G),⊂{'c'0≡⍵,∊⊃⍺:⎕UCS⍺⋄⍕⍺}/⍵,⍪⌷∘G¨1↓1+(Z←G='%')/⍳⍴G←'%!',⍺}

Некоторые тесты:

      'a:%c b:%s c:%d'{⊃,/,⌿↑(⊂2∘↓¨Z⊂G),⊂{'c'0≡⍵,∊⊃⍺:⎕UCS⍺⋄⍕⍺}/⍵,⍪⌷∘G¨1↓1+(Z←G='%')/⍳⍴G←'%!',⍺} 65 'foo' 67
a:A b:foo c:67 

      printf←{⊃,/,⌿↑(⊂2∘↓¨Z⊂G),⊂{'c'0≡⍵,∊⊃⍺:⎕UCS⍺⋄⍕⍺}/⍵,⍪⌷∘G¨1↓1+(Z←G='%')/⍳⍴G←'%!',⍺}
      '1:%s 2:%s 3:%d 4:%c 5:%c' printf 'foo' 'bar' 100 110 'z'
1:foo 2:bar 3:100 4:n 5:z   
      'The %s brown %c%c%c jumps over the %s dog.' printf 'quick' 102 111 'x' 'lazy'
The quick brown fox jumps over the lazy dog.

Объяснение:

  • G←'%!',⍺: префикс фиктивного спецификатора к строке (для упрощения обработки)
  • (Z←G='%')/⍳⍴G: найти индексы всех %символов в строке; также хранить битовую маску вZ
  • ⌷∘G¨1↓1+: выберите все символы рядом с %s и бросьте манекен.
  • ⍵,⍪: сопоставить каждый спецификатор с его значением из правильного аргумента.
  • {... }/: запустить следующую функцию для каждой пары:
    • 'c'0≡⍵,∊⊃⍺: если аргумент является числом, а спецификатор c:
    • :⎕UCS⍺: затем вернуть значение аргумента в юникоде,
    • ⋄⍕⍺: в противном случае возвращает строковое представление аргумента.
  • : приложить
  • ⊂2∘↓¨Z⊂G: разбить строку на %s, а затем удалить первые два символа каждой подстроки (это то место, где фигурирует манекен), и заключить результат этого.
  • : сделать матрицу из двух вложенных массивов, сопоставляя каждую подстроку со значением, которое должно следовать за ней.
  • ,⌿: объединить каждую подстроку с ее значением.
  • ⊃,/: затем присоедините получившиеся строки.
Мэринус
источник
Всегда приятно видеть эзотерические языки, которые выглядят как бред. ;)
nyuszika7h
2
@ nyuszika7h: На самом деле это серьезный язык. Он датируется 1960-ми годами и все еще используется. Это было бы немного менее похоже на тарабарщину, если бы не игра в гольф.
Маринус
Понятно, интересно.
nyuszika7h
@ nyuszika7h: Ну, технически это язык программирования, ориентированный на списки, так что вы можете сказать, что он разработан для гольф-кода, особенно учитывая, что он использует специальный набор символов, предназначенный для того, чтобы сделать программы более читабельными и менее многословными. И это было вдохновением для языка программирования J и GolfScript.
Конрад Боровски
@xfix Я думал, что LISP был ориентированным на список языком программирования? Мы использовали APL в университете для реальной работы - возможность работать с массивами изначально очень удобна. J был разработан одним из изобретателей APL как его «преемник» - конечно, это не значит, что он бесполезен для гольф-кода…
Джерри Иеремия
2

Рубин: 102 персонажа

f=->s,*a{s.gsub(/%(.)/){$1==?%??%:a.shift.send({?c=>:chr,?s=>:to_s,?d=>:to_i,?f=>:to_f}[$1])rescue$&}}

Образец прогона:

irb(main):001:0> f=->s,*a{s.gsub(/%(.)/){$1==?%??%:a.shift.send({?c=>:chr,?s=>:to_s,?d=>:to_i,?f=>:to_f}[$1])rescue$&}}
=> #<Proc:0x96634ac@(irb):1 (lambda)>

irb(main):002:0> puts f["percent : %%\n   char : %c or %c\n string : %s or %s or %s\ndecimal : %d or %d or %d\n  float : %f or %f or %f\ninvalid : %x or %s or %d or %f", 65, 'B', 'format me', 42, Math::PI, 42, Math::PI, '2014', 42, Math::PI, '2014', 'more']
percent : %
   char : A or B
 string : format me or 42 or 3.141592653589793
decimal : 42 or 3 or 2014
  float : 42.0 or 3.141592653589793 or 2014.0
invalid : %x or  or 0 or 0.0
=> nil

Неверные спецификаторы формата остаются на месте. Спецификаторы формата без значения аргумента заменяются пустым значением данного типа.

manatwork
источник
Вы можете предоставить анонимную функцию, так что оставьте ведущуюf
кошка
Верно. Но, насколько я помню, на момент публикации анонимные функции не были приняты единогласно. Пока что ни ответ Lua не был обновлен до анонимной функции (чтобы сохранить то же количество символов), я думаю, что я не буду запускать кампанию по обновлению.
Манатворк
2

Lua 5.2, 115 байт

-- Function definition, 115 chars
function f(f,...)n,t=0,{...}return(f:gsub('%%(%a)',function(s)n=n+1return(({c=s.char})[s]or tostring)(t[n])end))end

-- Usage example
print(f('Happy %cew %d %s %f',78,2014,'Year!',math.pi))
-- Output: Happy New 2014 Year! 3.1415926535898
Егор Скриптунов
источник
Хороший. Какая версия Lua? 5.1.5 дает «искаженное число около« 1 возврат »». Небольшая проблема с «% c», он терпит неудачу на «N» вместо 78. Или это также просто особенность моего старого Lua?
manatwork
@manatwork - Попробуй здесь
Егор Скриптунов
Да, там работает.
manatwork
У меня работает на Lua 5.2.3.
nyuszika7h
1

C ++ (281 символ)

#include<sstream>
#include<cstdarg>
#define q(x)va_arg(v,x);break;case
std::string p(char*f,...){std::ostringstream r;va_list v;va_start(v,f);while(*f)if(*f=='%')switch(++f,*f++){case's':r<<q(char*)'d':r<<q(int)'c':r<<(char)q(int)'%':r<<'%';}else r<<*f++;va_end(v);return r.str();}

Я ненавижу C ++, но мне показалось, что это хороший выбор (я действительно выбрал бы C, если бы этот char*указатель не потребовал слишком много усилий, чтобы быть действительно полезным). Принимает char*аргументы и std::stringрезультат, но, эй, это C ++, так кого волнует согласованность (на языке, который сам не согласован)?

Конрад Боровски
источник
Это не компилируется, так как у него нет основной функции.
nyuszika7h
@ nyuszika7h: Вопрос был о создании функции, а не main. Но если вам нужен пример main, попробуйте gist.github.com/xfix/8238576 (я использовал его при тестировании этой функции).
Конрад Боровски
Правда, вы не можете сделать значимую mainфункцию, добавив одну, вы просто увеличите количество символов. Если я не хочу изменять код, я могу добавить сопровождающий заголовочный файл и #includeего из моей тестовой программы.
nyuszika7h
1

Java , 201 186 174 байта

12 байтов благодаря Кевину Круйссену

String f(String s,Object...a){String r="";for(char c,i=0,j=0;i<s.length();r+=c==37?(c=s.charAt(i++))<38?c:c==99?(char)(int)a[j++]:a[j++]:c==37?"":c)c=s.charAt(i++);return r;}

Попробуйте онлайн!

Дрянная Монахиня
источник
Я не совсем уверен, но я думаю, что вы можете удалить =s.charAt(0)из char c=s.charAt(0). Это все еще работает в TIO, когда я так делаю.
Кевин Круйссен
@KevinCruijssen Клянусь, это довольно умно.
Утренняя монахиня
Я знаю, что прошло какое-то время, но вы можете сэкономить еще 8 байтов, печатая напрямую: void f(String s,Object...a){for(char c,i=0,j=0;i<s.length();System.out.print(c==37?(c=s.charAt(i++))<38?c:c==99?(char)(int)a[j++]:a[j++]:c==37?"":c))c=s.charAt(i++);} 166 байтов (и еще больше, конвертируя в Java 8, но это не ваше дело, не так ли?)
Кевин Круйссен,