định dạng chuỗi kiểu printf


9

Thử thách

Viết hàm thực hiện printfđịnh dạng chuỗi kiểu C.

Quy tắc

  1. Bạn phải thực hiện ít nhất %%, %c, %s, %d%f.
  2. Bạn không được sử dụng phương pháp định dạng chuỗi tích hợp.
  3. Bạn không được chạy các chương trình bên ngoài hoặc kết nối với Internet từ chương trình của bạn.
  4. Tùy bạn quyết định cách xử lý dữ liệu nhập không hợp lệ, nhưng chương trình của bạn không được chấm dứt bất thường.
  5. Bạn nên viết một hàm matrixdic nếu có thể.

Các từ khóa "PHẢI", "KHÔNG PHẢI", "BẮT BUỘC", "SALL", "SALL KHÔNG", "NÊN", "KHÔNG NÊN", "KHUYẾN NGHỊ", "CÓ THỂ" và "TÙY CHỌN" trong tài liệu này là được giải thích như được mô tả trong RFC 2119 .


Không gì %clàm gì? Khá chắc chắn %s, %d%flà cho chuỗi, ints và float nổi, nhưng không chắc chắn về %c.
Sumurai8

%chiển thị giá trị ASCII của int IIRC đã qua
mar bến

Nó in ký tự, vì vậy 97'a'cả hai sẽ trở thành ađầu ra.
nyuszika7h

Không cần hỗ trợ một số hình thức như %-02dphải không? chỉ có ba% c,% s,% d?
BẠN

@YOU Đúng. Thế là đủ rồi.
nyuszika7h

Câu trả lời:


4

APL (73)

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

Một số xét nghiệm:

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

Giải trình:

  • G←'%!',⍺: tiền tố một công cụ xác định giả cho chuỗi (để xử lý dễ dàng hơn)
  • (Z←G='%')/⍳⍴G: tìm các chỉ số của tất cả các %ký tự trong chuỗi; cũng lưu trữ một bitmask trongZ
  • ⌷∘G¨1↓1+: chọn tất cả các ký tự bên cạnh %s và thả hình nộm.
  • ⍵,⍪: khớp từng specifier với giá trị của nó từ đối số đúng.
  • {... }/: Chạy chức năng sau trên mỗi cặp:
    • 'c'0≡⍵,∊⊃⍺: nếu đối số là một số và chỉ định là c:
    • :⎕UCS⍺: sau đó trả về giá trị unicode của đối số,
    • ⋄⍕⍺: nếu không, trả về chuỗi đại diện của đối số.
  • : kèm theo
  • ⊂2∘↓¨Z⊂G: tách chuỗi trên %s và sau đó loại bỏ hai ký tự đầu tiên của mỗi chuỗi con (đây là nơi hình nộm xuất hiện) và kèm theo kết quả của điều đó.
  • : tạo một ma trận trong hai mảng kèm theo, khớp với từng chuỗi con với giá trị sẽ theo nó.
  • ,⌿: nối từng chuỗi con với giá trị của nó.
  • ⊃,/: sau đó tham gia chuỗi kết quả.

Thật vui khi thấy các ngôn ngữ bí truyền trông giống như vô nghĩa. ;)
nyuszika7h

2
@ nyuszika7h: Đây thực sự là một ngôn ngữ nghiêm túc. Nó có từ những năm 1960 và nó vẫn còn được sử dụng. Nó sẽ trông hơi giống như vô nghĩa nếu nó không được đánh gôn.
bến tàu

Tôi thấy, thú vị.
nyuszika7h

@ nyuszika7h: Về mặt kỹ thuật, đó là ngôn ngữ lập trình hướng đến danh sách, vì vậy bạn có thể nói nó được thiết kế cho môn đánh gôn, đặc biệt là xem xét nó sử dụng một bộ ký tự đặc biệt nhằm làm cho các chương trình dễ đọc hơn và ít dài dòng hơn. Và đó là một nguồn cảm hứng cho ngôn ngữ lập trình J và GolfScript.
Konrad Borowski

