将字符串分割成标记并将它们保存在一个数组中

43

如何将字符串分割为令牌并将它们保存在数组中?

具体而言,我有一个字符串"abc/qwe/jkh"。我想要按照"/"进行分隔,然后将令牌保存到一个数组中。

输出将会是这样的:

array[0] = "abc"
array[1] = "qwe"
array[2] = "jkh"

请帮助我

3个回答

48
#include <stdio.h>
#include <string.h>

int main ()
{
    char buf[] ="abc/qwe/ccd";
    int i = 0;
    char *p = strtok (buf, "/");
    char *array[3];

    while (p != NULL)
    {
        array[i++] = p;
        p = strtok (NULL, "/");
    }

    for (i = 0; i < 3; ++i) 
        printf("%s\n", array[i]);

    return 0;
}

如果我想比较array[0]和array[1],我应该怎么做? - Syeda Amna Ahmed
2
你可以使用<string.h>中的另一个函数:if (strcmp(array[0], array[1]) == 0) { // array[0] = array[1] } - rlib
33
假设标记数量已知。 - Jonathan.
3
该行代码的目的是使用斜杠字符 "/" 来将字符串拆分成多个子字符串,并将下一个子字符串的指针返回给指针变量 p。其中,strtok() 是一个标准 C 库函数,用于字符串分割。当第一次调用 strtok() 时,需要传入待分割的字符串地址和分隔符,之后每次调用 strtok(NULL, 分隔符) 则会返回下一个子字符串的指针,直到所有子字符串都被遍历完毕。 - Charles
1
strtok()在多线程程序、库中以及某些可能在循环未完成的情况下第二次调用strtok()的其他程序中效果不佳。当strtok_r()不可用时,编写自己的函数或使用strtok_r()可能是更好的解决方案。 - 12431234123412341234123

15
您可以使用strtok()函数。
char string[] = "abc/qwe/jkh";
char *array[10];
int i = 0;

array[i] = strtok(string, "/");

while(array[i] != NULL)
   array[++i] = strtok(NULL, "/");

7
如果在strtok()的第一个参数中指定了空指针,函数会继续扫描上一次成功调用该函数后的位置。请注意,这句话只是翻译原文,没有添加额外的解释或信息。 - Tomas M
3
表现相当不错。如果我们不知道分割元素的数量,该如何实现动态计数呢? - Samir
数组不能用变量初始化吗? - RoylatGnail
1
这将4个元素放入数组中,最后一个元素为NULL。 - MattSom
@12431234123412341234123 那么这些变量在哪里呢? - l33t
显示剩余2条评论

5

为什么strtok()是一个坏主意

在正常代码中不要使用strtok()strtok()使用static变量存在一些问题。在嵌入式微控制器上有一些用例适合使用static变量,但在大多数其他情况下请避免使用。当超过1个线程使用它时,当它在中断中使用时或当在连续调用strtok()之间处理多个输入的某些其他情况时,strtok()的行为会出现意外情况。 考虑以下示例:

#include <stdio.h>
#include <string.h>

//Splits the input by the / character and prints the content in between
//the / character. The input string will be changed
void printContent(char *input)
{
    char *p = strtok(input, "/");
    while(p)
    {
        printf("%s, ",p);
        p = strtok(NULL, "/");
    }
}

int main(void)
{
    char buffer[] = "abc/def/ghi:ABC/DEF/GHI";
    char *p = strtok(buffer, ":");
    while(p)
    {
        printContent(p);
        puts(""); //print newline
        p = strtok(NULL, ":");
    }
    return 0;
}

您可以期望输出为:
abc, def, ghi,
ABC, DEF, GHI,

但你会获得

abc, def, ghi,

这是因为你在printContent()中调用了strtok(),重置了在main()中生成的strtok()的内部状态。返回后,strtok()的内容为空,下一次调用strtok()将返回NULL

你应该做什么

如果你使用的是POSIX系统,你可以使用strtok_r(),这个版本不需要static变量。如果你的库没有提供strtok_r(),你可以编写自己的版本。这应该不难,Stackoverflow不是一个编码服务,你可以自己编写。


原帖中并未提到他们处于多线程环境中。 - jg6
6
他也没有说他不是。请记住,图书馆应该是多线程安全的,而将strtok()放在图书馆中是一个糟糕的想法。正如我在我的回答中所写的那样,这不仅是多线程应用程序中的问题。在你发表评论之前,请先阅读,谢谢。 - 12431234123412341234123

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接