我是 Erlang 世界的新手。我正在尝试实现该功能
拆分二进制。该函数作为输入(列表,索引)并拆分
根据索引将列表分为两个列表。
根据split_binary/2 的erlang 文档,这两个参数是binary,它不是一个列表,以及您要在其中拆分二进制文件的bytes 的数量。
首先,您需要对什么是二进制文件有一个基本的了解。二进制是一个字节序列,其中每个字节是 8 位,表示某个整数,例如
0010 0001
这是33。下面是一个二进制示例:
<<1, 2, 3>>
当您不为每个整数指定大小时,默认情况下每个整数将占用一个字节。如果您希望 2 占用两个字节,即 0000 0000 0000 0010,即 16 位,那么您可以这样写:
<<1, 2:16, 3>>
shell 将显示为:
<<1,0,2,3>>
嗯?那个 0 是从哪里来的? shell逐字节显示二进制,整数0000 0000 0000 0010的第一个字节是0000 0000,也就是0。
接下来,您可以像处理列表一样单步执行二进制文件,从二进制文件的前面一次提取任意数量的位。碰巧split_binary/2 每次从二进制文件的头部提取 8 位或 1 个字节。
学习如何逐步执行二进制文件有几个技巧:
-
对于列表,[] 表示一个空列表,对于二进制文件,<<>> 表示一个空二进制文件。
-
对于列表,您编写 [Head|Tail] 以提取列表的头部,对于二进制文件,您编写 <<Bits:3, Rest/binary>> 以从二进制文件的前面提取 3 位。在您的情况下,您需要从二进制文件的前面提取 8 位。
以下是您可以执行的操作的示例:
-module(a).
-compile(export_all).
split_b(Bin, N) ->
split_b(Bin, N, _Acc = <<>>).
split_b( Bin, _N = 0, Acc) -> [Acc, Bin];
split_b(<<Bits:8, Rest/binary>>, N, Acc) ->
split_b(Rest, N-1, <<Acc/binary, Bits>>).
在外壳中:
40> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}
41> a:split_b(<<5,6,7>>, 1).
[<<5>>,<<6,7>>]
42> a:split_b(<<5,6,7>>, 2).
[<<5,6>>,<<7>>]
请注意,在构建二进制文件时,二进制文件的一个段可以是另一个二进制文件:
23> Bin = <<1, 2, 3>>.
<<1,2,3>>
24> Acc = <<Bin/binary, 4>>.
<<1,2,3,4>>
如果你真的想实现lists:split/2,你可以这样做:
-module(a).
-compile(export_all).
split_l(N, List) ->
split_l(N, List, _Acc=[]).
split_l(_N=0, List, Acc) ->
[lists:reverse(Acc), List];
split_l(N, [H|T], Acc) ->
split_l(N-1, T, [H|Acc]).
在外壳中:
2> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}
3> a:split_l(1, [10, 20, 30]).
["\n",[20,30]]
4> shell:strings(false).
true
5> a:split_l(1, [10, 20, 30]).
[[10],[20,30]]
6> a:split_l(2, [10, 20, 30]).
[[10,20],[30]]