formatação de string no estilo printf


9

Desafio

Escreva uma função que implemente a printfformatação de string no estilo C.

Regras

  1. Você deve implementar pelo menos %%, %c, %s, %de %f.
  2. Você não deve usar um método de formatação de string interno.
  3. Você não deve executar programas externos ou conectar-se à Internet a partir do seu programa.
  4. Cabe a você decidir como lidar com entradas inválidas, mas seu programa não deve terminar de forma anormal.
  5. Você deve escrever uma função variável, se possível.

As palavras-chave "DEVEM", "NÃO DEVEM", "NECESSÁRIO", "DEVEM", "NÃO DEVEM", "DEVEM", "NÃO DEVEM", "RECOMENDADO", "PODE" e "OPCIONAL" neste documento são para ser interpretado como descrito na RFC 2119 .


O que %cfaz? Certamente %s, %de %fsão para strings, ints e floats respectivamente, mas não tenho certeza %c.
precisa saber é o seguinte

%cexibe o valor ASCII de um passado-in int IIRC
marinus

Ele imprime o caractere, portanto, 97e 'a'ambos ficam ana saída.
precisa saber é o seguinte

não há necessidade de apoiar alguma forma como %-02dcerto? apenas esses três% c,% s,% d?
VOCÊ

@YOU Correto. É o bastante.
precisa saber é o seguinte

Respostas:


4

APL (73)

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

Alguns testes:

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

Explicação:

  • G←'%!',⍺: prefixa um especificador fictício à string (para facilitar o processamento)
  • (Z←G='%')/⍳⍴G: encontre os índices de todos os %caracteres na string; Também armazene uma máscara de bit emZ
  • ⌷∘G¨1↓1+: selecione todos os caracteres ao lado de se %solte o manequim.
  • ⍵,⍪: combine cada especificador com seu valor no argumento correto.
  • {... }/: execute a seguinte função em cada par:
    • 'c'0≡⍵,∊⊃⍺: se o argumento for um número e o especificador for c:
    • :⎕UCS⍺: retorne o valor unicode do argumento,
    • ⋄⍕⍺: caso contrário, retorne a representação em cadeia do argumento.
  • : delimitar
  • ⊂2∘↓¨Z⊂G: divida a sequência nos se, em %seguida, remova os dois primeiros caracteres de cada substring (é aqui que o manequim entra) e inclua o resultado disso.
  • : crie uma matriz com as duas matrizes incluídas, correspondendo cada substring com o valor que deve segui-lo.
  • ,⌿: junte cada substring com seu valor.
  • ⊃,/: em seguida, junte as strings resultantes.

É sempre divertido ver idiomas esotéricos que parecem bobos. ;)
nyuszika7h

2
@ nyuszika7h: Esta é realmente uma linguagem séria. Data da década de 1960 e ainda está em uso. Seria um pouco menos sem sentido se não fosse jogado.
marinus

Entendo, interessante.
usar o seguinte código

@ nyuszika7h: Bem, tecnicamente, é uma linguagem de programação orientada a lista, então você poderia dizer que foi projetada para o código de golfe, especialmente considerando que usa um conjunto de caracteres especiais para tornar os programas mais legíveis e menos detalhados. E foi uma inspiração para a linguagem de programação J e o GolfScript.
precisa saber é o seguinte

@xfix Eu pensei que LISP era a linguagem de programação orientada a lista? Usamos o APL na universidade para um trabalho real - ser capaz de lidar com matrizes nativamente é realmente útil. J foi desenhado por um dos inventores do APL como seu "sucessor" - é claro que isso não significa que não é útil para o golfe código ...
Jerry Jeremias

2

Ruby: 102 caracteres

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

Exemplo de execução:

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

Especificadores de formato inválidos são mantidos no lugar. Especificadores de formato sem valor de argumento são substituídos pelo valor vazio do tipo especificado.


Você pode fornecer uma função anônima, então largue o líderf
cat

De fato. Mas, como me lembro, no momento da publicação, as funções anônimas não eram aceitas por unanimidade. Por enquanto, nem a resposta de Lua foi atualizada para a função anônima (para salvar a mesma quantidade de caracteres), acho que não vou iniciar a campanha de atualização.
Manatwork 21/03

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

Agradável. Qual versão do Lua? 5.1.5 fornece "número incorreto próximo a '1retorno'". Pequeno problema com "% c", falha em 'N' em vez de 78. Ou também é apenas a peculiaridade de minha antiga Lua?
manatwork

@manatwork - Tente aqui
Egor Skriptunoff

Sim, trabalha lá.
2010 '13

Funciona para mim no Lua 5.2.3.
precisa saber é o seguinte

1

C ++ (281 caracteres)

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

Eu odeio C ++, mas parecia uma boa escolha (eu realmente escolheria C, senão esse char*ponteiro exige muito esforço para ser realmente útil). Recebe char*argumentos e std::stringresulta, mas ei, isso é C ++, então quem se importa com consistência (em uma linguagem que não é consistente)?


Isso não compila, pois não tem uma função principal.
precisa saber é o seguinte

@ nyuszika7h: A questão era sobre criar uma função, não main. Mas se você precisar de amostra main, tente gist.github.com/xfix/8238576 (usei esse enquanto testava essa função).
precisa saber é o seguinte

É verdade que você não pode realmente fazer uma mainfunção significativa , adicionar uma apenas aumentaria a contagem de caracteres. Se não quisesse modificar o código, poderia adicionar um arquivo de cabeçalho que o acompanha e #includea partir do meu programa de teste.
precisa saber é o seguinte

1

Java , 201 186 174 bytes

12 bytes graças a 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;}

Experimente online!


Eu não estou totalmente certo, mas acho que você pode remover =s.charAt(0)a partir char c=s.charAt(0). Ainda funciona no TIO quando faço isso.
Kevin Cruijssen

@KevinCruijssen Eu juro que é bastante inteligente.
Leaky Nun

Eu sei que tem sido um tempo, mas você pode economizar mais 8 bytes imprimindo directamente: 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 (e um pouco mais através da conversão para Java 8, mas isso não é realmente sua coisa, não é?)
Kevin Cruijssen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.