Formatierung von Zeichenfolgen im printf-Stil

9

Herausforderung

Schreiben Sie eine Funktion, die die printfFormatierung von C- Zeichenfolgen implementiert .

Regeln

  1. Sie müssen mindestens implementieren %%, %c, %s, %dund %f.
  2. Sie dürfen keine integrierte Formatierungsmethode für Zeichenfolgen verwenden.
  3. Sie dürfen keine externen Programme ausführen oder von Ihrem Programm aus eine Verbindung zum Internet herstellen.
  4. Es liegt an Ihnen, zu entscheiden, wie mit ungültigen Eingaben umgegangen werden soll, aber Ihr Programm darf nicht abnormal beendet werden.
  5. Wenn möglich, sollten Sie eine variable Funktion schreiben .

Die Schlüsselwörter "MUSS", "MUSS NICHT", "ERFORDERLICH", "MUSS", "MUSS NICHT", "SOLLTE", "SOLLTE NICHT", "EMPFOHLEN", "KÖNNEN" und "OPTIONAL" in diesem Dokument lauten zu interpretieren wie in RFC 2119 beschrieben .

nyuszika7h
quelle
Was macht %cdas Ziemlich sicher %s, %dund %fsind für Streicher, Ints und Schwimmer respectivelly, aber nicht sicher %c.
Sumurai8
%czeigt den ASCII - Wert eines übergebenen in int IIRC
marinus
Es druckt das Zeichen, also 97und 'a'beide würden aauf der Ausgabe werden.
Nyuszika7h
Keine Notwendigkeit, irgendeine Form wie %-02drichtig zu unterstützen? nur dass drei% c,% s,% d?
SIE
@Sie korrigieren. Das ist genug.
Nyuszika7h

Antworten:

4

APL (73)

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

Einige Tests:

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

Erläuterung:

  • G←'%!',⍺: Stellen Sie der Zeichenfolge einen Dummy-Bezeichner voran (zur einfacheren Verarbeitung)
  • (Z←G='%')/⍳⍴G: finde die Indizes aller %Zeichen in der Zeichenfolge; Speichern Sie auch eine Bitmaske inZ
  • ⌷∘G¨1↓1+: Wählen Sie alle Zeichen neben dem %s aus und lassen Sie den Dummy fallen.
  • ⍵,⍪: Ordnen Sie jedem Bezeichner seinen Wert aus dem richtigen Argument zu.
  • {... }/: Führen Sie für jedes Paar die folgende Funktion aus:
    • 'c'0≡⍵,∊⊃⍺: Wenn das Argument eine Zahl ist und der Bezeichner lautet c:
    • :⎕UCS⍺: Geben Sie dann den Unicode-Wert des Arguments zurück.
    • ⋄⍕⍺: Andernfalls geben Sie die Zeichenfolgendarstellung des Arguments zurück.
  • : einschließen
  • ⊂2∘↓¨Z⊂G: Teilen Sie die Zeichenfolge auf dem %s und entfernen Sie dann die ersten beiden Zeichen jeder Teilzeichenfolge (hier kommt der Dummy ins Spiel) und fügen Sie das Ergebnis hinzu.
  • : Erstellen Sie aus den beiden eingeschlossenen Arrays eine Matrix, indem Sie jeden Teilstring mit dem Wert abgleichen, der darauf folgen soll.
  • ,⌿: Verbinden Sie jeden Teilstring mit seinem Wert.
  • ⊃,/: Verbinden Sie dann die resultierenden Zeichenfolgen.
