将代码点(或二进制)列表转换为字符串

nic*_*tme 7 elixir

我一直在研究Dave Thomas 在Elixir编程练习.我遇到了一个说写一个函数(caesar由于某种原因被调用)的函数,该函数将charlist和一个整数添加到charlist中的每个元素,如果它超过'z'则循环回'a',所以你应该能够称之为

MyList.caesar('ryvke', 13)

它应该返回一个字符串.

我有一个映射列表并执行添加的函数,但它返回一个charlist,我无法弄清楚如何将其转换为字符串:

defmodule MyList do
  def caesar(list, n) do
    Enum.map list, &(perform_addition(&1, n))
    |> to_charlist
    |> to_string
  end

  defp perform_addition(char_val, n) when char_val < 122 do
    char_val + n
  end

  defp perform_addition(_, n) do
    97 + n
  end
end
Run Code Online (Sandbox Code Playgroud)

我试过了:

基于最后一个子弹的尝试导致:

MyList.caesar('ryvke', 13)
# => <<127, 194, 134, 194, 131, 120, 114>>
Run Code Online (Sandbox Code Playgroud)

Dog*_*ert 21

要回答标题中的问题:您正在寻找List.to_string/1:

iex(1)> List.to_string([97, 98, 99])
"abc"
Run Code Online (Sandbox Code Playgroud)

您没有为这些参数获取可读字符串的原因是您旋转值的逻辑不正确.以下是如何移动小写字母并将其旋转回来,a如果它穿过z而不接触非小写字母:

# ?a == 97, ?z == 122
defp add(ch, n) when ch in ?a..?z do
  rem((ch - ?a + n), 26) + ?a
end
defp add(ch, n) when ch in ?A..?Z do
  rem(ch - ?A + shift, 26) + ?A
end
defp add(ch, _), do: ch
Run Code Online (Sandbox Code Playgroud)

有了这个,你只需要在输入charlist上映射函数,然后调用List.to_string/1:

def caesar(list, n) do
  list |> Enum.map(&add(&1, n)) |> List.to_string
end
Run Code Online (Sandbox Code Playgroud)
iex(1)> MyList.caesar('ryvke', 13)
"elixr"
Run Code Online (Sandbox Code Playgroud)

(因某种原因称为凯撒)

该算法称为Caesar Cipher.