Bir Dizeyi Yüzde Kodlama


14

Giriş

Bazılarınızın bildiği gibi, URL'ler aslında özel şeyler yapan karakterlerin bir listesine sahiptir. Örneğin, /karakter URL parçalarını ayırır ve ?, &ve =karakterler sunucuya sorgu parametrelerini geçirmek için kullanılır. Aslında, özel işlevlere sahip karakterlerin bir demet vardır: $&+,/:;=?@. Özel işlevlerin yanı sıra URL'de bu karakterleri başka herhangi bir nedenle kullanmanız gerektiğinde, yüzde kodlama adı verilen bir şey yapmanız gerekir .

Kodlama yüzdesi, bir karakterin onaltılı değerini alıp başına bir %karakteri yerleştirdiğiniz zamandır . Örneğin, karakter ?olarak kodlanır %3Fve karakter &olarak kodlanır %26. Özellikle bir URL'de, bu, ayrıştırma sorunlarına neden olmadan bu karakterleri URL üzerinden veri olarak göndermenizi sağlar. Sizin meydan okuma bir dize almak ve kodlanması gereken tüm karakterlerin yüzde kodlamak olacaktır.

Meydan okuma

Kod noktaları 00-FF (ASCII ve Genişletilmiş ASCII karakterleri) olan karakterlerden oluşan tek bir dize alan bir program veya işlev yazmalısınız. Daha sonra, gerekiyorsa yüzde kodlu her karakterle aynı dizeyi çıktılamanız veya döndürmeniz gerekir. Bu görevi yerine getiren yerleşik öğelere ve standart boşluklara izin verilmez. Referans olarak, yüzde kodlanması gereken her karakterin bir listesi:

  • Kontrol karakterleri (Kod noktaları 00-1F ve 7F)
  • Genişletilmiş ASCII karakterleri (Kod noktaları 80-FF)
  • Ayrılmış karakterler ( $&+,/:;=?@yani kod noktaları 24, 26, 2B, 2C, 2F, 3A, 3B, 3D, 3F, 40)
  • Güvenli olmayan karakterler ( " <>#%{}|\^~[]`ör. Kod noktaları 20, 22, 3C, 3E, 23, 25, 7B, 7D, 7C, 5C, 5E, 7E, 5B, 5D, 60)

İşte aynı liste, ancak ondalık kod noktalarının listesi olarak:

0-31, 32, 34, 35, 36, 37, 38, 43, 44, 47, 58, 59, 60, 62, 61, 63, 64, 91, 92, 93, 94, 96, 123, 124, 125, 126, 127, 128-255

Bu kod golf, bayt (veya onaylı alternatif puanlama yöntemi) en kısa kod kazanır!

Test Durumları

http://codegolf.stackexchange.com/  =>  http%3A%2F%2Fcodegolf.stackexchange.com%2F
[@=>]{#}  =>  %5B%40%3D%3E%5D%7B%23%7D
Test String  =>  Test%20String
ÑÉÐÔ®  =>  %D1%C9%D0%D4%AE
  =>  %0F%16%7F (Control characters 0F, 16, and 7F)
 ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ  =>  %80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF (Extended ASCII characters 80-FF)
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  =>  %20!%22%23%24%25%26'()*%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E

Kontrol karakterlerini gösteren bir test çantanız var mı?
Leaky Nun

@LeakyNun bitti.
GamrCorps

Eminim kod noktası EFsoru işareti içermiyor.
user48538

@ zyabin101 bunu nereden buldun? Görmüyorum.
GamrCorps

"Örneğin
,? Karakteri

Yanıtlar:


2

Pyth, 30 28 26 bayt

L?hx+G+rG1CGbb+\%.HCbsmydz

çevrimiçi dene

açıklama

L?hx+G+rG1CGbb+\%.HCbsmydz
L?hx+G+rG1CGbb+\%.HCb       First part, L defines the function y(b)
 ?hx+G+rG1CGbb+\%.HCb       ? is the ternary operator
  hx+G+rG1CGb               This part will be evaluated
  hx                        x will find the first occurence of a
                            character in a list. If it doesn't
                            find one, it will return -1. hx then
                            equals 0 (or false).
    +G+rG1CG                The list of allowed characters, a
                            concetanation (+) of the alphabet (G),
                            uppercase alphabet (rG1) and numbers
                            (CG, see below for details)
            b               The character to find in the list
             b              True branch of the ternary operator,
                            the character is allowed and returned.
              +\%.HCb       False branch, convert to hex and add %
                     smydz  The actual program
                      mydz  Map every character in the input (z)
                            using the function y on every d
                     s      Join the array, and implicit print.

CGolan bu hüner tüm olası basamak içeren çok sayıda üretir. Bu mükemmel, çünkü bir dizenin diğerinde olup olmadığını kontrol ederken kopyaları umursamıyoruz.


Bu cevap sorudaki spesifikasyonu karşılamıyor. İzin verilenden daha fazla izin verilen karakter var A-Za-z0-9. Örneğin, .çevrilmek yerine korunmalıdır %2E. (cc: @GamrCorps)
DLosc

3

Vim, 67 bayt / tuş vuruşları

:s/\c[^a-z!'()*0-9._-]/\='%'.printf("%02x",char2nr(submatch(0)))/g<cr>

<cr>Örneğin 0x0D, tek bir bayt olan enter tuşunu temsil ettiğine dikkat edin .

Bu oldukça basit bir çözüm. Açıklama:

:s/                                                                    "Search and replace
   \c                                                                  "Case-insensitive
     [^a-z!'()*0-9._-]/                                                "A negative range. Matches any character not alphabetc, numeric or in "!'()*0-9._-"
                       \=                                              "Evaluate
                         '%'                                           "a percent sign string
                            .                                          "Concatenated with
                             printf("%02x",char2nr(submatch(0)))       "The hex value of the character we just matched
                                                                /g     "Make this apply to ever match
                                                                  <cr> "Actually run the command

Bu printf("%02x",char2nr(submatch(0)))çöp korkunç derecede ungolfy .


"Bu printf("%02x",char2nr(submatch(0)))çöp korkunç ungolfy" ve son derece hacky
Leaky Nun

2

Perl, 40 bayt

39 bayt kodu + -p.

Biraz topal, ama bence en kısa çözüm ...

s/[^!'()*-.\w]/sprintf'%%%02x',ord$&/ge

kullanım

echo -n ' !"#$%&'\''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqstuvwxyz{|}~' | perl -pe "s/[^'()*-.\w]/sprintf'%%%02x',ord$&/ge"
%20%21%22%23%24%25%26'()*+,-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqstuvwxyz%7b%7c%7d%7e


1

Python 3, 92 bayt

Orlp sayesinde 5 bayt.

Sp3000 sayesinde 1 bayt.

import re;lambda s:''.join(re.match("[!'-*.0-9\w-]",c,256)and c or'%%%02X'%ord(c)for c in s)

Boşver!


re.match("[!'()*.0-9A-Za-z_-]",c)and c or'%%%02X'%ord(c)
orlp

@ Sp3000 \wgenişletilmiş ASCII içerir
Leaky Nun

Ayrıca, '()*->'-*
Sp3000

Bence ( ) seçeneği \wile çalışır : ideone . Kesinlikle ideone üzerinde Python 3'te çalışıyor ve gerektiği ile çalışmak mesela (Python 2'de dizeleri, ancak ideone ikincisi için korkak şeyler yapmak gibi görünüyor üzerinde 10 verir ideone üzerinde ancak 5 repl.it tüm 2.7 olmasına rağmen ve bilgisayarım. 10)256re.ASCIIu"..."print len(u"ÑÉÐÔ®")
Sp3000

1

C, 83 bayt

f(char*p){for(;*p;++p)printf(isalnum(*p)||strchr("!'()*-._",*p)?"%c":"%%%02X",*p);}

1

Python, 86 bayt

lambda s:"".join(["%%%02X"%ord(c),c][c<"{"and c.isalnum()or c in"!'()*-._"]for c in s)

Bağlantı noktası C cevabım.


1

Yakut, 37 + 3 = 40 bayt

Şunlarla çalış -p(3 ekstra bayt), örneğin $ ruby -p percent_encode.rb:

gsub(/[^\w!'()*-.]/){"%%%02X"%$&.ord}

1

Jöle , 28 27 bayt

ḟØWḟ©“!'()*-.”Od⁴‘ịØH”%p®,y

Bu monadik bir link. Çevrimiçi deneyin!

Nasıl çalışır

ḟØWḟ©“!'()*-.”Od⁴‘ịØH”%p®,y  Monadic link. Argument: s (string)

 ØW                          Yield “0...9A...Z_a...z”.
ḟ                            Remove these characters from s.
     “!'()*-.”               Yield “!'()*-.”.
   ḟ                         Remove these characters from s.
    ©                        Copy the result to the register.
              O              Ordinal; get the code point of each character.
               d⁴            Divmod 16; yield quotient and remainder modulo 16.
                 ’           Decrement the results.
                  ịØH        Index into “0123456789ABCDEF”.
                     ”p%     Perform Cartesian product with ”%, prepending it to
                             each pair of hexadecimal digits.
                        ®,   Yield [t, r], where t is the string in the register
                             and r the result of the Cartesian product.
                          y  Use this pair to perform transliteration on s.

1

Haskell, 201 179 178 127 119 bayt

import Data.Char;import Numeric;f=(=<<)(\c->if isAlphaNum c&&isAscii c||elem c"-_.~"then[c]else '%':(showHex$ord c)"")

Ungolfed:

import Data.Char
import Numeric

f=(=<<) e
e c = if isAlphaNum c && isAscii c && c `elem` "-_.~" then [c] else '%' : (showHex $ ord c) ""

Bir sürü alanı kaldırabilir misin?
Rɪᴋᴇʀ

Sen gevşek olabilir where, dönüş if, makyaj kısmi e, muhafız içine son argüman gevşek showHex, inline p, inline ssipariş, imza gevşek elemve gevşek daha boşluk. İlk yaklaşım olarak 118'e düştüm.
MarLinn

@MarLinn, kodu kısmakla ilgili iyi öneriler için teşekkürler. Ancak, bazı önerilerle ilgili bir sorunum vardı. Her şeyden önce, imzayı kaldırırsam GHC bunu şikayet edecektir No instance for (Foldable t0) arising from a use of ‘foldr’. Fonksiyonun türünün belirsiz olduğunu ve sonuçta bağlanmasıyla sonuçlandığını söylüyor f :: t0 Char -> [Char]. Ve ikincisi, boş dize argümanını showHex'ten kaldıramadığım için boş bir dizeye String -> Stringihtiyaç duyduğu için bir tür takma adı olan bir ShowS döndürür .
sham1

@ sham1, yes, ShowSbir String alır ... ama bir tane var: eklediğiniz (++). Böylece her ikisini de aynı anda kaybedebilirsiniz. Aslında bu yüzden böyle ShowSgörünüyor. Yazım hatası almıyorum, bu yüzden sanırım sürüm bir şey mi? Şimdiye kadar fark ettiğim diğer iki şey: otherwiseher zaman ile değiştirilebiliyor 1<2(için bir kısayol True), ancak ifbunun yerine geri dönerseniz tüm satırları satır içine alabilir eve bırakabilirsiniz. Ve hatta a'yı concatMap, yani a (>>=). Çok tasarruf etmiyor, ama en azından biraz. Tür hatasını da çözebilir.
MarLinn

0

Python 2, 78 bayt

lambda s:"".join(["%%%02x"%ord(c),c][c.isalnum()or c in"!'()*-._"]for c in s)

Daha güzel biçimlendirilmiş:

lambda s:
    "".join(["%%%02x" % ord(c), c][c.isalnum() or c in"!'()*-._"] for c in s)

0

SQF , 199 176

Dosya olarak işlev biçimini kullanma:

i="";a="0123456789ABCDEF!'()*-.GHIJKLMNOPQRSTUVWXYZ_";{i=i+if((toUpper _x)in a)then{_x}else{x=(toArray[_x])select 0;"%"+(a select floor(x/16))+(a select(x%16))}}forEach _this;i

Şu şekilde ara: "STRING" call NAME_OF_COMPILED_FUNCTION


0

PowerShell v2 +, 146 bayt

param($n)37,38+0..36+43,44,47+58..64+91,93+96+123..255-ne33|%{$n=$n-replace"[$([char]$_)]",("%{0:x2}"-f$_)};$n-replace'\\','%5c'-replace'\^','%5e'

Uzun çünkü sadece diğer regex dize kopya yapıştırma yerine farklı bir yaklaşım göstermek istedim.

Bunun yerine, burada yüzde kodlaması gereken her kod noktasında döngü yapıyoruz ve her yinelemede -replacegiriş dizesi üzerinde bir değişmez değer yapıyoruz $n(yeniden kaydetme $n). Sonra kaçması gereken iki özel karakteri hesaba katmalıyız \ve ^böylece bunlar -replacesonunda ayrı öğelerdedir. Bu son dizgiyi yeniden kaydetmediğimiz için, boru hattında kaldı ve yazdırma örtük.


0

16/32 bit x86 derlemesi, 73 bayt

Bayt kodu:

AC 3C 21 72 2A 74 3E 3C 26 76 24 3C 2B 72 36 3C
2C 76 1C 3C 2F 72 2E 74 16 3C 3A 72 28 74 10 3C
5F 74 22 50 0C 60 3C 60 74 02 3C 7B 58 72 16 D4
10 3C 09 1C 69 2F 86 E0 3C 09 1C 69 2F 92 B0 25
AA 92 AA 86 E0 AA E2 B8 C3

demontaj:

l0: lodsb         ;fetch a character
    cmp  al, 21h
    jb   l1       ;encode 0x00-0x20
    je   l2       ;store 0x21
    cmp  al, 26h
    jbe  l1       ;encode 0x22-0x26
    cmp  al, 2bh
    jb   l2       ;store 0x27-0x2A
    cmp  al, 2ch
    jbe  l1       ;encode 0x2B-0x2C
    cmp  al, 2fh
    jb   l2       ;store 0x2D-0x2E
    je   l1       ;encode 0x2F
    cmp  al, 3ah
    jb   l2       ;store 0x30-0x39
    je   l1       ;encode 0x3A
    cmp  al, 5fh
    je   l2       ;store 0x5F
    push eax
    or   al, 60h  ;merge ranges
    cmp  al, 60h
    je   l3       ;encode 0x40, 0x60
    cmp  al, 7bh
l3: pop  eax
    jb   l2       ;store 0x41-0x5A, 0x61-0x7A
                  ;encode 0x3B-0x3F, 0x5B-0x5E, 0x7B-0xFF

l1: aam  10h      ;split byte to nibbles
    cmp  al, 9    ;convert 0x0A-0x0F 
    sbb  al, 69h  ;to
    das           ;0x41-0x46 ('A'-'F')
    xchg ah, al   ;swap nibbles
    cmp  al, 9    ;do
    sbb  al, 69h  ;other
    das           ;half
    xchg edx, eax ;save in edx
    mov  al, '%'
    stosb         ;emit '%'
    xchg edx, eax
    stosb         ;emit high nibble
    xchg ah, al

l2: stosb         ;emit low nibble or original character
    loop l0       ;until end of string
    ret


Şununla ara : - esi = kaynak dizgiyi tutan arabelleğe işaretçi;
- edi = kodlanmış dizeyi alan arabelleğe giden işaretçi;
- ecx = kaynak dizginin uzunluğu.

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.