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闲人,谢谢!

 

posted @ 2012-05-06 09:45  chinagragon  阅读(1635)  评论(0)    收藏  举报

Powered by中国龙 博客空间 IT闲人,不干实事