将字符串作为带有空格分隔参数的命令读取的最佳方法是什么?

时间:2015-01-23 19:37:45

标签: c linux

我目前正在编写一个原始shell,允许用户输入一些基本命令:lscat等。我正在从用户那里获取如下输入:ls /home/someUser/someDirectory并存储这是一个字符数组,比如说input。我写了一些小函数lscat等等,这些函数接受一个参数并打印到stdout预期的结果。

我想知道的是:将input分解为命令和论证的最佳方法是什么?对于上述示例,我想获得两个不同的块:ls/home/someUser/someDirectory,以便我可以使用什么参数检查用户想要执行的命令。当然,我可以维护指针并检查数组的前几个字符并比较它们,然后在空格后继续处理字符并相应地解析参数,但这将是非常乏味和低效的。有没有更好的方法来做到这一点,可能是一个内置函数?

提前致谢。

3 个答案:

答案 0 :(得分:1)

您可以尝试使用strtok

#include <string.h>
#include <stdio.h>

int main(){
  char example_input[80] = "ls /home/user/directory/file.ext";
  const char s[2] = "-";
  char *token = strtok(example_input, " ");

  /* walk through other tokens */
  while( token != NULL ){
     printf("%s\n", token );
     token = strtok(NULL, s);
  }

  return(0);
}

转义字符会有些棘手。

如果你只需要将字符串分成命令和参数,这可能有效:

#include <string.h>
#include <stdio.h>

void cmd_ls(const char *arg){
  printf("lsing %s\n",arg);
}

void cmd_pwd(const char *arg){
  printf("pwding %s\n",arg);
}

int main(){
  char example_input[80] = "psdwd /home/user/directory/file.ext";
  const char s[2] = "-";

  //Find command, assuming it ends at the first space

  //Points to first space in string, will eventually point to beginning of
  //command
  char *command  = strchr(example_input, ' ');

  //Will point to beginning of argument
  char *argument = NULL;

  //If command is not NULL, then there is at least one space, so the string has
  //the form "<COMMAND> X" where X is either '\0' (string terminator) or another
  //character. If the string contains a space, edit it so that there is a
  //terminator after the command. If there is an argument, return a pointer to
  //its beginning (which may be a space).
  if(command!=NULL){
    *(command) = '\0';       //Terminate command string
    if(*(command+1)!='\0')   //If there are argument characters, point to them
      argument = command+1;
  }
  command = example_input;   //Point command to beginning of command


  //Do I recognise this command?
  if(strcmp(command,"ls")==0){
    cmd_ls(argument);
  } else if(strcmp(command,"pwd")==0) {
    cmd_pwd(argument);
  } else {
    printf("Unrecognised command!\n");
  }

  return(0);
}

答案 1 :(得分:1)

检查出来

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char **split(char *const source, const char *const delimiter)
{
    size_t length;
    char **list;
    size_t count;
    char  *pointer;
    char  *token;
    void  *saved;

    if ((source == NULL) || (delimiter == NULL))
        return NULL;

    list    = NULL;
    pointer = source;
    count   = 0;
    while ((token = strtok(pointer, delimiter)) != NULL)
    {
        saved = realloc(list, (1 + count) * sizeof(*list));
        if (saved == NULL)
            goto abort;
        length      = strlen(token);
        list        = saved;
        list[count] = malloc(1 + length);
        if (list[count] == NULL)
            goto abort;
        strcpy(list[count], token);
        pointer = NULL;

        count++;
    }
    saved = realloc(list, (1 + count) * sizeof(*list));
    if (saved == NULL)
        return list;
    list        = saved;
    list[count] = NULL;

    return list;
abort:
    while (count != 0)
        free(list[count--]);
    free(list);

    return NULL;
}

int main()
{
    size_t k;
    char string[] = "example string with spaces";
    char **list;

    list = split(string, " ");
    if (list == NULL)
        return -1;
    k = 0;
    while (list[k] != NULL)
    {
        printf("%s\n", list[k]);
        free(list[k]);

        k++;
    }
    free(list);
    return 0;
}

split函数将返回一个包含标记的char指针数组,并有一个sentinel NULL指针,告诉你列表末尾的位置。

答案 2 :(得分:1)

你可以简单地使用scanf。你必须阅读输入,直到你得到一个&#39; \ n&#39;字符。 这样做的代码是:

scanf("%[^\n]", string);

总字符串将存储在数组字符串中。你可以做进一步的字符串处理来提取所需的数据。