如何在C中使用strsep?

时间:2018-06-18 18:21:48

标签: c string split strsep

我正在创建一个程序,在启动时接受输入命令和一些参数 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是如何运作的,有人可以帮助我吗?

1 个答案:

答案 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;
}

请注意destst的更改 - 以及添加空格以使代码更易于阅读(以及输出中的换行符)。我也删除了奇怪且不相关的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]
$