题
如何安全解析制表符分隔符字符串?例如:测试 bla-bla-bla 2332 ?
解决方案
strtok()
是用于解析任意字符串的分隔符的标准功能。它,然而,不是线程安全的。你选择的C库可能有一个线程安全的变体。
另一个标准兼容的方式(只是写这时,它是的未测试强>):
#include <string.h>
#include <stdio.h>
int main()
{
char string[] = "foo\tbar\tbaz";
char * start = string;
char * end;
while ( ( end = strchr( start, '\t' ) ) != NULL )
{
// %s prints a number of characters, * takes number from stack
// (your token is not zero-terminated!)
printf( "%.*s\n", end - start, start );
start = end + 1;
}
// start points to last token, zero-terminated
printf( "%s", start );
return 0;
}
其他提示
使用 strtok_r 而不是 strtok(如果可用)。它有类似的用法,除了它是可重入的,而且它 才不是 像 strtok 一样修改字符串。[编辑: 其实我说错了。正如 Christoph 指出的那样,strtok_r 确实用 '\0' 替换了分隔符。因此,如果要保留原始字符串,则应该对字符串的副本进行操作。但它比 strtok 更可取,因为它是可重入且线程安全的]
strtok 会保留修改后的原始字符串。它将分隔符替换为“\0”。如果您的字符串恰好是一个常量,存储在只读内存中(某些编译器会这样做),您实际上可能会遇到访问冲突。
这strtok()
使用string.h
。
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "test\tbla-bla-bla\t2332";
char * pch;
pch = strtok (str," \t");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " \t");
}
return 0;
}
又一版本;这一个逻辑分离成一个新的功能
#include <stdio.h>
static _Bool next_token(const char **start, const char **end)
{
if(!*end) *end = *start; // first call
else if(!**end) // check for terminating zero
return 0;
else *start = ++*end; // skip tab
// advance to terminating zero or next tab
while(**end && **end != '\t')
++*end;
return 1;
}
int main(void)
{
const char *string = "foo\tbar\tbaz";
const char *start = string;
const char *end = NULL; // NULL value indicates first call
while(next_token(&start, &end))
{
// print substring [start,end[
printf("%.*s\n", end - start, start);
}
return 0;
}
如果你需要一个二进制安全的方式来标记特定字符串:
#include <string.h>
#include <stdio.h>
void tokenize(const char *str, const char delim, const size_t size)
{
const char *start = str, *next;
const char *end = str + size;
while (start < end) {
if ((next = memchr(start, delim, end - start)) == NULL) {
next = end;
}
printf("%.*s\n", next - start, start);
start = next + 1;
}
}
int main(void)
{
char str[] = "test\tbla-bla-bla\t2332";
int len = strlen(str);
tokenize(str, '\t', len);
return 0;
}
不隶属于 StackOverflow