strtok と メモリダンプ

  トークン



C 言語における「トークン」とは、コンパイラが認識する基本要素であり、コンパイラが認識できる最小単位のテキストです。もう少し具体的に言うと、キーワード、識別子、定数、リテラル文字列、演算子 の事です。さらに、[]、{ }、( )、カンマもトークンです



  strtok



トークンとトークンの間には、デリミタ(区切り文字) が存在します。それによって、トークン同士が独立できるわけですから、必ず必要なものとなります。C 言語のソースコード上のデリミタは、「空白文字」ですが、任意のデリミタによって文字列をトークンに分解する作業を行なうのがライブラリ関数の strtok です

例えば、"ABC,DEF" という文字列をカンマで分解するには以下のようにします

  
#include "stdafx.h"
#include <string.h>

int main(int argc, char* argv[])
{

	char szBuffer[128];
	char *pszToken;

	strcpy( szBuffer, "ABC,DEF" );

	pszToken = strtok( szBuffer, "," );
	printf( "%s\n", pszToken );
	pszToken = strtok( NULL, "," );
	printf( "%s\n", pszToken );

	return 0;

}
  

strtok は初回の呼び出し時に、トークンを取り出す文字列の先頭アドレスを渡す必要があります。
2回目以降には NULL を渡すのが仕様ですが、要するにこの NULL は引数の省略を意味します。

strtok は、トークンが無くなると NULL を返します。
ですから、トークンの数が解らない文字列に対しては以下のように記述します

  
	strcpy( szBuffer, "ABC,DEF,GHI,JKL,MNO" );

	pszToken = strtok( szBuffer, "," );
	while( pszToken != NULL ) {
		printf( "%s\n", pszToken );
		pszToken = strtok( NULL, "," );
	}
  



  strtok の欠点

論より証拠。以下のコードを実行して下さい

  
	strcpy( szBuffer, "ABC,,,,MNO" );

	pszToken = strtok( szBuffer, "," );
	while( pszToken != NULL ) {
		printf( "%s\n", pszToken );
		pszToken = strtok( NULL, "," );
	}
  

つまり、連続しデリミタは、一つのデリミタとして扱われます。C 言語のソースコードの解析にはそれで良いでしょうが、我々が通常扱う「データ」では、,, は 3つの省略されたデータを意味します



  strtok の実行結果のメモリダンプ

  
	strcpy( szBuffer, "ABC,DEF,GHI,JKL,MNO" );

	pszToken = strtok( szBuffer, "," );
	while( pszToken != NULL ) {
		printf( "%s\n", pszToken );
		pszToken = strtok( NULL, "," );
	}

	int i,j;

	for( i = 0; i < 128; i += 16 ) {
		for( j = i; j < i + 16; j++ ) {
			printf( "%02x ", 0x000000ff & szBuffer[j] );
		}
		printf( "\n" );
	}
  

この結果より、strtok に渡された文字列は、strtok によってデリミタが 0x00 に変更されている事が解ります。つまり、ちょっとしたトークン分解には使えますが、前出の欠点も有るので、実際のデータ分解には「使えない」という事になります。このようなトークン分解の結果は、配列で戻すのが最も使いやすいのが通常です。実際はユーザ関数を作成して使用する事になります



  Shift JIS(漢字) を使用する場合

strtok では無く、_mbstok を使用します

以下の例では、デリミタに 0x5c を使用し、0x5c を含む漢字をトークンとしています

  
#include "stdafx.h"
#include <mbstring.h>
#include <string.h>

int main(int argc, char* argv[])
{

	char szBuffer[128];
	unsigned char *pszToken;

	strcpy( szBuffer, "ABC\\表示\\MNO" );

	pszToken = _mbstok( (unsigned char *)szBuffer, (const unsigned char *)"\\" );
	while( pszToken != NULL ) {
		printf( "%s\n", pszToken );
		pszToken = _mbstok( NULL, (const unsigned char *)"\\" );
	}

	int i,j;

	for( i = 0; i < 128; i += 16 ) {
		for( j = i; j < i + 16; j++ ) {
			printf( "%02x ", 0x000000ff & szBuffer[j] );
		}
		printf( "\n" );
	}

	return 0;

}
  










  infoboard   管理者用   
このエントリーをはてなブックマークに追加





フリーフォントWEBサービス
SQLの窓WEBサービス

SQLの窓フリーソフト

素材

一般WEBツールリンク

SQLの窓

フリーソフト

JSライブラリ