服务计算作业5:模仿、改写程序包

模仿、改写程序包

设计思路

myCobra用于处理简单的子命令系统(简单的,不能带很多参数的)。其中有一个命令树,每个节点的子节点就是子命令,每个节点存储自己的命令。

type Command struct设计:

type Command struct{
	cmds string;
	father *Command;
	sons [](*Command);
}

就是一棵树。

AddCommand函数:

func (c Command) AddCommand(newCom *Command){
	if (len(newCom.sons)!=0 || (newCom.father)!=nil){
		fmt.Printf("AddCommand Error\n");
		return;
	}
	newCom.father=&c;
	c.sons=append(c.sons,newCom)
	
}

在当前的叶子节点加入子命令,子命令是一个新节点。由于sons是用切片定义的,只用append函数就能插入。

CommandPath函数

func (C Command) CommandPath() string{
	if (C.father==nil){
		ret:="No Command : "+C.cmds;		
		return ret;
	}

	var now Command;
	var path []string;
	now=C;
	path=append(path,now.cmds);
	for ;(now.father)!=&root;{

		if (now.father==nil){
			ret:="No Command : "+now.cmds;		
			return ret;
		}
		now=*now.father;
		path=append(path,now.cmds);
	}

	ret:="";
	for i:=len(path)-1;i>=0;i=i-1{
		ret=ret+path[i];
		if i!=0{
			ret=ret+" -> "
		}
	}
	return ret;
}

返回当前节点的命令路径,路径通常用Root -> cmd1 -->cmd2 -->… -> current cmd 的形式列出。查找原理就是不断地访问父命令,迭代,直到访问到根,根的father就是自己。并且将一路上路过的节点的命令记录下来,再倒叙输出。

ExcuteC函数

func (c Command) ExcuteC(){
	cmd := exec.Command(c.cmds) 
    out, err := cmd.CombinedOutput()  
    if err != nil {  
        fmt.Println(err)  
    }  
    fmt.Println(string(out))
	
}

执行当前命令。
exec.Command会在Path系统变量中寻找指定的二进制文件,并且执行,这里将输出指向了cmd.CombineOutput,然后再一起输出它,这样我们就能看到输出了。

NewCommand函数

func NewCommand(cmds string) Command{
	var ret Command;
	ret.cmds=cmds;
	return ret;
}

创建一个新的command,可以添加在树中

此外还有:
Init函数:初始化一个树,在每次调用mycobra函数前需要先使用。
GetRoot函数:获得这棵树的根节点。

测试函数

mycobra_test可以这样写:

package mycobra;

import (
	"testing"
)

func TestInit(t *testing.T){
	Init();
	var c1=NewCommand("hello");
	mroot:=GetRoot();
	mroot.AddCommand(&c1);
	if (c1.CommandPath()!="Root -> hello"){
		t.Errorf("%s\n",c1.CommandPath());
	}

	var c2=NewCommand("hello2");
	c1.AddCommand(&c2);
	if (c2.CommandPath()!="Root -> hello -> hello2"){
		t.Errorf("%s\n",c2.CommandPath());
	}

	var c3=NewCommand("hello3");
	mroot.AddCommand(&c3);

	if (c3.CommandPath()!="Root -> hello3"){
		t.Errorf("%s\n",c3.CommandPath());
	}
	c1.ExcuteC();
	c2.ExcuteC();
	c3.ExcuteC();
}

创建了一个有四个节点的树,root,c1,c2,c3,对应不同的helloworld输出。
将c1,c2,c3三个命令Command加入到树中的不同位置,并且判断它们的CommandPath是否等于预期的值。

结果:
在这里插入图片描述

使用一下

在main函数中这样写(和test函数中的案例一样)

package main

import (
	"mycobra"
	"fmt"
//"os/exec"
//"os"
)

func main(){
	
	mycobra.Init();
	var c1=mycobra.NewCommand("hello");
	var root=mycobra.GetRoot();
	root.AddCommand(&c1);
	fmt.Printf("%s\n",c1.CommandPath());

	var c2=mycobra.NewCommand("hello2");
	c1.AddCommand(&c2);
	fmt.Printf("%s\n",c2.CommandPath());

	var c3=mycobra.NewCommand("hello3");
	root.AddCommand(&c3);
	fmt.Printf("%s\n",c3.CommandPath());

	c1.ExcuteC();
	c2.ExcuteC();
	c3.ExcuteC();
	
}

运行结果:
在这里插入图片描述
完全符合预期,路径是对的,输出也是对的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值