@xfix Tôi nghĩ LISP là ngôn ngữ lập trình định hướng danh sách? Chúng tôi đã sử dụng APL trong trường đại học cho công việc thực tế - có thể xử lý các mảng nguyên bản thực sự tiện dụng. J được thiết kế bởi một trong những nhà phát minh của APL với tư cách là "người kế thừa" của nó - tất nhiên điều đó không có nghĩa là nó không hữu ích cho môn đánh gôn ...
Jerry Jeremiah

2

Ruby: 102 ký tự

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

Chạy mẫu:

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

Định dạng định dạng không hợp lệ được giữ đúng vị trí. Định dạng định dạng không có giá trị đối số được thay thế bằng giá trị trống của loại đã cho.


Bạn có thể cung cấp một chức năng ẩn danh, vì vậy hãy thả f
con mèo

Thật. Nhưng như tôi nhớ, tại thời điểm đăng bài này, các chức năng ẩn danh không được chấp nhận nhất trí. Hiện tại, câu trả lời Lua không được cập nhật thành chức năng ẩn danh (để lưu cùng số lượng ký tự), tôi nghĩ rằng tôi sẽ không bắt đầu chiến dịch cập nhật.
manatwork

2

Lua 5.2, 115 byte

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

Đẹp một. Phiên bản nào của Lua? 5.1.5 cung cấp cho các số không đúng định dạng của Google gần '1return'. Vấn đề nhỏ với %% C, nó thất bại trên 'N' thay vì 78. Hay đó cũng chỉ là đặc thù của Lua cũ của tôi?
manatwork

@manatwork - Thử tại đây
Egor Skriptunoff

Yepp, làm việc ở đó.
thao tác

Làm việc cho tôi trên Lua 5.2.3.
nyuszika7h

1

C ++ (281 ký tự)

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

Tôi ghét C ++, nhưng nó có vẻ là một lựa chọn tốt (tôi thực sự sẽ đi với C, nếu không char*con trỏ đó đòi hỏi quá nhiều nỗ lực để thực sự hữu ích). Đưa ra các char*đối số và std::stringkết quả, nhưng này, đó là C ++, vậy ai quan tâm đến tính nhất quán (theo ngôn ngữ mà bản thân nó không nhất quán)?


Điều này không biên dịch, vì nó không có chức năng chính.
nyuszika7h

@ nyuszika7h: Câu hỏi là về việc tạo ra một chức năng, không phải main. Nhưng nếu bạn cần mẫu main, hãy thử gist.github.com/xfix/8238576 (Tôi đã sử dụng cái đó trong khi kiểm tra chức năng này).
Konrad Borowski

Đúng, bạn thực sự không thể tạo ra một mainchức năng có ý nghĩa , thêm một chức năng sẽ chỉ tăng số lượng ký tự. Nếu tôi không muốn sửa đổi mã, tôi có thể thêm tệp tiêu đề đi kèm và #includenó từ chương trình thử nghiệm của mình.
nyuszika7h

1

Java , 201 186 174 byte

12 byte nhờ 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;}

Hãy thử trực tuyến!


Tôi không hoàn toàn chắc chắn, nhưng tôi nghĩ rằng bạn có thể xóa =s.charAt(0)từ char c=s.charAt(0). Nó vẫn hoạt động trong TIO khi tôi làm như vậy.
Kevin Cruijssen

@KevinCruijssen Tôi thề điều đó khá thông minh.
Rò rỉ Nun

Tôi biết đã được một lúc, nhưng bạn có thể tiết kiệm thêm 8 byte bằng cách in trực tiếp: 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 byte (và một số nữa bằng cách chuyển đổi sang Java 8, nhưng đó không thực sự là điều của bạn, phải không?)
Kevin Cruijssen 16/03/18
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.