форматування рядків у стилі printf


9

Виклик

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

Правила

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

У цьому документі ключові слова "ОБОВ'ЯЗКОВО", "НЕ ПОВИННІ", "ПОТРІБНО", "ПОТРІБНО", "НЕ ПОТРІБНО", "ПОТРІБНО", "НЕ БУДЕ", "РЕКОМЕНДОВАНО", "МОЖУ" та "ОПЦІЙНО" слід інтерпретувати так, як описано в RFC 2119 .


Що робить %c? Досить впевнені %s, %dі %fдля струн, ints та floats відповідно, але не впевнені %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⍺: потім повертаємо значення аргументу unicode,
    • ⋄⍕⍺: в іншому випадку поверніть рядкове представлення аргументу.
  • : укласти
  • ⊂2∘↓¨Z⊂G: розділіть рядок на %s, а потім видаліть перші два символи кожної підрядки (сюди входить манекен) і додайте результат цього.
  • : складіть матрицю з двох вкладених масивів, узгоджуючи кожну підрядку зі значенням, яке повинно слідувати за нею.
  • ,⌿: приєднати кожну підрядку до її значення.
  • ⊃,/: потім приєднуйтесь до отриманих рядків.

Завжди весело бачити езотеричні мови, схожі на гріш. ;)
nyuszika7h

2
@ nyuszika7h: Це насправді серйозна мова. Він датується 1960 -ми роками і досі використовується. Це було б трохи менше схоже на гнучкості, якби не гольф.
marinus

Бачу, цікаво.
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

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


Ви можете надати анонімну функцію, тому відмовтеся від ведучого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

Хороший. Яка версія Луа? 5.1.5 вказує "неправильне число біля" 1return "". Невелика проблема з "% c", вона не працює на "N" замість 78. Або це також лише особливість моєї старої Луї?
манантська робота

@manatwork - Спробуйте тут
Egor Skriptunoff

Yepp, працює там.
манантська робота

Для мене працює на Луї 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 байт завдяки Kevin Cruijssen

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 клянусь, що це досить розумно.
Leaky Nun

Я знаю, що минув час, але ви можете зберегти ще 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, але це не справді ваше, чи не так?)
Кевін Круїссен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.