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,它应该在args [0]保存diff,在args [1]保存space name.txt,在args保存sample.txt [ 2]。
我不确定如何实现这一点,我已经尝试了几种不同的if语句逻辑方法,但我并不完全相同。目前我正在尝试做一些简单的事情:ls“文件夹”,然而,它会卡在打印我的printf()语句的while循环中。
我知道这不是一个问题 - 它更多地解释了我正在努力实现的目标以及我到目前为止所处的地方,但我遇到了麻烦,并且真的很欣赏一些关于逻辑如何的提示应该是。
答案 0 :(得分:1)
而不是使用strtok
通过char处理字符串char。如果您看到"
,请设置一个标记。如果已设置标志 - 请取消设置。如果看到空格 - 检查标志并切换到下一个arg,或者向当前添加空格。任何其他字符 - 添加到当前。零字节 - 完成处理。
通过一些额外的努力,您甚至可以处理diff "file \"one\"" file\ two
之类的内容(您应该获得diff
,file "one"
和file two
作为结果)
答案 1 :(得分:0)
我甚至很难理解你的尝试。您是否尝试将输入字符串标记为空格分隔的标记?
只需在空格上分隔输入字符串,当遇到双引号字符时,您需要第二个处理引用字符串的内部循环。
引用字符串比搜索结束引号更多。您需要处理反斜杠,例如反斜杠转义引号以及反斜杠转义反斜杠。
请考虑以下事项:
diff "space name \" with quotes.txt\\" foo
指的是(无用的)文件名space name " with quotes.txt\
。使用它作为测试用例,然后您就知道完成基础知识的时间。请注意,shell命令行拆分比这更疯狂。
答案 2 :(得分:0)
这是我的想法:
A
和B
,最初指向字符串的第一个字符。A
遍历字符串,只要它不是空格,就将每个字符复制到数组中。"
后,从位置B
开始指针A+1
,然后继续前行,直至到达下一个"
,复制包括空格在内的所有内容。 B+1
开始。\0
,就重复。注意:如果有嵌套引号,您必须考虑该怎么做。
您还可以使用一个标志(int 1 || 0)和一个指针来表示您是否在引用中,遵循基于该标志的2个单独规则。
答案 3 :(得分: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++);
}
通过将其分解为四个独立的算法,你能看出这项任务变得多么简单吗?
答案 4 :(得分: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有帮助,因为可修改的左值提示。