閱讀117 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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;
}
結果為:

     

最後更新:2017-04-03 05:40:17

  上一篇:go 堆排序+代碼實現
  下一篇:go Qt Creator的下載、安裝及試用