KZK13さん、あなたは質問がメチャクチャ下手です。
次のように質問すれば誤解が無いと思いませんか?
C
1#include <stdio.h>
2#include <string.h>
3
4int main()
5{
6 char buf[] = "明日\t名詞,アシタ\nは\t助詞,ワ\n晴れ\t名詞,ハレ\n";
7 char *words[100];
8 int n = 0;
9 words[n] = strtok(buf, "\t\n");
10 while (n < 100 && words[n]) {
11 strtok(NULL, "\t\n");
12 words[++n] = strtok(NULL, "\t\n");
13 }
14 for (int i = 0; i < n; i++) {
15 if (words[i] == NULL)
16 printf("words[%d] = NULL\n", i);
17 else
18 printf("words[%d] = [%s]\n", i, words[i]);
19 }
20}
実行結果
plain
1words[0] = [明日]
2words[1] = [は]
3words[2] = [晴れ]
上のコードの strtok(NULL, "\t\n");
の "\t\n"
を "\t"
に変えると
実行結果が次のように変わりました。
plain
1words[0] = [明日]
2words[1] = [助詞,ワ]
3words[2] = [名詞,ハレ]
「は」と「晴れ」が表示されなくなった理由が知りたいです。
追記
char buf[] = "明日\t名詞,アシタ\nは\t助詞,ワ\n晴れ\t名詞,ハレ\n";
で、区切り文字が "\t\n" だけの場合のコードを説明します。
words[n] = strtok(buf, "\t\n"); で strtok は buf の先頭から、'\t' または
'\n' を探しに行き、buf[4] で '\t' を見つけ、そこに '\0' を書き込んで
"明日" という文字列を切り出します。そして、buf[5] のアドレスを内部に保存し、
buf[0] のアドレスを返します。
words[0] には "明日" の先頭アドレスが入ります。
その値は NULL ではないので、whileループの中に入ります。
strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に保存していた
buf[5] のところから、区切り文字の検索をし、buf[16] で '\n' を見つけます。
buf[16] に '\0' を書き込んで、"名詞,アシタ" という文字列を切り出します。
そして、buf[17]のアドレスを内部に保存し、buf[5]のアドレスを返します。
strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
保存していたbuf[17] のところから、区切り文字の検索をし、buf[19] で '\t' を
見つけ、そこに '\0' を書き込んで "は" という文字列を切り出します。
そして、buf[20]のアドレスを内部に保存し、buf[17]を返します。
strtok の呼び出しもとでは返ってきた値を words[++n] に代入します。
words[1] には "は" の先頭アドレスが入ります。
while の先頭に戻ります。
words[1] の値は NULL ではないので、whileループの中に入ります。
strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に保存していた
buf[20] のところから、区切り文字の検索をし、buf[27] で '\n' を見つけます。
buf[27] に '\0' を書き込んで、"助詞,ワ" という文字列を切り出します。
そして、buf[28]のアドレスを内部に保存し、buf[20]のアドレスを返します。
strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
保存していたbuf[28] のところから、区切り文字の検索をし、buf[32] で '\t' を
見つけ、そこに '\0' を書き込んで "晴れ" という文字列を切り出します。
そして、buf[33]のアドレスを内部に保存し、buf[28]を返します。
strtok の呼び出し元では返ってきた値を words[++n] に代入します。
words[2] には "晴れ" の先頭アドレスが入ります。
while の先頭に戻ります。
words[2] の値は NULL ではないので、whileループの中に入ります。
strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に保存していた
buf[33] のところから、区切り文字の検索をし、buf[42] で '\n' を見つけます。
buf[42] に '\0' を書き込んで、"名詞,ハレ" という文字列を切り出します。
そして、buf[43]のアドレスを内部に保存し、buf[33]のアドレスを返します。
strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
保存していたbuf[43] のところから、区切り文字の検索をしますが、buf[43] は
'\0' で文字列の最後です。文字列の切り出しはできず、strtok は NULL を返します。
strtok の呼び出し元では返ってきた値 NULL を words[++n] に代入します。
words[3] には NULL が入ります。
while の先頭に戻ります。
words[3] の値は NULL なので、whileループは終了します。これで
words[0] = "明日", words[1] = "は", words[2] = "晴れ", words[3] = NULL
となりました。
今度は whileループの中の最初の strtok の呼び出しの区切り文字が "\t" の場合です。
words[n] = strtok(buf, "\t\n"); で strtok は buf の先頭から、'\t' または
'\n' を探しに行き、buf[4] で '\t' を見つけ、そこに '\0' を書き込んで
"明日" という文字列を切り出します。そして、buf[5] のアドレスを内部に保存し、
buf[0] のアドレスを返します。
words[0] には "明日" の先頭アドレスが入ります。
その値は NULL ではないので、whileループの中に入ります。
strtok(NULL, "\t"); で、NULL を渡された strtok は内部に保存していた
buf[5] のところから、区切り文字の検索をし、buf[19] で '\t' を見つけます。
buf[19] に '\0' を書き込んで、"名詞,アシタ\nは" という文字列を切り出します。
そして、buf[20]のアドレスを内部に保存し、buf[19]のアドレスを返します。
strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
保存していたbuf[20] のところから、区切り文字の検索をし、buf[27] で '\n' を
見つけ、そこに '\0' を書き込んで "助詞,ワ" という文字列を切り出します。
そして、buf[28]のアドレスを内部に保存し、buf[20]を返します。
strtok の呼び出しもとでは返ってきた値を words[++n] に代入します。
words[1] には "助詞,ワ" の先頭アドレスが入ります。
while の先頭に戻ります。
words[1] の値は NULL ではないので、whileループの中に入ります。
strtok(NULL, "\t"); で、NULL を渡された strtok は内部に保存していた
buf[28] のところから、区切り文字の検索をし、buf[32] で '\t' を見つけます。
buf[32] に '\0' を書き込んで、"晴れ" という文字列を切り出します。
そして、buf[33]のアドレスを内部に保存し、buf[20]のアドレスを返します。
strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
保存していたbuf[33] のところから、区切り文字の検索をし、buf[42] で '\n' を
見つけ、そこに '\0' を書き込んで "名詞,ハレ" という文字列を切り出します。
そして、buf[43]のアドレスを内部に保存し、buf[33]を返します。
strtok の呼び出し元では返ってきた値を words[++n] に代入します。
words[2] には "名詞,ハレ" の先頭アドレスが入ります。
while の先頭に戻ります。
words[2] の値は NULL ではないので、whileループの中に入ります。
strtok(NULL, "\t"); で、NULL を渡された strtok は内部に保存していた
buf[43] のところから、区切り文字の検索をしますが、buf[43] は '\0' なので、
文字列の最後です。文字列の切り出しはできず、strtok は NULL を返します。
strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
保存していたbuf[43] のところから、区切り文字の検索をしますが、buf[43] は '\0'
なので、文字列の最後です。文字列の切り出しはできず、strtok は NULL を返します。
strtok の呼び出し元では返ってきた値 NULL を words[++n] に代入します。
words[3] には NULL が入ります。
while の先頭に戻ります。
words[3] の値は NULL なので、whileループは終了します。これで
words[0] = "明日", words[1] = "助詞,ワ", words[2] = "名詞,ハレ",
words[3] = NULL となりました。
要するに、全部 "\t\n" で区切ると、
"明日"
"名詞,アシタ"
"は"
"助詞,ワ"
"晴れ"
"名詞,ハレ"
NULL
になるものが、"\t\n", "\t", "\t\n" で区切ると
"明日"
"名詞,アシタ\nは"
"助詞,ワ"
"晴れ"
"名詞,ハレ"
NULL
NULL
になるということです。