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

我've been working on the exercises from Dave Thomas' s Programming in 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

我试过了:

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

MyList.caesar('ryvke', 13)
# => <<127, 194, 134, 194, 131, 120, 114>>

回答(1)

2 years ago

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

iex(1)> List.to_string([97, 98, 99])
"abc"

您're not getting a readable string back for those arguments is that your logic to rotate the value is incorrect. Here'如何在不接触非小写字母的情况下穿过 z 时如何移动小写字母并将其旋转回 a 的原因:

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

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

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

(出于某种原因称为凯撒)

该算法称为Caesar Cipher .