回答編集履歴

1 d

tiitoi

tiitoi score 13718

2018/10/25 19:01  投稿

プログラム自体は動かせていませんが、文字列分割の部分だけコメントします。
strtok() の仕様は少々複雑です。
```
char *strtok(char *s1, const char *s2);
```
> 最初の呼び出しでは s1 には分解対象の文字列を指定します。トークンがあれば、strtok() はトークンへのポインタを返却します。
> 2回目以降の呼び出しでは s1 に NULL を指定します。分解できるトークンがあるうちは、strtok() はトークンへのポインタを返却します。
> トークンがなくなると strtok() は NULL を返却します。
> strtok() はトークンへのポインタを返却しながら、分解対象文字列 s1 中の区切り文字に空文字('\0')を埋めていきます。ですから、s1 に文字列リテラルや変更されては困る文字列を指定してはいけません。
[引用元](http://www9.plala.or.jp/sgwr-t/lib/strtok.html)
なので、以下のようにするべきではないでしょうか?
```c
#include <stdio.h>
#include <string.h>
int main()
{
   char str[] = "file1.txt,file2.txt,file3.txt";
   char *filename = strtok(str, ",");
   // 1回目の呼び出しでは、トークン、つまり先頭のポインタを返す。
   // 見つけた区切り文字は\0で置き換えられるので、filename = "file1.txt" となっている。
   do {
       printf("%s\n", filename);
   // 2回目以降の呼び出しのときは、第一引数は NULL を指定する。
   // filename = "file2.txt" となっている。
   // その次の呼び出した場合、
   // filename = "file3.txt" となっている。
   // その次の呼び出した場合、もうトークンが残ってないので NULL を返す。
   // よ  
   } while (filename = strtok(NULL, ","));
}
```
```
file1.txt
file2.txt
file3.txt
```
記載のコードですと、最後の呼び出しの際に *NULL となり、null pointer に対する de-reference 操作となり、C言語では、動作未定義なので危険です。
```
token = *strtok(filename, ",");
do {
   // 処理
} while (token == *strtok(NULL, ","));
```

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る