2008-11-05 107 views
23

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

编辑:标记化而使用:

strtok(string, " "); 

的代码是类似如下

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

您的示例将获得第一个标记,请查看gbjbaanb或我的答案,以了解正确的用法。 – 2008-11-05 20:02:20

+0

好的。现在我们正在某个地方。你认为你没有得到什么样的行为? – dmckee 2008-11-05 20:08:22

+0

你的代码是正确的,请让我们知道你的输入字符串和结果是什么。 – 2008-11-05 20:08:46

回答

0

当读strtok的文档,我看你需要一个NULL指针传递后的第一个“初始化“打电话。也许你没有那样做。只是猜测当然。

38

做这样的:

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

注:strtok修改字符串的tokenising,所以它不可能是一个const char*

32

这里的strtok使用的例子,请记住,strtok是破坏性的,它的输入字符串的(因此不能永远可以在一个字符串常量

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

基本上要注意的是使用这传递一个NULLstrtok第一个参数告诉它要得到它以前的标记化字符串的下一个标记。

3

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

#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; 
} 
6

的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); 
} 

注:因为它的分离 '文本' 的字符串被破坏。这可能不是优选的行为=)

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); 
} 
-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); 
    } 

}

你可以在博客中我的个人资料:)

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(),或一个我上面implmented,依靠static *char变量保存之间的最后一个分隔符的位置在处理多线程应用程序时应该格外小心。