扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

c语言实例|实现简单的命令行

12小时前
204
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

嵌入式系统开发,经常需要用到命令行功能,比如uboot命令行。

命令行可以增加程序运行的灵活性,方便我们调试程序,大幅提高我们开发效率。

本文通过过一个简单的例子,来教大家如何实现一个简单的命令行模块,

该模块可以很方便的移植到自己的c项目中。

完整源码获取,见文末。

一、设计思想

二、实现

1、结构体

模块支持的命令相关信息,我们用结构体 struct _cmdnum来维护。

typedef void (* CMDFUNC)(char [][256],int argc);   
typedef struct _cmdnum{   
    char *cmd;   
    int index;   
    int paramcount;   
    CMDFUNC callback;
    char *info;
}CMDNUM,*PCMDNUM;   
成员 含义
char *cmd 命令名字
int index 命令下标
int paramcount 命令参数个数
CMDFUNC callback 命令对应回调函数

2、支持的命令

本问例子中加了4个命令:

功能 参数个数 回调函数
help 显示所有命令信息 0 showhelp()
exit 退出当前进程 0 quit()
test 打印所有参数信息,测试用 3 test()
send 将输入的16进制字符串,转换成16进制整形数并存入数组中 MAX_PARAM_NUM send()

定义如下:

CMDNUM cmdlist[] = 
{   
    {"help",1,0,showhelp},   
    {"exit",2,0,quit},   
    {"test",3,3,test}, 
    {"send",4,MAX_PARAM_NUM,send},   
};

3、相关函数

1. getline()
#include <stdio.h>
ssize_t getline(char **lineptr, size_t *n, FILE *stream);

从文件流stream读取一行数据,结果保存到*lineptr中,结尾包括空字符和换行符。

2. parsecmd()
void parsecmd(char *s)   

解析命令行内容,主要通过函数stripcmd/getcmdindex实现。

    stripcmd
int stripcmd(char *s,char cmds[][256])   

借助库函数strtok,通过空格将命令行s中各个参数分隔开,提取出参数,然后存储到二维数组**char cmds[256]**中,

    getcmdindex
int  getcmdindex(char *name)

通过命令名字name,遍历数组cmdlist[],并得到数组下标index。

4、核心代码

CMDNUM cmdlist[] = 
{   
    {"help",1,0,showhelp,"show all cmd info"},   
    {"exit",2,0,quit,"quit application"},   
    {"test",3,3,test,"[param...]print params"}, 
    {"send",3,MAX_PARAM_NUM,senddata,"[xx...]converts data from sting to hex and store to buf"},   
};   

void parsecmd(char *s)   
{   
char cmd[MAX_PARAM_NUM][256];   
int argc = 0;   
int index = -1; 
   
 argc = stripcmd(s,cmd);

//printf("argc=%dn",argc);
 index=getcmdindex(cmd[0]);
if(index == -1)   
 {   
if(argc>0)
  {
   cprintf(RED,"tNo such commond n");   
  }
return;   
 }   
elseif(argc>0)  
 {
  cmdlist[index].callback(cmd,argc);   
 }   
}   
   
UINT8 hex2char(UINT8 ch)
{
if ((ch >= '0') && (ch <= '9')) {return ch - '0';}
if ((ch >= 'a') && (ch <= 'f')) {return ch - 'a' + 10;}
if ((ch >= 'A') && (ch <= 'F')) {return ch - 'A' + 10;}
return (UINT8)0xff;
}

UCHAR stringToByte(char* str)
{
 UCHAR bytes = 0;

if(strlen(str)==1)
 {
  bytes= 0 << 4 | hex2char(str[0]);
 }else
 {
  bytes= hex2char(str[0]) << 4 | hex2char(str[1]);
 }

return bytes;
} 
//7e 01 02 01 00 07 07 01 00 00 00 c6 51 2a 7e 

void senddata(char argv[][256],int argc)
{
int i = 0;
int len = 0;
 UCHAR buf[256] = {0};

if(argc < 2)
 {
return;
 }
for(i=1;i<argc;i++)
 {
   buf[i-1] = stringToByte(argv[i]);
 }
 cprintf(GREEN,"n  buf:");
for(i=0;i<argc-1;i++)
 {
  cprintf(GREEN,"%02x ",buf[i]);
 }
putchar('n');

}
void test(char argv[][256],int argc)

{   
int i = 0;

for(i=0;i<argc;i++)
 {
  cprintf(YEL,"targv[%d]:%sn",i,argv[i]);
 }

return;   
} 
void showsysinfo(void)   
{   
  cprintf(D_GREEN_H,"---------------yikoulinux cmdline demo-----------n");     
}   
void quit(char cmd[][256],int argc)   
{   
    cprintf(RED_H,"exit to system n");   
    exit(0);   
}   
   
void showhelp(char cmd[][256],int argc)   
{   
int i = 0;  

for(i=0;i<sizeof(cmdlist)/sizeof(CMDNUM);i++) 
 { 
    cprintf(GREEN_H,"t%s",cmdlist[i].cmd);
  cprintf(YEL_H,"t%sn",cmdlist[i].info); 
 } 
return ;    
}  

int main(int argc, char* argv[])   
{   
    char *line;   
    int ret = 0;  
size_t len_line = 0;

    showsysinfo();   
    
while(1)   
 {   
  fflush( stdin );   
  cprintf(D_GREEN_H,DEV_NAME"# ");   

  ret = getline(&line, &len_line, stdin); 
if(ret == -1)
  {
   break;
  }
  parsecmd(line); 
free(line);
  line = NULL;
 }   
   
    return0;   
}   

三、测试

1. help

2. test

3. send

4. exit

四、源码获取

公众号【一口Linux】后台回复:cmd

或者加一口君好友 此外:一口君原创得所有c语言基础知识、c语言实例代码,均整理成pdf文档【定期更新

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

公众号『一口Linux』号主彭老师,拥有15年嵌入式开发经验和培训经验。曾任职ZTE,某研究所,华清远见教学总监。拥有多篇网络协议相关专利和软件著作。精通计算机网络、Linux系统编程、ARM、Linux驱动、龙芯、物联网。原创内容基本从实际项目出发,保持原理+实践风格,适合Linux驱动新手入门和技术进阶。