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

回答編集履歴

3

strtok の説明を追加

2020/08/03 11:29

投稿

kazuma-s
kazuma-s

スコア8224

answer CHANGED
@@ -64,4 +64,36 @@
64
64
  ```
65
65
  なぜ、strcpy を何度も実行しているのか分かりますか?
66
66
  strtok は元の文字列に '\0' をたくさん書き込みます。
67
- そのことは理解できていますか?
67
+ そのことは理解できていますか?
68
+
69
+ **追記2**
70
+ strtok について説明します。
71
+
72
+ char str[] = "abc:123,def:45,ghi:678."; という文字列があったとします。
73
+
74
+ char *p = strtok(str, ",."); を実行すると、
75
+ strtok は、str の先頭から ',' または '.' を探しに行き、
76
+ str[7] に ',' が入っているのを見つけて、そこを '\0' に書き換えます。
77
+ "abc:123" という文字列を作ったことになります。
78
+ そして、'a' の入った str[0] のアドレスを返します。
79
+ その時 strtok は 'd' の入った str[8] のアドレスを内部に憶えておきます。
80
+
81
+ 次に、p = strtok(NULL, ".,"); を実行すると、
82
+ strtok は文字列をもらえず、NULL をもらったので、先ほど憶えておいた
83
+ str[8] のアドレスから ',' または '.' を探しに行き、
84
+ "def:45" という文字列を作って、その先頭の文字のアドレスを返します。
85
+
86
+ これを繰り返すと、str は "abc:123\0def:45\0ghi:678\0" となります。
87
+
88
+ このように、元の文字列 str は書き換えられてしまうので、
89
+ 今度は別の区切り文字、例えば ':' で分割しようと思ってももうできません。
90
+
91
+ だから、char buf[1024]; strcpy(buf, str); で str の文字列を buf に
92
+ コピーして、それを分割しているのです。
93
+
94
+ また、元の文字列が、const char *str = "abc:123,def:45,ghi:678."; だった場合、
95
+ str は配列ではなくポインタですから、文字列の実体は書き換えできない
96
+ 文字列リテラル "abc:123,def:45,ghi:678." であり、ポインタがそれを指します。
97
+ strtok(str, ",.") とすることはできません。
98
+ この場合も、書き換え可能な char配列に strcpy でコピーしてから、
99
+ strtok を使うことになります。

2

strtok のサンプルを追加

2020/08/03 11:28

投稿

kazuma-s
kazuma-s

スコア8224

answer CHANGED
@@ -27,4 +27,41 @@
27
27
  「...,ヲ,ヲ」と「吸い」の間の区切り文字は '\n' です。
28
28
 
29
29
  MeCab でのパース結果を見て、単語だけ取り出そうとするとき、
30
- 分割したときの区切り文字が何か知りたいなあと思いませんでしたか?
30
+ 分割したときの区切り文字が何か知りたいなあと思いませんでしたか?
31
+
32
+ **追記**
33
+ 質問者が頑張れば理解可能な strtok の使用例。
34
+ ```C
35
+ #include <stdio.h> // puts, printf
36
+ #include <string.h> // strcpy, strtok
37
+
38
+ int main()
39
+ {
40
+ const char *str = "タバコ\t名詞,一般,*,*,*,*,タバコ,タバコ,タバコ\n"
41
+ "を\t助詞,格助詞,一般,*,*,*,を,ヲ,ヲ\n";
42
+ char buf[1024], *p;
43
+
44
+ strcpy(buf, str);
45
+ puts("-- \"\n\" --");
46
+ p = strtok(buf, "\n");
47
+ while (p) { printf("[%s]\n", p); p = strtok(NULL, "\n"); }
48
+
49
+ strcpy(buf, str);
50
+ puts("-- \"\t\" --");
51
+ p = strtok(buf, "\t");
52
+ while (p) { printf("[%s]\n", p); p = strtok(NULL, "\t"); }
53
+
54
+ strcpy(buf, str);
55
+ puts("-- \",\" --");
56
+ p = strtok(buf, ",");
57
+ while (p) { printf("[%s]\n", p); p = strtok(NULL, ","); }
58
+
59
+ strcpy(buf, str);
60
+ puts("-- \",\t\n\" --");
61
+ p = strtok(buf, ",\t\n");
62
+ while (p) { printf("[%s]\n", p); p = strtok(NULL, ",\t\n"); }
63
+ }
64
+ ```
65
+ なぜ、strcpy を何度も実行しているのか分かりますか?
66
+ strtok は元の文字列に '\0' をたくさん書き込みます。
67
+ そのことは理解できていますか?

1

スペースの調整

2020/08/02 10:02

投稿

kazuma-s
kazuma-s

スコア8224

answer CHANGED
@@ -15,8 +15,8 @@
15
15
  ```
16
16
  [タバコ 名詞,一般,*,*,*,*,タバコ,タバコ,タバコ
17
17
  を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
18
- 吸い 動詞,自立,*,*,五段・ワ行促音便,連用形,吸う,スイ,スイ
18
+ 吸い 動詞,自立,*,*,五段・ワ行促音便,連用形,吸う,スイ,スイ
19
- ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
19
+ ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
20
20
  。 記号,句点,*,*,*,*,。,。,。
21
21
  EOS
22
22
  ]