回答編集履歴

2

コードの説明を追加

2020/08/08 05:45

投稿

kazuma-s
kazuma-s

スコア8224

test CHANGED
@@ -75,3 +75,299 @@
75
75
  ```
76
76
 
77
77
  「は」と「晴れ」が表示されなくなった理由が知りたいです。
78
+
79
+
80
+
81
+ **追記**
82
+
83
+ char buf[] = "明日\t名詞,アシタ\nは\t助詞,ワ\n晴れ\t名詞,ハレ\n";
84
+
85
+ で、区切り文字が "\t\n" だけの場合のコードを説明します。
86
+
87
+
88
+
89
+ words[n] = strtok(buf, "\t\n"); で strtok は buf の先頭から、'\t' または
90
+
91
+ '\n' を探しに行き、buf[4] で '\t' を見つけ、そこに '\0' を書き込んで
92
+
93
+ "明日" という文字列を切り出します。そして、buf[5] のアドレスを内部に保存し、
94
+
95
+ buf[0] のアドレスを返します。
96
+
97
+
98
+
99
+ words[0] には "明日" の先頭アドレスが入ります。
100
+
101
+ その値は NULL ではないので、whileループの中に入ります。
102
+
103
+
104
+
105
+ strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に保存していた
106
+
107
+ buf[5] のところから、区切り文字の検索をし、buf[16] で '\n' を見つけます。
108
+
109
+ buf[16] に '\0' を書き込んで、"名詞,アシタ" という文字列を切り出します。
110
+
111
+ そして、buf[17]のアドレスを内部に保存し、buf[5]のアドレスを返します。
112
+
113
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
114
+
115
+
116
+
117
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
118
+
119
+ 保存していたbuf[17] のところから、区切り文字の検索をし、buf[19] で '\t' を
120
+
121
+ 見つけ、そこに '\0' を書き込んで "は" という文字列を切り出します。
122
+
123
+ そして、buf[20]のアドレスを内部に保存し、buf[17]を返します。
124
+
125
+ strtok の呼び出しもとでは返ってきた値を words[++n] に代入します。
126
+
127
+ words[1] には "は" の先頭アドレスが入ります。
128
+
129
+
130
+
131
+ while の先頭に戻ります。
132
+
133
+
134
+
135
+ words[1] の値は NULL ではないので、whileループの中に入ります。
136
+
137
+
138
+
139
+ strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に保存していた
140
+
141
+ buf[20] のところから、区切り文字の検索をし、buf[27] で '\n' を見つけます。
142
+
143
+ buf[27] に '\0' を書き込んで、"助詞,ワ" という文字列を切り出します。
144
+
145
+ そして、buf[28]のアドレスを内部に保存し、buf[20]のアドレスを返します。
146
+
147
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
148
+
149
+
150
+
151
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
152
+
153
+ 保存していたbuf[28] のところから、区切り文字の検索をし、buf[32] で '\t' を
154
+
155
+ 見つけ、そこに '\0' を書き込んで "晴れ" という文字列を切り出します。
156
+
157
+ そして、buf[33]のアドレスを内部に保存し、buf[28]を返します。
158
+
159
+ strtok の呼び出し元では返ってきた値を words[++n] に代入します。
160
+
161
+ words[2] には "晴れ" の先頭アドレスが入ります。
162
+
163
+
164
+
165
+ while の先頭に戻ります。
166
+
167
+
168
+
169
+ words[2] の値は NULL ではないので、whileループの中に入ります。
170
+
171
+
172
+
173
+ strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に保存していた
174
+
175
+ buf[33] のところから、区切り文字の検索をし、buf[42] で '\n' を見つけます。
176
+
177
+ buf[42] に '\0' を書き込んで、"名詞,ハレ" という文字列を切り出します。
178
+
179
+ そして、buf[43]のアドレスを内部に保存し、buf[33]のアドレスを返します。
180
+
181
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
182
+
183
+
184
+
185
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
186
+
187
+ 保存していたbuf[43] のところから、区切り文字の検索をしますが、buf[43] は
188
+
189
+ '\0' で文字列の最後です。文字列の切り出しはできず、strtok は NULL を返します。
190
+
191
+ strtok の呼び出し元では返ってきた値 NULL を words[++n] に代入します。
192
+
193
+ words[3] には NULL が入ります。
194
+
195
+
196
+
197
+ while の先頭に戻ります。
198
+
199
+ words[3] の値は NULL なので、whileループは終了します。これで
200
+
201
+ words[0] = "明日", words[1] = "は", words[2] = "晴れ", words[3] = NULL
202
+
203
+ となりました。
204
+
205
+
206
+
207
+ ----------------------------------------------
208
+
209
+ 今度は whileループの中の最初の strtok の呼び出しの区切り文字が "\t" の場合です。
210
+
211
+
212
+
213
+ words[n] = strtok(buf, "\t\n"); で strtok は buf の先頭から、'\t' または
214
+
215
+ '\n' を探しに行き、buf[4] で '\t' を見つけ、そこに '\0' を書き込んで
216
+
217
+ "明日" という文字列を切り出します。そして、buf[5] のアドレスを内部に保存し、
218
+
219
+ buf[0] のアドレスを返します。
220
+
221
+
222
+
223
+ words[0] には "明日" の先頭アドレスが入ります。
224
+
225
+ その値は NULL ではないので、whileループの中に入ります。
226
+
227
+
228
+
229
+ strtok(NULL, "\t"); で、NULL を渡された strtok は内部に保存していた
230
+
231
+ buf[5] のところから、区切り文字の検索をし、buf[19] で '\t' を見つけます。
232
+
233
+ buf[19] に '\0' を書き込んで、"名詞,アシタ\nは" という文字列を切り出します。
234
+
235
+ そして、buf[20]のアドレスを内部に保存し、buf[19]のアドレスを返します。
236
+
237
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
238
+
239
+
240
+
241
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
242
+
243
+ 保存していたbuf[20] のところから、区切り文字の検索をし、buf[27] で '\n' を
244
+
245
+ 見つけ、そこに '\0' を書き込んで "助詞,ワ" という文字列を切り出します。
246
+
247
+ そして、buf[28]のアドレスを内部に保存し、buf[20]を返します。
248
+
249
+ strtok の呼び出しもとでは返ってきた値を words[++n] に代入します。
250
+
251
+ words[1] には "助詞,ワ" の先頭アドレスが入ります。
252
+
253
+
254
+
255
+ while の先頭に戻ります。
256
+
257
+
258
+
259
+ words[1] の値は NULL ではないので、whileループの中に入ります。
260
+
261
+
262
+
263
+ strtok(NULL, "\t"); で、NULL を渡された strtok は内部に保存していた
264
+
265
+ buf[28] のところから、区切り文字の検索をし、buf[32] で '\t' を見つけます。
266
+
267
+ buf[32] に '\0' を書き込んで、"晴れ" という文字列を切り出します。
268
+
269
+ そして、buf[33]のアドレスを内部に保存し、buf[20]のアドレスを返します。
270
+
271
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
272
+
273
+
274
+
275
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
276
+
277
+ 保存していたbuf[33] のところから、区切り文字の検索をし、buf[42] で '\n' を
278
+
279
+ 見つけ、そこに '\0' を書き込んで "名詞,ハレ" という文字列を切り出します。
280
+
281
+ そして、buf[43]のアドレスを内部に保存し、buf[33]を返します。
282
+
283
+ strtok の呼び出し元では返ってきた値を words[++n] に代入します。
284
+
285
+ words[2] には "名詞,ハレ" の先頭アドレスが入ります。
286
+
287
+
288
+
289
+ while の先頭に戻ります。
290
+
291
+
292
+
293
+ words[2] の値は NULL ではないので、whileループの中に入ります。
294
+
295
+
296
+
297
+ strtok(NULL, "\t"); で、NULL を渡された strtok は内部に保存していた
298
+
299
+ buf[43] のところから、区切り文字の検索をしますが、buf[43] は '\0' なので、
300
+
301
+ 文字列の最後です。文字列の切り出しはできず、strtok は NULL を返します。
302
+
303
+ strtok の呼び出し元では返ってきた値をどこにも代入せず無視します。
304
+
305
+
306
+
307
+ words[++n] = strtok(NULL, "\t\n"); で、NULL を渡された strtok は内部に
308
+
309
+ 保存していたbuf[43] のところから、区切り文字の検索をしますが、buf[43] は '\0'
310
+
311
+ なので、文字列の最後です。文字列の切り出しはできず、strtok は NULL を返します。
312
+
313
+ strtok の呼び出し元では返ってきた値 NULL を words[++n] に代入します。
314
+
315
+ words[3] には NULL が入ります。
316
+
317
+
318
+
319
+ while の先頭に戻ります。
320
+
321
+ words[3] の値は NULL なので、whileループは終了します。これで
322
+
323
+ words[0] = "明日", words[1] = "助詞,ワ", words[2] = "名詞,ハレ",
324
+
325
+ words[3] = NULL となりました。
326
+
327
+
328
+
329
+ ----------------------------------------------------
330
+
331
+
332
+
333
+ 要するに、全部 "\t\n" で区切ると、
334
+
335
+
336
+
337
+ "明日"
338
+
339
+ "名詞,アシタ"
340
+
341
+ "は"
342
+
343
+ "助詞,ワ"
344
+
345
+ "晴れ"
346
+
347
+ "名詞,ハレ"
348
+
349
+ NULL
350
+
351
+
352
+
353
+ になるものが、"\t\n", "\t", "\t\n" で区切ると
354
+
355
+
356
+
357
+ "明日"
358
+
359
+ "名詞,アシタ\nは"
360
+
361
+ "助詞,ワ"
362
+
363
+ "晴れ"
364
+
365
+ "名詞,ハレ"
366
+
367
+ NULL
368
+
369
+ NULL
370
+
371
+
372
+
373
+ になるということです。

1

コード修正

2020/08/08 05:45

投稿

kazuma-s
kazuma-s

スコア8224

test CHANGED
@@ -40,7 +40,7 @@
40
40
 
41
41
  else
42
42
 
43
- printf("words[%d = [%s]\n", i, words[i]);
43
+ printf("words[%d] = [%s]\n", i, words[i]);
44
44
 
45
45
  }
46
46
 
@@ -52,11 +52,11 @@
52
52
 
53
53
  ```plain text
54
54
 
55
- words[0 = [明日]
55
+ words[0] = [明日]
56
56
 
57
- words[1 = [は]
57
+ words[1] = [は]
58
58
 
59
- words[2 = [晴れ]
59
+ words[2] = [晴れ]
60
60
 
61
61
  ```
62
62
 
@@ -66,11 +66,11 @@
66
66
 
67
67
  ```plain text
68
68
 
69
- words[0 = [明日]
69
+ words[0] = [明日]
70
70
 
71
- words[1 = [助詞,ワ]
71
+ words[1] = [助詞,ワ]
72
72
 
73
- words[2 = [名詞,ハレ]
73
+ words[2] = [名詞,ハレ]
74
74
 
75
75
  ```
76
76