Marinus
quelle
Es macht immer Spaß, esoterische Sprachen zu sehen, die wie Kauderwelsch aussehen. ;)
Nyuszika7h
2
@ Nyuszika7h: Dies ist eigentlich eine ernsthafte Sprache. Es stammt aus den 1960er Jahren und ist noch in Gebrauch. Es würde ein bisschen weniger nach Kauderwelsch aussehen, wenn es nicht Golf gespielt würde.
marinus
Ich sehe interessant.
Nyuszika7h
@ nyuszika7h: Nun, technisch gesehen ist es eine listenorientierte Programmiersprache, man könnte also sagen, dass sie für Code-Golf entwickelt wurde, insbesondere wenn man bedenkt, dass ein spezieller Zeichensatz verwendet wird, um Programme lesbarer und weniger ausführlich zu machen. Und es war eine Inspiration für die Programmiersprache J und GolfScript.
Konrad Borowski
@xfix Ich dachte, LISP sei die listenorientierte Programmiersprache? Wir haben APL an der Universität für echte Arbeit verwendet - es ist sehr praktisch, Arrays nativ handhaben zu können. J wurde von einem der Erfinder von APL als "Nachfolger" entworfen - das bedeutet natürlich nicht, dass es für Code-Golf nicht nützlich ist ...
Jerry Jeremiah
2

Ruby: 102 Zeichen

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

Probelauf:

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

Ungültige Formatspezifizierer bleiben erhalten. Formatbezeichner ohne Argumentwert werden durch den leeren Wert des angegebenen Typs ersetzt.

Mann bei der Arbeit
quelle
Sie können eine anonyme Funktion, liefern so fallen die führendef
Katze
Tatsächlich. Aber wie ich mich erinnere, wurden zum Zeitpunkt der Veröffentlichung anonyme Funktionen nicht einstimmig akzeptiert. Da weder die Lua-Antwort auf die anonyme Funktion aktualisiert wurde (um die gleiche Anzahl von Zeichen zu speichern), werde ich die Aktualisierungskampagne wahrscheinlich nicht starten.
Manatwork
2

Lua 5,2, 115 Bytes

-- 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
Egor Skriptunoff
quelle
Schön. Welche Version von Lua? 5.1.5 gibt "fehlerhafte Nummer in der Nähe von '1return'" an. Kleines Problem mit "% c", es schlägt auf "N" statt auf 78 fehl. Oder ist es auch nur die Besonderheit meiner alten Lua?
Manatwork
@ Manatwork - Versuchen Sie es hier
Egor Skriptunoff
Yepp, arbeitet dort.
Manatwork
Funktioniert für mich auf Lua 5.2.3.
Nyuszika7h
1

C ++ (281 Zeichen)

#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();}

Ich hasse C ++, aber es schien eine gute Wahl zu sein (ich würde wirklich mit C gehen, wenn dieser char*Zeiger nicht zu viel Aufwand erfordert, um wirklich nützlich zu sein). Nimmt char*Argumente und std::stringErgebnisse, aber hey, das ist C ++. Wen interessiert also die Konsistenz (in einer Sprache, die selbst nicht konsistent ist)?

Konrad Borowski
quelle
Dies wird nicht kompiliert, da es keine Hauptfunktion hat.
Nyuszika7h
@ nyuszika7h: Die Frage war, eine Funktion zu machen, nicht main. Wenn Sie jedoch ein Beispiel benötigen main, versuchen Sie es mit gist.github.com/xfix/8238576 (ich habe dieses beim Testen dieser Funktion verwendet).
Konrad Borowski
Es stimmt, Sie können keine wirklich sinnvolle mainFunktion erstellen. Wenn Sie eine hinzufügen, erhöht sich nur die Anzahl der Zeichen. Wenn ich den Code nicht ändern wollte, konnte ich eine zugehörige Header-Datei und #includediese aus meinem Testprogramm hinzufügen .
Nyuszika7h
1

Java , 201 186 174 Bytes

12 Bytes dank 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;}

Probieren Sie es online aus!

Undichte Nonne
quelle
Ich bin nicht ganz sicher, aber ich glaube , Sie entfernen =s.charAt(0)aus char c=s.charAt(0). Es funktioniert immer noch im TIO, wenn ich das tue.
Kevin Cruijssen
@ KevinCruijssen Ich schwöre, das ist ziemlich klug.
Undichte Nonne
Ich weiß, es ist eine Weile her, aber Sie können 8 weitere Bytes sparen, indem Sie direkt drucken: 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 Bytes (und einige weitere durch Konvertieren in Java 8, aber das ist nicht wirklich Ihr Ding, oder?)
Kevin Cruijssen