-3

我正在创建一个程序,该程序在启动时接受输入命令和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;
}

调用strsep需要第 5 行和第 6 行,dest[10]中的 10是符号。

第 7 行将输入存储在 st。

第 9 行应该拆分为 " " 并将命令和参数存储在dest[I]中(我将传递给 execvp)。

第 11 行打印 dest 存储的内容。

这是可悲的输出:

./mystring 
type the command to start (and arguments if required) 
Segmentation fault: 11

我不明白 strsep 是如何工作的,有人可以帮助我吗?

4

1 回答 1

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指向一些分配的内存(在问题中,它没有)。

请注意,strsep()macOS 手册页中的描述说:

char *strsep(char **stringp, const char *delim);

strsep()函数在 引用的字符串中定位字符串*stringp中任何字符delim(或终止'\0'字符)的第一次出现,并将其替换为 '\0'。分隔符之后的下一个字符的位置(或 NULL,如果已到达字符串的末尾)存储在*stringp. 的原始值*stringp被返回。

这意味着您需要传递指向char *变量的指针,而不是char **变量的值。macOS 手册页还包括一个示例,该示例显示了类似的代码,传递&stringstrsep()where 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]
$
于 2018-06-18T18:31:12.967 回答