Erlang实战练习(五)
看过我前几次实战练习的朋友应该知道,大多数文章我都在通过练习来学习Erlang语言,我觉得通过不同的练习,可以对一门语言的某些方面有更加深入和细致的了解,而且最重要的是它比纯将理论让人印象更深刻。为了更好的接着前面的逻辑,下面温故前面所讲的内容吧:
Erlang实战练习(一):生成斐波那契数列、求列表元素平均值、求12+22+32+42+52+…+n2、将两个列表连接起来等;
Erlang实战练习(二):求1-2+3-4+5-6+...+n、汉诺塔、求特殊的和、输出满足条件的数等;
Erlang实战练习(三):冒泡排序、插入排序、打印九九乘法表等;
Erlang实战练习(四):二分搜索、echo server、进程环三个实战练习。
本文将要探讨的是列表的高级操作,通过一个分布式管理系统对2-4个节点进行管理。
练习1:列表的高级操作。

分析:此练习需实现4个功能,包括过滤不满足条件的列表元素、列表逆置、连接多个列表、将嵌套列表扁平化,代码如下:
-module(list).
-export([filter/2,reverse/1,concatenate/3,flatten/1]).
%% Return all elements lower then X in L
filter(L, X) -> filter(L,X,[]).
filter([],X,Ret) -> reverse(Ret);
filter([H|T],X, Ret) ->
if
H =< X ->
Temp = [H|Ret],
filter(T,X,Temp);
H > X ->
filter(T,X,Ret)
end.
%% reverse a list
reverse(L) -> reverse(L,[]).
reverse([],Ret) -> Ret;
reverse([H|T], Ret) ->
Temp = [H|Ret],
reverse(T,Temp).
%% concatenate a list of lists
concatenate(L1,L2,L3) ->
NewList = concate(L2,reverse(L1)),
concate(NewList,L3).
concate([],L2) -> L2;
concate([H|T],L2) ->
concate(T,[H|L2]).
%% given a list of nested list, return a flat list
flatten(L) -> flatten(L,[]).
flatten([],Ret) -> Ret;
flatten(L,Ret) ->
case is_integer(L) of
true ->
New = [L|Ret];
false->
%io:format("1--(~p)~n",[L]),
First = lists:nth(1,L),
Remain = lists:sublist(L,2,length(L)-1),
%io:format("Remain--(~p)~n",[Remain]),
case is_integer(First) of
true ->
Temp = [First|Ret],
%io:format("2--(~p)--(~p)~n",[First,Temp]),
flatten(Remain,Temp);
false ->
%io:format("3--(~p)~n",[First]),
Temp = flatten(First,Ret),
flatten(Remain,Temp)
end
end.
编译后,运行结果如下:

不多解释了,知识对于flatten/1,输出结果可能与原来顺序不一样,大家可以自己想办法。
练习2:分布式管理系统,对2~4个结点进行管理,支持以下命令:
-list, 列出管理的所有结点的信息;
-quit,断开与所有结点的连接,退出程序;
-cmd,在一个、多个或所有结点上运行一个脚本或命令,并将各个结点返回的信息打印出来。
提示:使用os:cmd()函数。
注:os:cmd()为
-module(dist_manage). -export([rpc/2, start/1,list/0,quit/0,cmd/2]). start(Node) -> Pid = spawn(Node, fun() -> loop() end), put(Node,Pid), start_success. list() -> L = nodes(), io:format("Node connect to this server node:~n"), lists:foreach( fun(X) -> io:format("Node: (~p) ~n",[X]) end, L ). quit() -> L = nodes(), io:format("Current node will disconnect to his connected nodes:~n"), lists:foreach( fun(X) -> disconnect(X) end, L ). disconnect(Node) -> disconnect_node(Node), io:format("Node:(~p) disconnected~n",[Node]). cmd(Node,Command) ->rpc(get(Node),Command). rpc(Pid, Command) -> Pid ! {rpc, self(), Command}, receive {Pid, Node, Response} -> io:format("Node:(~p) Process (~p) has excuted the command.~n", [Node,Pid]), io:format("The result is: {~n~n ~s }~n~n", [Response]) end. loop() -> receive {rpc, Pid, ls} -> os:cmd("dir"), LsOut = os:cmd("dir"), Pid ! {self(), node(),LsOut}, loop(); {rpc, Pid, ipconfig} -> LsOut = os:cmd("ipconfig"), Pid ! {self(), node(),LsOut}, loop() end.
启动三个节点,一个为server,另两个为node1和node2,如下图所示:

在server节点,启动node1和node2监听server请求,如下图所示:

调用list/1函数,显示与此server节点控制的节点列表,如下图所示:

调用cmd/2,在某个节点运行一个命令,为了实现这个功能,我只实现了windows下ipconfig、和dir命令,如下图所示:

注意:此程序运行在windows系统下,若在linux系统下运行,可能需要改变一下命令,如windows显示目录下的文件或文件夹用dir命令,而linux则使用ls命令等等。
本节通过两个实例,温故了前面所学的知识,同时对节点的通信与管理进行了简单的实战练习,下节将讲述一个Erlang创建文本索引的例子,要知道,Erlang适合并发编程和通信,在文本处理方面并不擅长,因此,下节将通过为文本建立索引来讲述Erlang操作文本的知识。
注:如无特殊说明,本博客内容纯属原创,转载请注明:http://www.cnblogs.com/itfreer/ | IT闲人,谢谢!

浙公网安备 33010602011771号