在C中通过字符串运行命令

Posted

技术标签:

【中文标题】在C中通过字符串运行命令【英文标题】:Run command through string in C 【发布时间】:2014-07-10 21:50:42 【问题描述】:

我需要用 C 语言编写一个应用程序,允许用户通过stdin 提交各种命令。根据具体的命令,程序会执行各种功能。

命令需要这样读:

func_name(%d:%d) 

其中func_name 是要执行的函数的名称,每个%d 是一个整数,将作为函数的参数。

我不知道如何以有效的方式做到这一点。 其实,我真的不知道怎么做才对。

希望你们知道如何帮助我。

【问题讨论】:

不知道 fscanf 存在吗?还是什么? 我做到了,我尝试使用 scanf,但直到我需要的 '(' 才能读取字符串。我认为的基础知识是读取字符串直到'(',然后将 '(' 和 ':' 之间的数字分配给一个 int,最后将 ':' 和 ')' 之间的数字分配给另一个 int。之后将字符串与不同名称的字符串进行比较函数,如果字符串是“标志”来运行函数 flagElement(x, y),x 和 y 是整数。 【参考方案1】:

子命令有帮助吗?你可以像./program <subcommand> <param1> <param2> 这样运行程序。这样就可以解析argv[1],并开始基于argv[1]将逻辑分派给函数。

如果你想要一个交互的环境,你可以使用一个while循环,在循环内使用fscanf来获取子命令和参数。

【讨论】:

【参考方案2】:

如何使用具有指向要运行的函数的函数指针的二叉搜索树来完成类似的操作。我不打算实现它,因为这对我来说工作量太大,但我为你建立了一个基本结构。如果您需要两个以上的整数,请将函数设为可变参数。

typedef void (*Command)(int, int);

typedef struct Node 
   char *key;
   Command cmd;
   struct Node *left;
   struct Node *right;
 Node;


//function to set up a BST of function pointers not implemented
void AddFunction(Node *root, char *name, Command cmd);

//function to retrieve function pointer given key not implemented
Command GetFunction(Node *root, char *name);


int main() 
   char cmdBuff[100], *name, *params;
   Node *root; //set up your BST
   while (scanf("%100s", cmdBuff) != EOF) 
      name = strstr(cmdBuff, "("));
      if (name) 
         *name = '\0'; //terminate string
         params = name + 1; //you can separate the integer args on your own
         //int1 = blahblahblah;
         //int2 = blahblahblah;
         GetFunction(root, name)(int1, int2);
      
   

【讨论】:

【参考方案3】:

有点复杂的剧透:

/*********************************************************************
** http:\\www.mahonri.info/SO/23796987_run-command-through-string-in-c.c
** If you like it, vote for it.
**
** Allows the user to submit various commands through stdin.
** Depending of the specific command, the program will execute various
** functions.
**
** Example usage (this code compiled into a program called 'test'):
**
**    > echo "EXE_Add(1:2) EXE_Subtract(10:5) bye()" | ./test
**    1+2=3
**    10-5=5
**    No such command: [bye]
**    Done.
*/

/*********************************************************************
** Compiler setup.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define CMD_TRUE  (-1)
#define CMD_FALSE (0)

typedef struct CMD_REC_S
   
   char *commandStr;
   int (*commandFn)(int, int);
    CMD_REC_T;

/*********************************************************************
** EXE_Add command handler.
*/
int EXE_Add(
      int I__a,
      int I__b
      )
   
   printf("%d+%d=%d\n", I__a, I__b, I__a+I__b);
   return(0);
   

/*********************************************************************
** EXE_Subtract command handler.
*/
int EXE_Subtract(
      int I__a,
      int I__b
      )
   
   printf("%d-%d=%d\n", I__a, I__b, I__a-I__b);
   return(0);
   

/*********************************************************************
** Command table identifies the name of all stdin commands (above).
*/
CMD_REC_T CMD_table[] =
   
      "EXE_Add",      EXE_Add,
      "EXE_Subtract", EXE_Subtract,
      NULL,           NULL
   ;

