teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

コードの説明を追加

2020/08/08 05:45

投稿

kazuma-s
kazuma-s

スコア8222

answer CHANGED
@@ -36,4 +36,152 @@
36
36
  words[1] = [助詞,ワ]
37
37
  words[2] = [名詞,ハレ]
38
38
  ```
39
- 「は」と「晴れ」が表示されなくなった理由が知りたいです。
39
+ 「は」と「晴れ」が表示されなくなった理由が知りたいです。
40
+
41
+ **追記**
42
+ char buf[] = "明日\t名詞,アシタ\nは\t助詞,ワ\n晴れ\t名詞,ハレ\n";
43
+ で、区切り文字が "\t\n" だけの場合のコードを説明します。
44
+
45
+ words[n] = strtok(buf, "\t\n"); で strtok は buf の先頭から、'\t' または
46
+ '\n' を探しに行き、buf[4] で '\t' を見つけ、そこに '\0' を書き込んで
47
+ "明日" という文字列を切り出します。そして、buf[5] のアドレスを内部に保存し、
48
+ buf[0] のアドレスを返します。
49
+
50
+ words[0] には "明日" の先頭アドレスが入ります。
51
+ その値は NULL ではないので、whileループの中に入ります。
52
+
53
+ strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に保存していた
54
+ buf[5] のところから、区切り文字の検索をし、buf[16] で '\n' を見つけます。
55
+ buf[16] に '\0' を書き込んで、"名詞,アシタ" という文字列を切り出します。
56
+ そして、buf[17]のアドレスを内部に保存し、buf[5]のアドレスを返します。
57
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
58
+
59
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
60
+ 保存していたbuf[17] のところから、区切り文字の検索をし、buf[19] で '\t' を
61
+ 見つけ、そこに '\0' を書き込んで "は" という文字列を切り出します。
62
+ そして、buf[20]のアドレスを内部に保存し、buf[17]を返します。
63
+ strtok の呼び出しもとでは返ってきた値を words[++n] に代入します。
64
+ words[1] には "は" の先頭アドレスが入ります。
65
+
66
+ while の先頭に戻ります。
67
+
68
+ words[1] の値は NULL ではないので、whileループの中に入ります。
69
+
70
+ strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に保存していた
71
+ buf[20] のところから、区切り文字の検索をし、buf[27] で '\n' を見つけます。
72
+ buf[27] に '\0' を書き込んで、"助詞,ワ" という文字列を切り出します。
73
+ そして、buf[28]のアドレスを内部に保存し、buf[20]のアドレスを返します。
74
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
75
+
76
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
77
+ 保存していたbuf[28] のところから、区切り文字の検索をし、buf[32] で '\t' を
78
+ 見つけ、そこに '\0' を書き込んで "晴れ" という文字列を切り出します。
79
+ そして、buf[33]のアドレスを内部に保存し、buf[28]を返します。
80
+ strtok の呼び出し元では返ってきた値を words[++n] に代入します。
81
+ words[2] には "晴れ" の先頭アドレスが入ります。
82
+
83
+ while の先頭に戻ります。
84
+
85
+ words[2] の値は NULL ではないので、whileループの中に入ります。
86
+
87
+ strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に保存していた
88
+ buf[33] のところから、区切り文字の検索をし、buf[42] で '\n' を見つけます。
89
+ buf[42] に '\0' を書き込んで、"名詞,ハレ" という文字列を切り出します。
90
+ そして、buf[43]のアドレスを内部に保存し、buf[33]のアドレスを返します。
91
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
92
+
93
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
94
+ 保存していたbuf[43] のところから、区切り文字の検索をしますが、buf[43] は
95
+ '\0' で文字列の最後です。文字列の切り出しはできず、strtok は NULL を返します。
96
+ strtok の呼び出し元では返ってきた値 NULL を words[++n] に代入します。
97
+ words[3] には NULL が入ります。
98
+
99
+ while の先頭に戻ります。
100
+ words[3] の値は NULL なので、whileループは終了します。これで
101
+ words[0] = "明日", words[1] = "は", words[2] = "晴れ", words[3] = NULL
102
+ となりました。
103
+
104
+ ----------------------------------------------
105
+ 今度は whileループの中の最初の strtok の呼び出しの区切り文字が "\t" の場合です。
106
+
107
+ words[n] = strtok(buf, "\t\n"); で strtok は buf の先頭から、'\t' または
108
+ '\n' を探しに行き、buf[4] で '\t' を見つけ、そこに '\0' を書き込んで
109
+ "明日" という文字列を切り出します。そして、buf[5] のアドレスを内部に保存し、
110
+ buf[0] のアドレスを返します。
111
+
112
+ words[0] には "明日" の先頭アドレスが入ります。
113
+ その値は NULL ではないので、whileループの中に入ります。
114
+
115
+ strtok(NULL, "\t"); で、NULL を渡された strtok は内部に保存していた
116
+ buf[5] のところから、区切り文字の検索をし、buf[19] で '\t' を見つけます。
117
+ buf[19] に '\0' を書き込んで、"名詞,アシタ\nは" という文字列を切り出します。
118
+ そして、buf[20]のアドレスを内部に保存し、buf[19]のアドレスを返します。
119
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
120
+
121
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
122
+ 保存していたbuf[20] のところから、区切り文字の検索をし、buf[27] で '\n' を
123
+ 見つけ、そこに '\0' を書き込んで "助詞,ワ" という文字列を切り出します。
124
+ そして、buf[28]のアドレスを内部に保存し、buf[20]を返します。
125
+ strtok の呼び出しもとでは返ってきた値を words[++n] に代入します。
126
+ words[1] には "助詞,ワ" の先頭アドレスが入ります。
127
+
128
+ while の先頭に戻ります。
129
+
130
+ words[1] の値は NULL ではないので、whileループの中に入ります。
131
+
132
+ strtok(NULL, "\t"); で、NULL を渡された strtok は内部に保存していた
133
+ buf[28] のところから、区切り文字の検索をし、buf[32] で '\t' を見つけます。
134
+ buf[32] に '\0' を書き込んで、"晴れ" という文字列を切り出します。
135
+ そして、buf[33]のアドレスを内部に保存し、buf[20]のアドレスを返します。
136
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
137
+
138
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
139
+ 保存していたbuf[33] のところから、区切り文字の検索をし、buf[42] で '\n' を
140
+ 見つけ、そこに '\0' を書き込んで "名詞,ハレ" という文字列を切り出します。
141
+ そして、buf[43]のアドレスを内部に保存し、buf[33]を返します。
142
+ strtok の呼び出し元では返ってきた値を words[++n] に代入します。
143
+ words[2] には "名詞,ハレ" の先頭アドレスが入ります。
144
+
145
+ while の先頭に戻ります。
146
+
147
+ words[2] の値は NULL ではないので、whileループの中に入ります。
148
+
149
+ strtok(NULL, "\t"); で、NULL を渡された strtok は内部に保存していた
150
+ buf[43] のところから、区切り文字の検索をしますが、buf[43] は '\0' なので、
151
+ 文字列の最後です。文字列の切り出しはできず、strtok は NULL を返します。
152
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
153
+
154
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
155
+ 保存していたbuf[43] のところから、区切り文字の検索をしますが、buf[43] は '\0'
156
+ なので、文字列の最後です。文字列の切り出しはできず、strtok は NULL を返します。
157
+ strtok の呼び出し元では返ってきた値 NULL を words[++n] に代入します。
158
+ words[3] には NULL が入ります。
159
+
160
+ while の先頭に戻ります。
161
+ words[3] の値は NULL なので、whileループは終了します。これで
162
+ words[0] = "明日", words[1] = "助詞,ワ", words[2] = "名詞,ハレ",
163
+ words[3] = NULL となりました。
164
+
165
+ ----------------------------------------------------
166
+
167
+ 要するに、全部 "\t\n" で区切ると、
168
+
169
+ "明日"
170
+ "名詞,アシタ"
171
+ "は"
172
+ "助詞,ワ"
173
+ "晴れ"
174
+ "名詞,ハレ"
175
+ NULL
176
+
177
+ になるものが、"\t\n", "\t", "\t\n" で区切ると
178
+
179
+ "明日"
180
+ "名詞,アシタ\nは"
181
+ "助詞,ワ"
182
+ "晴れ"
183
+ "名詞,ハレ"
184
+ NULL
185
+ NULL
186
+
187
+ になるということです。

1

コード修正

2020/08/08 05:45

投稿

kazuma-s
kazuma-s

スコア8222

answer CHANGED
@@ -19,21 +19,21 @@
19
19
  if (words[i] == NULL)
20
20
  printf("words[%d] = NULL\n", i);
21
21
  else
22
- printf("words[%d = [%s]\n", i, words[i]);
22
+ printf("words[%d] = [%s]\n", i, words[i]);
23
23
  }
24
24
  }
25
25
  ```
26
26
  実行結果
27
27
  ```plain text
28
- words[0 = [明日]
28
+ words[0] = [明日]
29
- words[1 = [は]
29
+ words[1] = [は]
30
- words[2 = [晴れ]
30
+ words[2] = [晴れ]
31
31
  ```
32
32
  上のコードの `strtok(NULL, "\t\n");` の `"\t\n"` を `"\t"` に変えると
33
33
  実行結果が次のように変わりました。
34
34
  ```plain text
35
- words[0 = [明日]
35
+ words[0] = [明日]
36
- words[1 = [助詞,ワ]
36
+ words[1] = [助詞,ワ]
37
- words[2 = [名詞,ハレ]
37
+ words[2] = [名詞,ハレ]
38
38
  ```
39
39
  「は」と「晴れ」が表示されなくなった理由が知りたいです。