マルチバイト文字列を1文字ずつに分割する

調べ方が悪いのかそんな事やろうとする人がいないのか知らないけど、見つからなかったから自分で作った。
文字コードUTF-8限定。
 
mallocとreallocを使ってメモリを動的に確保した。
「文字列の配列」を作るのかと思ってたけど、動的に生成するなら「(文字列の1バイト目の)ポインタの配列」を作るっぽい。
で、関数の引数は「(文字列の1バイト目の)ポインタの配列のポインタ」か。
メモリの事はよく解らないけど、これでいいのかな。
文字列用にmallocしたメモリもfreeするべきなのかな。
 

ソース

#include <stdio.h>
#include <stdlib.h>

int str_split(const char *str, char*** dest)
{
	char **arr, **tmp;
	int i = 0;
	int size = 100;

	arr = (char**)malloc(size * sizeof(char*));

	while (*str != '\0') {
		int code = (unsigned char)*str;
		if (code < 0x80) {
			arr[i] = (char*)malloc(2 * sizeof(char));
			sprintf(arr[i], "%c", *str);
			i++;
			str += 1;
		} else if (code < 0xC0) {
			str += 1;
		} else if (code < 0xE0) {
			arr[i] = (char*)malloc(3 * sizeof(char));
			sprintf(arr[i], "%c%c", *str, *(str+1));
			i++;
			str += 2;
		} else if (code < 0xF0) {
			arr[i] = (char*)malloc(4 * sizeof(char));
			sprintf(arr[i], "%c%c%c", *str, *(str+1), *(str+2));
			i++;
			str += 3;
		} else {
			arr[i] = (char*)malloc(5 * sizeof(char));
			sprintf(arr[i], "%c%c%c%c", *str, *(str+1), *(str+2), *(str+3));
			i++;
			str += 4;
		}
		if (size <= i) {
			size += 100;
			if ((tmp = (char**)realloc(arr, size * sizeof(char*))) == NULL) {
				printf("realloc error!!\n");
				free(arr);
				exit(EXIT_FAILURE);
			} else {
				arr = tmp;
			}
		}
	}
	arr[i] = NULL;

	*dest = arr;
	return i;
}


int main(char *args)
{
	char** char_arr;
	int i, len;

	len = str_split("ポインタ(pointer)とは、あるオブジェクトがなんらかの論理的位置情報でアクセスできるとき、その位置を表現する変数の事をいう。有名な例としてはC/C++でのメモリアドレスを表すポインタが挙げられる。類似の概念に参照(reference)があるが、ポインタが演算により無効な位置を作り出せるのに対し、参照では元々存在するオブジェクトを指し示す事しかできない。このため一般には参照の方がより安全な操作であるとされる。ただし、参照先のオブジェクトがいつまで有効な状態であるかはプログラムに依存するので、無効なものを指し得ないというわけではない。(参照透過性)", &char_arr);

	for (i=0; i<len; i++) {
		printf("%s\n", char_arr[i]);
	}
	free(char_arr);

	return 0;
}

 

参考URL

ポインタ配列にまつわる話
http://sometime.minidns.net/programming/c/pointer_array.html