printf tarzı dize biçimlendirme


9

Meydan okuma

C printfstili dize biçimlendirmesi uygulayan bir işlev yazın .

kurallar

  1. Sen gerekir uygulamak en azından %%, %c, %s, %dve %f.
  2. Sen olmamalıdır yerleşik bir dize biçimlendirme yöntemi kullanın.
  3. Sen olmamalıdır harici programları çalıştırmak veya programdan internete bağlanın.
  4. Bu geçersiz giriş nasıl işleneceğine karar vermek size kalmış, ama programınız olmamalıdır anormal sonlandırmak.
  5. Sen gerektiğini bir yazma variadic fonksiyonunu mümkünse.

Bu belgede "ZORUNLU", "ZORUNLU DEĞİL", "GEREKLİ", "SHALL", "SHALL NOT", "SHOULD", "NOT ÖNERİLMELİ", "ÖNERİLEN", "MAYIS" ve "İSTEĞE BAĞLI" anahtar kelimeleri RFC 2119'da açıklandığı gibi yorumlanmalıdır .


Ne yapar %c? Oldukça emin %s, %dve %fdizeleri, ints ve yüzen respectivelly ama emin about içindir %c.
Sumurai8

%caktarılan int IIRC'nin ASCII değerini gösterir
marinus

Bu karakter yazdırır, böylece 97ve 'a'hem olacaktı açıkışına.
nyuszika7h

gibi bir formu desteklemeye gerek yok %-02ddeğil mi? sadece% 3 c,% s,% d?
SİZ

@Doğrusun. Bu yeterli.
nyuszika7h

Yanıtlar:


4

APL (73)

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

Bazı testler:

      '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.

Açıklama:

  • G←'%!',⍺: dizeye kukla bir tanımlayıcı öneki (daha kolay işlem için)
  • (Z←G='%')/⍳⍴G: %dizgedeki tüm karakterlerin indekslerini bulur ; ayrıca bir bitmask saklayınZ
  • ⌷∘G¨1↓1+: %s'nin yanındaki tüm karakterleri seçin ve kukla bırakın.
  • ⍵,⍪: her belirteci doğru argümandaki değeriyle eşleştirin.
  • {... }/: her bir çiftte aşağıdaki işlevi çalıştırın:
    • 'c'0≡⍵,∊⊃⍺: bağımsız değişken bir sayı ve belirleyici ise c:
    • :⎕UCS⍺: sonra argümanın unicode değerini döndürür,
    • ⋄⍕⍺: aksi takdirde, bağımsız değişkenin dize olarak temsil edilen halini döndürür.
  • : içine al
  • ⊂2∘↓¨Z⊂G: dizeyi %s üzerine bölün ve ardından her bir alt dizenin ilk iki karakterini kaldırın (bu, kukla devreye girer) ve bunun sonucunu da ekleyin.
  • : her bir alt dizeyi izlemesi gereken değerle eşleştirerek, iki kapalı diziden bir matris oluşturun.
  • ,⌿: her bir alt dizeyi değeriyle birleştirin.
  • ⊃,/: sonra elde edilen dizelere katılın.

Anlamsız görünen ezoterik dilleri görmek her zaman eğlencelidir. ;)
nyuszika7h

2
@ nyuszika7h: Bu aslında ciddi bir dildir. 1960'lı yıllardan kalmadır ve hala kullanılmaktadır. Golf olmasaydı biraz daha az anlamsız görünüyordu.
Marinus

Anlıyorum, ilginç.
nyuszika7h

@ nyuszika7h: Teknik olarak liste odaklı programlama dili, bu yüzden özellikle programları daha okunaklı ve daha az ayrıntılı hale getirmek için özel bir karakter seti kullandığını düşünerek kod golf için tasarlandığını söyleyebilirsiniz. Ve J programlama dili ve GolfScript için bir ilham kaynağı oldu .
Konrad Borowski

@xfix LISP'nin listeye yönelik programlama dili olduğunu düşündüm? APL'yi üniversitede gerçek iş için kullandık - dizileri yerel olarak işleyebilmek gerçekten kullanışlı. J, APL'nin icatçılarından biri tarafından "halefi" olarak tasarlandı - elbette bu, kod golfü için yararlı olmadığı anlamına gelmiyor ...
Jerry Jeremiah

2

Ruby: 102 karakter

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

Örnek çalışma:

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

Geçersiz biçim belirticileri yerinde tutulur. Bağımsız değişken değeri olmayan biçim belirleyicileri, belirtilen türün boş değeri ile değiştirilir.


Anonim bir işlev sağlayabilirsiniz, bu yüzden öndef
kedi

Aslında. Ancak hatırladığım gibi, bunu gönderirken anonim işlevler oybirliğiyle kabul edilmedi. Lua yanıtı anonim bir işleve güncellenmedi (aynı miktarda karakteri kaydetmek için), sanırım güncelleme kampanyasını başlatmayacağım.
manatwork

2

Lua 5.2, 115 bayt

-- 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

Güzel bir. Hangi Lua sürümü? 5.1.5 “1return” yakınında hatalı biçimlendirilmiş sayı verir. “% C” ile ilgili küçük bir sorun, 78 yerine 'N'de başarısız oluyor. Yoksa sadece eski Lua'mın özelliği de mi?
manatwork

@manatwork - Burada
Egor Skriptunoff

Yepp, orada çalışıyor.
manatwork

Benim için Lua 5.2.3 üzerinde çalışıyor.
nyuszika7h

1

C ++ (281 karakter)

#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 ++ nefret ediyorum, ama iyi bir seçim gibi görünüyordu (gerçekten char*işaretçi gerçekten yararlı olmak için çok fazla çaba gerektiriyorsa , gerçekten C ile gitmek istiyorum ). Alır char*argümanları ve std::string++, bu yüzden kim (kendisi tutarlı değil o dilde) tutarlılık umurunda C olduğunu hey sonucunu ama?


Ana işlevi olmadığı için bu derlenmez.
nyuszika7h

@ nyuszika7h: Soru bir işlev yapmakla ilgiliydi, değil main. Ancak örneğe ihtiyacınız varsa main, gist.github.com/xfix/8238576 (bu işlevi test ederken bunu kullandım) deneyin .
Konrad Borowski

Doğru, gerçekten anlamlı bir mainişlev yapamazsınız, bir tane eklemek sadece karakter sayısını artıracaktır. Kodu değiştirmek istemiyorsam, eşlik eden bir başlık dosyası ekleyebilirim ve #includetest programımdan.
nyuszika7h

1

Java , 201 186 174 bayt

Kevin Cruijssen'e 12 bayt teşekkürler

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;}

Çevrimiçi deneyin!


Tam olarak emin değilim, ama kaldırmak düşünüyorum =s.charAt(0)dan char c=s.charAt(0). Bunu yaptığımda hala TIO'da çalışıyor.
Kevin Cruijssen

@KevinCruijssen Yemin ederim ki bu oldukça zekice.
Leaky Nun

Bir süre geçtiğini biliyorum, ancak doğrudan yazdırarak 8 bayt daha kaydedebilirsiniz: 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 bayt (ve Java 8'e dönüştürerek biraz daha, ama bu gerçekten bir şey değil, değil mi?)
Kevin Cruijssen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.