C语言中的标记化字符串
我一直在尝试使用空格作为分隔符来标记字符串,但它不起作用。有人对它为什么不起作用有什么建议吗 编辑:标记化使用:C语言中的标记化字符串,c,string,tokenize,C,String,Tokenize,我一直在尝试使用空格作为分隔符来标记字符串,但它不起作用。有人对它为什么不起作用有什么建议吗 编辑:标记化使用: strtok(string, " "); 代码如下所示 pch = strtok (str," "); while (pch != NULL) { printf ("%s\n",pch); pch = strtok (NULL, " "); } 在阅读strtok文档时,我发现您需要在第一次“初始化”调用之后传入一个空指针。也许你没那么做。当然只是猜测。这样做: char
strtok(string, " ");
代码如下所示
pch = strtok (str," ");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ");
}
在阅读strtok文档时,我发现您需要在第一次“初始化”调用之后传入一个空指针。也许你没那么做。当然只是猜测。这样做:
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*
这里有一个strtok
用法的示例,请记住strtok
对其输入字符串具有破坏性(因此不能用于字符串常量)
char *p = strtok(str, " ");
while(p != NULL) {
printf("%s\n", p);
p = strtok(NULL, " ");
}
基本上需要注意的是,将
NULL
作为第一个参数传递给strtok
会告诉它从先前标记的字符串中获取下一个标记。可以通过引入额外变量简化代码
#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;
}
#包括
#包括
int main()
{
char str[100],*s=str,*t=NULL;
strcpy(str,一个空格分隔的字符串);
而((t=strtok(s,“”)!=NULL){
s=零;
printf(“:%s:\n”,t);
}
返回0;
}
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);
}
注意:“文本”字符串在被分离时会被销毁。这可能不是首选行为=)我制作了一些字符串函数,以便使用尽可能少的指针来分割值,因为此代码打算在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);
}
#包括
#包括
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”;
int findchar(char*string,int Start,char C){
while((string[Start]!=0)){Start++;if(string[Start]==C)返回Start;}
返回-1;
}
int findcharn(字符*字符串,整数倍,字符C){
int i=0,pos=0,fnd=0;
而(i<次){
fnd=findchar(字符串,位置,C);
如果(fnd<0)返回-1;
如果(fnd>0)pos=fnd;
i++;
}
返回fnd;
}
void mid(字符*输入,字符*输出,整数开始,整数结束){
int i=0;
int size=结束-开始;
对于(i=0;i
}
您可以在我的个人资料中提到的博客上阅读详细分析:)这里有另一个
strtok()
实现,它能够识别连续的分隔符(标准库的strtok()
没有此功能)
该函数是BSD许可字符串库的一部分,名为。非常欢迎您的贡献:)
char*zstring\u strok(char*str,const char*delim){
static char*static_str=0;/*var存储最后一个地址*/
int index=0,strlength=0;/*用于索引的整数*/
int found=0;/*检查是否找到delim*/
/*分隔符不能为空
*如果没有更多的字符,也返回NULL
*/
if(delim==0 | |(str==0&&static_-str==0))
返回0;
如果(str==0)
str=静态_str;
/*获取字符串的长度*/
while(str[strlength])
strlength++;
/*发现delim的第一次出现*/
对于(index=0;indexIn事实上,如果你看一下现代的strtok实现,它们倾向于使用线程本地存储(MSVC已经多年这么做了),所以它们是线程安全的。这仍然是一个古老的函数,我会避免,虽然…strtok_r是strtok的线程安全版本,我同意第一段,但后面的句子很糟糕。scanf
很难正确使用,如您的示例所示;您忘记传递大小(%255s
)。如何strtok()
know,何时从之前标记的字符串中获取下一个标记?对我来说,它看起来像strtok()
应该标记NULL
值。我预计会出现错误。strtok
有一个内部状态变量跟踪标记化的字符串。当您将NULL
传递给它时,strtok
将继续使用此状态变量。当您传递非NULL值时,状态变量会重置。换句话说:传递NULL
表示“继续标记相同的字符串”。谢谢你的澄清。但不管怎样,这似乎是一个糟糕的设计。你是对的,这就是为什么许多实现提供了strtok\u r
,而atr至少提供了一种以线程安全的方式使用它的方法。难道不应该先为char*p
分配一些空间吗?strtok返回的指针指向哪里?在我看来只是一个随机的地方mory?哦…它是否指向给定字符串中的某个位置?您是在使用strtok还是您自己开发的东西?如果您是在使用strtok,您是在尝试在常量字符串上执行它吗?您的示例将获得第一个标记,请查看gbjbaanb或我的答案以获得正确的用法。好的。现在我们已经取得了一些进展。您希望自己是什么行为没有得到?顺便说一句,kombo。许多在帮助台工作或教书的人把“它不起作用”这句话看作是妈妈
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);
}
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;
}