0
char *args[32];
char **next = args;
char *temp = NULL;
char *quotes = NULL;

temp = strtok(line, " \n&");

while (temp != NULL) {
    if (strncmp(temp, "\"", 1) == 0) {
        //int i = strlen(temp);
        printf("first if");
        quotes = strtok(temp, "\"");    
    } else if (strncmp(temp, "\"", 1) != 0) {
        *next++ = temp;
        temp = strtok(NULL, " \n&");
    }
}

如果字符串的一部分用引号引起来,我很难理解如何仍然保留空格。例如,如果我希望 execvp() 执行以下命令:diff "space name.txt" sample.txt,它应该将 diff 保存在 args[0],space name.txt 保存在 args[1],sample.txt 保存在 args[ 2]。

我不太确定如何实现这一点,我已经尝试了几种不同的 if 语句逻辑方式,但我并不完全在那里。目前我正在尝试做一些简单的事情,例如:ls“文件夹”,但是,它卡在了打印我的 printf() 语句的 while 循环中。

我知道这不是一个问题 - 它更多地解释了我正在努力实现的目标以及到目前为止我在哪里,但我遇到了麻烦,并且真的很感激一些关于逻辑应该如何的提示。

4

5 回答 5

1

而不是strtok逐个字符地处理字符串。如果您看到",请设置一个标志。如果标志已经设置 - 改为取消设置。如果您看到一个空格 - 检查标志并切换到下一个参数,或者将空格添加到当前。任何其他字符 - 添加到当前。零字节 - 完成处理。

通过一些额外的努力,您甚至可以处理diff "file \"one\"" file\ two(您应该得到diff,file "one"file two结果)之类的东西

于 2013-03-25T13:06:53.690 回答
0

所以这是我在该行中读到的地方:

while((qtemp = fgets(line, size, stdin)) != NULL ) {
    if (strcmp(line, "exit\n") == 0) {
        exit(EXIT_SUCCESS);
    }
    spaceorquotes(qtemp);
}    

然后我去这个:(我没有添加我的初始化程序,但你明白了)

length = strlen(qtemp);
for(i = 0; i < length; i++) {
    position = strcspn(qtemp, " \"\n");
    while (strncmp(qtemp, " ", 1) == 0) {   
        memmove(qtemp, qtemp+1, length-1);
        position = strcspn(qtemp, " \"\n");
    } /*this while loop is for handling multiple spaces*/

    if (strncmp(qtemp, "\"", 1) == 0) { /*this is for handling quotes */    
        memmove(qtemp, qtemp+1, length-1);
        position = strcspn(qtemp, "\"");
        stemp = malloc(position*sizeof(char));
        strncat(stemp, qtemp, position);
        args[i] = stemp;
    } else {      /*otherwise handle it as a (single) space*/
        stemp = malloc(position*sizeof(char));
        strncat(stemp, qtemp, position); 
        args[i] = stemp;
    }
    //printf("args: %s\n", args[i]);
    length = strlen(qtemp);
    memmove(qtemp, qtemp+position+1, length-position);
}
args[i-1] = NULL; /*the last position seemed to be a space, so I overwrote it with a null to terminate */
if (execvp(args[0], args) == -1) {
    perror("execvp");
    exit(EXIT_FAILURE);
}

我发现使用 strcspn 有帮助,正如可修改的左值所建议的那样。

于 2013-03-26T20:55:23.960 回答
0

我什至不明白你试图做什么。您是否尝试将输入字符串标记为空格分隔的标记?

只需在空格上分隔输入字符串,当您遇到双引号字符时,您需要第二个内部循环来处理带引号的字符串。

带引号的字符串比搜索结束引号要多。您需要处理反斜杠,例如反斜杠转义引号和反斜杠转义反斜杠。

只需考虑以下几点:

diff "space name \" with quotes.txt\\" foo

它指的是(垃圾)文件名space name " with quotes.txt\。将此用作测试用例,然后您就知道何时完成了基础知识。请注意,shell 命令行拆分比这要疯狂得多。

于 2013-03-25T13:08:34.033 回答
0

这是我的想法:

  1. 制作两个指针AB,最初指向字符串的第一个字符。
  2. 使用指针遍历字符串A,将每个字符复制到数组中,只要它不是空格。
  3. 到达 a后,从该位置开始"指针并继续前进,直到到达下一个,复制包括空格在内的所有内容。BA+1"
  4. 现在从数字 2 开始重复,从 char 开始B+1
  5. 只要你还没有达到,就重复\0

注意:如果有嵌套引号,您将不得不考虑该怎么做。

您还可以使用标志 (int 1 || 0) 和指针来表示您是否在引号中,遵循基于标志的 2 个单独规则。

于 2013-03-25T13:21:28.507 回答
0

写三个函数。所有这些都应该返回它们处理的字节数。首先,处理引用参数的那个。

size_t handle_quoted_argument(char *str, char **destination) {
    assert(*str == '\"');
    /* discard the opening quote */
    *destination = str + 1;

    /* find the closing quote (or a '\0' indicating the end of the string) */
    size_t length = strcspn(str + 1, "\"") + 1;
    assert(str[length] == '\"'); /* NOTE: You really should handle mismatching quotes properly, here */

    /* discard the closing quote */
    str[length] = '\0';
    return length + 1;
}

...然后是一个处理未引用参数的函数:

size_t handle_unquoted_argument(char *str, char **destination) {
    size_t length = strcspn(str, " \n");
    char c = str[length];
    *destination = str;
    str[length] = '\0';
    return c == ' ' ? length + 1 : length;
}

...然后是处理(可能是重复的)空格的函数:

size_t handle_whitespace(char *str) {
    int whitespace_count;
    /* This will count consecutive whitespace characters, eg. tabs, newlines, spaces... */
    assert(sscanf(str, " %n", &whitespace_count) == 0);
    return whitespace_count;
}

将这三者结合起来应该很简单:

size_t n = 0, argv = 0;
while (line[n] != '\0') {
    n += handle_whitespace(line + n);
    n += line[n] == '\"' ? handle_quoted_argument(line + n, args + argv++)
                         : handle_unquoted_argument(line + n, args + argv++);
}

通过将其分解为四个独立的算法,你能看出这个任务变得多么简单吗?

于 2013-03-25T13:34:08.403 回答