もうすぐあるらしい学科のプログラミングテストとやらに備えて、少しC言語を書いてみる。書いたのはPerlやRubyやPythonでは実装されている、split関数*1っぽいもの。
結局、strtokのラッパー関数みたいになってしまった。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STR 256
#define MAX_WORD 128
// strtokと同じ引数をとる
// 文字列さすポインタを要素とする配列を返す
char **split(char *str, char *sep)
{
char *word = NULL;
char *str_work = NULL;
int last = 0;
//うけとった文字列のコピーを作成
str_work = (char *)malloc(sizeof(char) * (strlen(str) + 1));
strcpy(str_work, str);
//文字列のポインタを保持する配列
char **results = (char **)malloc(sizeof(char *) * MAX_WORD);
//strtokで得たトークンのポインタを配列に代入
last = 0;
for(word = strtok(str_work,sep); word; word = strtok(NULL,sep),last++) {
results[last] = word;
}
results[last] = NULL;
return results;
}
// splitで作成した配列のメモリを解放する
void split_free(char **words)
{
//words[0]をfreeすればすべてのトークンのメモリは解放される?
free(words[0]);
free(words);
}
int main(int argc, char *argv[])
{
int i = 0;
char str[MAX_STR] = "Hello-my-world"; //splitする前の文字列
char *sep = "-"; //セパレータ
char **words = NULL;
//splitされたトークンを保持する配列を得る
words = split(str, sep);
for (i = 0; words[i] != NULL; i++) {
printf("%2d: %s\n", i,words[i]);
}
split_free(words);
words = NULL;
return 0;
}splitが返す配列にはトークン文字列が一つづつ確保されているので、扱いやすい。これを、tokという名前でコンパイルして動作させると、
$ ./tok 0: Hello 1: my 2: world
となります。
うーん、やはりメモリを解放するのに気を使わなきゃダメなのはめんどうだなぁ。ガベージコレクションマンセー。えー、これを、Perlで書くと、
$str = 'Hello-my-world';
@words = split(/-/,$str);
$count = 0;
foreach (@words) {
printf "%2d: $_\n", $count;
$count += 1;
}となるね。短いね。RubyやPythonだと…。悲しくなるのでもういいや。Lightweight Languageマンセー。

- 作者: B.W.カーニハン,D.M.リッチー,石田晴久
- 出版社/メーカー: 共立出版
- 発売日: 1989/06/15
- メディア: 単行本
- 購入: 28人 クリック: 721回
- この商品を含むブログ (200件) を見る
*1:もしくはメソッド