我正在创建一个程序,在启动时接受输入命令和一些参数 scanf 并使用这些参数调用 execvp 。 我用 strsep 这样做。 我将字符串存储在一个数组(char *)中,然后我想将它拆分并在一个新数组中存储标记(这次它是一个数组[]所以我可以将它与execvp一起使用)。 使用 scanf 保存的参数应为终端命令(“ls ”,“ - l” ecc,“pwd” ...但是变量保存在 PATH 中,因此它们用“”分隔。
Ex :
./mystring
Type arguments : " ls -l "
这只是一个例子,用于指定哪种输入。 我将单独执行execvp,我需要帮助将字符串拆分为令牌。 这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
fflush(NULL); //to clean streams
printf("type the command to start (and arguments if required) \n");
char **st;
char dest[10];
scanf("%s",*st);
int i;
for (i=0;(dest[i]=strsep(st," "))!=NULL;i++)
continue;
for (int c=0;c<i;c++) printf(" arg %d : [%s] ",c,dest[c]);
return 0;
}
第5行和第6行需要调用 strsep , dest [10] 中的10是符号。
第7行将输入存储在圣
中第9行应拆分为“”并将命令和参数存储在 dest [I] 中(我将传递给execvp)。
第11行打印dest存储的内容。
这是令人遗憾的输出:
./mystring
type the command to start (and arguments if required)
Segmentation fault: 11
我不明白strsep是如何运作的,有人可以帮助我吗?
答案 0 :(得分:3)
您需要将strsep()
指针传递给要分析的字符串。这意味着更像:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("type the command to start (and arguments if required)\n");
char *dest[10];
char line[4096];
if (fgets(line, sizeof(line), stdin) == 0)
return 1;
line[strcspn(line, "\n")] = '\0'; /* Zap trailing newline */
char *st = line;
int i;
for (i = 0; i < 10 && (dest[i] = strsep(&st, " ")) != NULL; i++)
;
for (int c = 0; c < i; c++)
printf(" arg %d : [%s]\n", c, dest[c]);
return 0;
}
请注意dest
和st
的更改 - 以及添加空格以使代码更易于阅读(以及输出中的换行符)。我也删除了奇怪且不相关的fflush(NULL)
- 当程序启动时,缓冲区不需要刷新。代码从输入中删除换行符; scanf()
不会包含任何换行符。问题中的符号scanf("%s", *st);
只会从输入中读取一个单词,即使假设*st
指向某个已分配的内存(在问题中,它没有)。
请注意,macOS手册页中的strsep()
说明如下:
char *strsep(char **stringp, const char *delim);
strsep()
函数在*stringp
引用的字符串中找到第一个匹配项 字符串delim
(或终止'\0'
字符)中的任何字符,并将其替换为'\0'
。分隔符后面的下一个字符的位置(如果结束,则为NULL) 到达的字符串)存储在*stringp
中。返回*stringp
的原始值。
这意味着您需要将指针传递给char *
变量,而不是char **
变量的值。 macOS手册页还包含一个显示类似代码的示例,将&string
传递给strsep()
char *string = …;
。阅读手册页有时会有一种艺术 - 并在手册页的各行之间进行阅读。
可以运行上面的代码(现已测试)来生成:
$ ./ss53
type the command to start (and arguments if required)
command-name-is-long a short arg
arg 0 : [command-name-is-long]
arg 1 : [a]
arg 2 : [short]
arg 3 : [arg]
$