首页 > 代码库 > strtok():“字符串分割”实用函数

strtok():“字符串分割”实用函数

    最近一直纠结于一个十分简单的问题:如何将一个字符串按标志分割开来?提出这个问题的初衷是自己在处理一个将命令行字符串转换为argc,argv格式的问题。

    尝试了很多种方法,最后觉得利用strtok()函数来实现是一个比较好的方法。首先进行strtok()函数的介绍。

char *strtok(string, control); 

    --- Tokenize string with delimiter in control.

   --- 通过分割符控制将字符串切片化。

Purpose:

    strtok considers the string to consist of a sequence of zero or more text tokens separated by spans of one or more control chars. The first call, with string specified, returns a pointer to the first char of the first token, and will write a null char into string immediately following the returned token. Subsequent calls with zero for the first argument (string) will work through the string until no tokens remain. The control string may be different from call to call. When no tokens remain in string a NULL pointer is returned. Remember the control chars with a bit map, one bit per ASCII char. The null char is always a control char.

   strtok认为字符串是由一个或多个文本切片组成,这些文本切片被一个或多个字符分隔开来。第一次调用时,返回第一个文本切片的第一个字符指针,同时将该文本切片后的控制字符设为NULL。此后的调用重复上面的操作,直到没有文本切片首字符返回(返回NULL)为止。这些控制字符可能在不同的调用中而不同。当字符串中没有文本切片时,则返回NULL。首次调用时,string指向要分解的字符串,之后再次调用要把string设成NULL。strtok在string中查找包含在delim中的字符并用NULL(‘/0‘)来替换,直到找遍整个字符串。

Entry:

   char *string --- string to tokenize, or NULL to get next token

   char *control --- string of characters to use as delimiters

Exit:

   Return pointer to first token in string, or if string was NULL, to next token. Return NULL when no more tokens remain.

Source Code:

#include <string.h>
static char *olds;

/* Parse S into tokens separated by characters in DELIM. If S is NULL, the last string strtok() was called with is used. For example:
char s[] = "-abc-=-def";
x = strtok(s, "-");        // x = "abc"
x = strtok(NULL, "-=");        // x = "def"
x = strtok(NULL, "=");        // x = NULL
// s = "abc\0=-def\0"
*/
char *strtok (s, delim)
   char *s;
   const char *delim;
{
   char *token;

   if (s == NULL)
       s = olds;

   /* Scan leading delimiters. */
   //strspn : 返回字符串s中第一个不在指定字符串delim中出现的字符下标
   //将指针移到第一个非delim中的字符的位置
   s += strspn (s, delim); 
   if (*s == '\0')
   {
      olds = s;
      return NULL;
   }

   /* Find the end of the token. */
   token = s;
   // char *strpbrk(const char *token, const char *delim);
   // 依次检验字符串s中字符,当被检验字符在字符串delim中也包含时,则停止检验,并返回该字符位置,空字符NULL不包括在内
   // 获取到delim中字符在字符串s中第一次出现的位置
   s = strpbrk (token, delim);
   if (s == NULL)
      /* This token finishes the string. */
      olds = __rawmemchr (token, '\0');
   else
   {
      /* Terminate the token and make OLDS point past it. */
      *s = '\0';
      olds = s + 1;
   }
   return token;
}
//其实现的核心方法在于static char *olds;的方法,用于保存前次处理后的字符串。

举例说明:

将字符串”Hello,Brief,Kitty”字符串分割为”Hello”、”Brief”、”Kitty”。

代码可以这样实现:

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

int main()
{
	int i=0;
	char str[] = "Hello,Brief,Kitty";
	char *token[3];
	char *buf = str;
	while((token[i] = strtok(buf, ",")) != NULL)
	{
		i++;
		buf = NULL;
	}
	for(i=0;i<3;i++)
		printf("%s\n",token[i]);
	return 0;
}
现在,基于一般的命令行处理,现有以下代码:

#include <stdio.h>
#include <string.h>
#define MAXLEN 1024
#define MAXCOUNT 64

int main()
{
	int i,argc=0;
	char *argv[MAXCOUNT],*buf;
	char cmdline[MAXLEN];
	printf("Please input the command line to be parsed:\n");
	if((buf=fgets(cmdline,MAXLEN,stdin))==NULL)
		printf("input error!\n");
	while((argv[argc] = strtok(buf, " ")) != NULL)
	{
		argc++;
		buf = NULL;
	}
	printf("There is %d arguments:\n",argc);
	for(i=0;i<argc;i++)
		printf("%s\n",argv[i]);
	return 0;
}
结果为:

     

strtok():“字符串分割”实用函数