/*********************************************************************
** Fetch a command from stdin.  Return the command in allocated memory.
*/
int CMD_Fetch(
      char **_O_command
      )
   
   int     rCode      = 0;
   char   *command    = NULL;
   size_t  commandLen = 0;
   int     found      = CMD_FALSE;

   /* Initialize dynamic command buffer. */
   errno=0;
   command = malloc(++commandLen);
   if(NULL == command)
      
      rCode = errno ? errno : ENOMEM;
      fprintf(stderr, "malloc() failed.  errno:%d\n", errno);
      goto CLEANUP;
      
   *command = '\0';

   /* Read characters from stdin to a dynamic command buffer
    * until a ')' character is encountered.
    */
   while(!found)
      
      char *tmp;
      int   character;

      /* Read & process a character from stdin. */
      character=getchar();
      switch(character)
         
         case EOF:
            rCode=ENOENT;
            goto CLEANUP;

         case ')':
            found=CMD_TRUE;
            break;

         case '\t':
         case ' ':
            continue;

         default:
            break;
         ;

      /* Add the character to the dynamic command buffer. */
      errno=0;
      tmp=realloc(command, ++commandLen);
      if(NULL == tmp)
         
         rCode = errno ? errno : ENOMEM;
         fprintf(stderr, "realloc() failed.  errno:%d\n", errno);
         goto CLEANUP;
         
      command=tmp;
      command[commandLen-2] = character;
      command[commandLen-1] = '\0';
      

   /* Return results. */
   if(_O_command)
      
      *_O_command = command;
      command=NULL;
      

CLEANUP:

   if(command)
      free(command);

   return(rCode);
   

/*********************************************************************
** Execute command.
*/
int CMD_Execute(
      const char *I__command
      )
   
   int rCode=0;
   char *cp;
   CMD_REC_T *commandRec = CMD_table;
   int a, b;

   /* Isolate the function name. */
   cp=strchr(I__command, '(');
   if(NULL == cp)
      
      rCode=EINVAL;
      fprintf(stderr, "Parsing error: I__command[%s] is missing '('\n", I__command);
      goto CLEANUP;
      
   *cp='\0';
   ++cp;

   /* Fetch the CMD_REC_T from the CMD_table */
   while(commandRec->commandStr)
      
      if(0 == strcmp(commandRec->commandStr, I__command))
         break;

      ++commandRec;
      
   if(NULL == commandRec->commandStr)
      
      rCode=ENOENT;
      goto CLEANUP;
      

   /* Parse the two integers, a & b */
   a=atoi(cp);
   cp=strchr(cp, ':');
   if(NULL == cp)
      
      rCode=EINVAL;
      fprintf(stderr, "Parsing error: Missing ':'\n");
      goto CLEANUP;
      

   b=atoi(++cp);

   /* Verify that the commandRec->commandFn is non-NULL. */
   if(NULL == commandRec->commandFn)
      
      rCode=ENOSYS;
      fprintf(stderr, "Function %s() is unavailable.\n", commandRec->commandStr);
      goto CLEANUP;
      

   /* Call the specified function. */
   rCode=(*commandRec->commandFn)(a, b);
   if(rCode)
      
      fprintf(stderr, "%s() reports: %d\n", commandRec->commandStr, rCode);
      goto CLEANUP;
      

CLEANUP:

   return(rCode);
   

/*********************************************************************
** Program start.
*/
int main()
   
   int rCode=0;
   char *command=NULL;
   int done=CMD_FALSE;

   while(!done)
      
      rCode=CMD_Fetch(&command);
      switch(rCode)
         
         case 0:
            break;

         case ENOENT:
            rCode=0;
            done=CMD_TRUE;
            printf("Done.\n");
            continue;

         default:
            fprintf(stderr, "CMD_Fetch() reports: %d\n", rCode);
            goto CLEANUP;
         

      rCode=CMD_Execute(command);
      switch(rCode)
         
         case 0:
            break;

         case ENOENT:
            fprintf(stderr, "No such command: [%s]\n", command);
            continue;

         default:
            fprintf(stderr, "CMD_Execute() reports: %d\n", rCode);
            goto CLEANUP;
         

      free(command);
      command=NULL;
      

CLEANUP:

   if(command)
      free(command);

   return(rCode);
   

【讨论】:

不是我需要的,但感谢您的帮助。我正在使用它的一部分来尝试解决它,所以谢谢!

以上是关于在C中通过字符串运行命令的主要内容,如果未能解决你的问题,请参考以下文章

在命令行中通过 ssh 在远程机器上运行 MySQL 查询

我们可以在 Windows 中通过命令提示符运行 mysql 查询吗?

如何在 Qt 应用程序中通过终端命令运行分离的应用程序?

如何在Windows中通过Cygwin安装和运行Nmap程序?

在Linux中通过Top运行进程查找最高内存和CPU使用率

如何在 Linux tclsh 中通过光标键获取命令历史记录