25

我一直在尝试使用 SPACE 作为分隔符来标记字符串,但它不起作用。有没有人建议它为什么不起作用?

编辑:使用标记化:

strtok(string, " ");

代码如下

pch = strtok (str," ");
while (pch != NULL)
{
  printf ("%s\n",pch);
  pch = strtok (NULL, " ");
}
4

8 回答 8

46

像这样做:

char s[256];
strcpy(s, "one two three");
char* token = strtok(s, " ");
while (token) {
    printf("token: %s\n", token);
    token = strtok(NULL, " ");
}

注意:strtok修改字符串的标记,所以它不能是const char*.

于 2008-11-05T19:57:39.180 回答
39

这是一个strtok使用示例,请记住它strtok破坏其输入字符串(因此不能用于字符串常量

char *p = strtok(str, " ");
while(p != NULL) {
    printf("%s\n", p);
    p = strtok(NULL, " ");
}

基本上要注意的是,传递 aNULL作为第一个参数strtok告诉它从之前标记的字符串中获取下一个标记。

于 2008-11-05T19:57:53.673 回答
7

strtok 可能非常危险。它不是线程安全的。它的预期用途是在循环中一遍又一遍地调用,传入前一个调用的输出。strtok 函数有一个内部变量,用于存储 strtok 调用的状态。这种状态不是每个线程独有的——它是全局的。如果任何其他代码在另一个线程中使用 strtok,就会出现问题。也不是您要追踪的问题!

我建议寻找一个正则表达式实现,或者使用 sscanf 来分离字符串。

尝试这个:

char strprint[256];
char text[256];
strcpy(text, "My string to test");
while ( sscanf( text, "%s %s", strprint, text) > 0 ) {
   printf("token: %s\n", strprint);
}

注意:'text' 字符串在分离时被破坏。这可能不是首选行为 =)

于 2008-11-05T20:14:22.160 回答
2

您可以通过引入一个额外的变量来简化代码。

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

int main()
{
    char str[100], *s = str, *t = NULL;

    strcpy(str, "a space delimited string");
    while ((t = strtok(s, " ")) != NULL) {
        s = NULL;
        printf(":%s:\n", t);
    }
    return 0;
}
于 2008-11-05T20:02:26.270 回答
2

我制作了一些字符串函数来拆分值,尽可能使用更少的指针,因为此代码旨在在 PIC18F 处理器上运行。当可用的可用 RAM 很少时,这些处理器不能很好地处理指针:

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

char POSTREQ[255] = "pwd=123456&apply=Apply&d1=88&d2=100&pwr=1&mpx=Internal&stmo=Stereo&proc=Processor&cmp=Compressor&ip1=192&ip2=168&ip3=10&ip4=131&gw1=192&gw2=168&gw3=10&gw4=192&pt=80&lic=&A=A";

int findchar(char *string, int Start, char C) {
    while((string[Start] != 0)) { Start++; if(string[Start] == C) return Start; }
    return -1;
}

int findcharn(char *string, int Times, char C) {
   int i = 0, pos = 0, fnd = 0;

    while(i < Times) {
       fnd = findchar(string, pos, C);
        if(fnd < 0) return -1;
        if(fnd > 0) pos = fnd;
       i++;
   }
   return fnd;
}

void mid(char *in, char *out, int start, int end) {
    int i = 0;
    int size = end - start;

    for(i = 0; i < size; i++){
        out[i] = in[start + i + 1];
    }
    out[size] = 0;
}

void getvalue(char *out, int index) {
    mid(POSTREQ, out, findcharn(POSTREQ, index, '='), (findcharn(POSTREQ, index, '&') - 1));
}

void main() {
   char n_pwd[7];
   char n_d1[7];

   getvalue(n_d1, 1);

   printf("Value: %s\n", n_d1);
} 
于 2013-09-02T20:00:06.397 回答
0

在阅读 strtok 文档时,我看到您需要在第一次“初始化”调用之后传入一个 NULL 指针。也许你没有那样做。当然只是猜测。

于 2008-11-05T19:51:27.197 回答
0

这是另一个strtok()实现,它能够识别连续的分隔符(标准库strtok()没有这个)

该函数是 BSD 许可字符串库的一部分,称为zString。非常欢迎您贡献:)

https://github.com/fnoyanisi/zString

char *zstring_strtok(char *str, const char *delim) {
    static char *static_str=0;      /* var to store last address */
    int index=0, strlength=0;       /* integers for indexes */
    int found = 0;                  /* check if delim is found */

    /* delimiter cannot be NULL
    * if no more char left, return NULL as well
    */
    if (delim==0 || (str == 0 && static_str == 0))
        return 0;

    if (str == 0)
        str = static_str;

    /* get length of string */
    while(str[strlength])
        strlength++;

    /* find the first occurance of delim */
    for (index=0;index<strlength;index++)
        if (str[index]==delim[0]) {
            found=1;
            break;
        }

    /* if delim is not contained in str, return str */
    if (!found) {
        static_str = 0;
        return str;
    }

    /* check for consecutive delimiters
    *if first char is delim, return delim
    */
    if (str[0]==delim[0]) {
        static_str = (str + 1);
        return (char *)delim;
    }

    /* terminate the string
    * this assignmetn requires char[], so str has to
    * be char[] rather than *char
    */
    str[index] = '\0';

    /* save the rest of the string */
    if ((str + index + 1)!=0)
        static_str = (str + index + 1);
    else
        static_str = 0;

        return str;
}

正如在之前的文章中提到的,因为strtok(),或者我上面实现的那个,依赖于一个static *char变量来保存连续调用之间最后一个分隔符的位置,所以在处理多线程应用程序时应该格外小心。

于 2016-02-18T22:44:24.957 回答
-1
int not_in_delimiter(char c, char *delim){

    while(*delim != '\0'){
            if(c == *delim) return 0;
            delim++;
    }
    return 1;
}

char *token_separater(char *source, char *delimiter, char **last){

char *begin, *next_token;
char *sbegin;

/*Get the start of the token */
if(source)
  begin = source;
else
  begin = *last;

sbegin = begin;

/*Scan through the string till we find character in delimiter. */
while(*begin != '\0' && not_in_delimiter(*begin, delimiter)){
       begin++;
}

/* Check if we have reached at of the string */
if(*begin == '\0') {
/* We dont need to come further, hence return NULL*/
   *last = NULL;
    return sbegin;
}
/* Scan the string till we find a character which is not in delimiter */
 next_token  = begin;
 while(next_token != '\0' && !not_in_delimiter(*next_token, delimiter))    {
    next_token++;
 }
 /* If we have not reached at the end of the string */
 if(*next_token != '\0'){
  *last = next_token--;
  *next_token = '\0';
   return sbegin;
}
}

 void main(){

    char string[10] = "abcb_dccc";
    char delim[10] = "_";
    char *token = NULL;
    char *last = "" ;
    token  = token_separater(string, delim, &last);
    printf("%s\n", token);
    while(last){
            token  = token_separater(NULL, delim, &last);
            printf("%s\n", token);
    }

}

您可以在我的个人资料中提到的博客上阅读详细分析:)

于 2013-11-01T05:12:32.197 回答