回答編集履歴
6
コメントに対する回答を追加
answer
CHANGED
@@ -116,4 +116,46 @@
|
|
116
116
|
これなら理解できますか?
|
117
117
|
|
118
118
|
p は &str[i]、*p は str[i]、
|
119
|
-
q は &str[j]、*q は str[j] という関係です。
|
119
|
+
q は &str[j]、*q は str[j] という関係です。
|
120
|
+
|
121
|
+
**追記3**
|
122
|
+
> しかし、なぜ*q++ではなく、q++なのでしょうか?
|
123
|
+
++してアドレスをずらしていきながら?:0をを探すのなら*q++ではないのですか?
|
124
|
+
|
125
|
+
この質問に対して、i++ と a[i++] の例を出して、a[i++] は無意味であり、
|
126
|
+
同様に q++ で済むのに、*q++ と書くのは無意味である、
|
127
|
+
と回答しましたが、理解されなかったようですね。
|
128
|
+
|
129
|
+
```C
|
130
|
+
#include <stdio.h>
|
131
|
+
|
132
|
+
int main(void)
|
133
|
+
{
|
134
|
+
int a[4] = { 3, 5, 7, 0 };
|
135
|
+
char str[4] = "abc"; // char str[5] = { 'a', 'b', 'c', '\0' }; でも同じ
|
136
|
+
|
137
|
+
for (int i = 0; a[i] != 0; i++) printf("%d ", a[i]);
|
138
|
+
putchar('\n');
|
139
|
+
for (int i = 0; a[i] != 0; a[i++]) printf("%d ", a[i]);
|
140
|
+
putchar('\n');
|
141
|
+
for (int i = 0; a[i] != 0; &a[i++]) printf("%d ", a[i]);
|
142
|
+
putchar('\n');
|
143
|
+
|
144
|
+
for (int i = 0; str[i] != 0; i++) printf("%s ", &str[i]);
|
145
|
+
putchar('\n');
|
146
|
+
for (int i = 0; str[i] != 0; str[i++]) printf("%s ", &str[i]);
|
147
|
+
putchar('\n');
|
148
|
+
for (int i = 0; str[i] != 0; &str[i++]) printf("%s ", &str[i]);
|
149
|
+
putchar('\n');
|
150
|
+
|
151
|
+
for (char *p = str; *p != 0; p++) printf("%s ", p);
|
152
|
+
putchar('\n');
|
153
|
+
for (char *p = str; *p != 0; *p++) printf("%s ", p);
|
154
|
+
putchar('\n');
|
155
|
+
for (char *p = str; *p != 0; &*p++) printf("%s ", p);
|
156
|
+
putchar('\n');
|
157
|
+
}
|
158
|
+
```
|
159
|
+
i++ や p++ に意味があるのに、それに * や [] や & を付けてもその演算結果を
|
160
|
+
使わないのであれば無意味です。
|
161
|
+
わかりませんか?
|
5
誤字修正(関節参照 → 間接)
answer
CHANGED
@@ -63,7 +63,7 @@
|
|
63
63
|
p も q もポインタで、str[0] を指しているのです。
|
64
64
|
str[0] は文字列の先頭なので、p と q は文字列を指していると言っていいでしょう。
|
65
65
|
|
66
|
-
*q=='?' ですが、* は
|
66
|
+
*q=='?' ですが、* は間接演算子なので、*q は q の指している変数になります。
|
67
67
|
q の値は str[0] のアドレスなので、*q は str[0] です。
|
68
68
|
*q=='?' は str[0]=='?' のことなのです。
|
69
69
|
|
4
配列版のコードを追加
answer
CHANGED
@@ -88,4 +88,32 @@
|
|
88
88
|
|
89
89
|
for (q = p; !(*q == '?'); q++) を
|
90
90
|
for (q = p; !(*q == '?'); *q++) と書いても同じように動きますが、
|
91
|
-
そう書く意味はありません。
|
91
|
+
そう書く意味はありません。
|
92
|
+
|
93
|
+
**追記2**
|
94
|
+
ポインタを使わずに配列だけで書いてみました。
|
95
|
+
実行手順も実行結果もポインタを使ったものと同じです。
|
96
|
+
```C
|
97
|
+
#include <stdio.h>
|
98
|
+
#include <string.h>
|
99
|
+
|
100
|
+
int main(void)
|
101
|
+
{
|
102
|
+
char str[] = "str == NULL ? \"(NULL)\" : str";
|
103
|
+
int i, j;
|
104
|
+
int ch;
|
105
|
+
i = 0;
|
106
|
+
for (;;) {
|
107
|
+
for (j = i; !(str[j]=='?' || str[j]==':' || str[j]==0); j++) ;
|
108
|
+
ch = str[j];
|
109
|
+
str[j] = 0;
|
110
|
+
printf("|%s|\n", &str[i]);
|
111
|
+
if (ch == 0) break;
|
112
|
+
i = j + 1;
|
113
|
+
}
|
114
|
+
}
|
115
|
+
```
|
116
|
+
これなら理解できますか?
|
117
|
+
|
118
|
+
p は &str[i]、*p は str[i]、
|
119
|
+
q は &str[j]、*q は str[j] という関係です。
|
3
説明の修正
answer
CHANGED
File without changes
|
2
説明の修正
answer
CHANGED
@@ -77,7 +77,7 @@
|
|
77
77
|
*(q++) ということになります。
|
78
78
|
q++ で str[0] のアドレスを持っていた q が str[1] のアドレスを持つようになります。
|
79
79
|
ただし、後置演算子++ の演算結果は 1増えた q の値ではなく、元の値です。
|
80
|
-
ということは、 q の値は str[0] のアドレスです。
|
80
|
+
ということは、 q++ の値は str[0] のアドレスのままです。
|
81
81
|
前置演算子* により *q++ は str[0] になります。
|
82
82
|
この str[0] という変数は、値を参照されることもなく、別の値を代入されること
|
83
83
|
もなく、何の意味もないことになります。
|
1
コメントの質問への回答を追加
answer
CHANGED
@@ -36,4 +36,56 @@
|
|
36
36
|
|
37
37
|
ch が '?' または ';' だった場合、次に探索する文字列をその次に進めるためです。
|
38
38
|
*q に 0 を代入して文字列を 2つに分割したあとの 2番目の文字列の先頭を
|
39
|
-
p が指すようにします。
|
39
|
+
p が指すようにします。
|
40
|
+
|
41
|
+
**追記**
|
42
|
+
amazon で「苦しんで覚えるC言語」を検索して、「試し読み」で目次を見たら、
|
43
|
+
pp.252-354 が「第14章 文字列を扱う方法」と「第15章 ポインタ変数」だと分かりました。
|
44
|
+
説明はとても丁寧で分かりやすく書いてあります。
|
45
|
+
これを読んで、q と *q の違いが分からないはずがないと思うのですが、
|
46
|
+
まだ分からないのですね。
|
47
|
+
|
48
|
+
書名を教えてもらったので、次の質問には答えます。
|
49
|
+
|
50
|
+
> q=p; はpの値をqに代入します。そして
|
51
|
+
!(*q=='?' || *q==':' || *q==0); に進む、
|
52
|
+
qに入った文字列を一つとして扱うのではなく、文字列の文字一つ一つの文字のアドレスに含まれる?:0を探すために!(*q=='?' || *q==':' || *q==0);の形にした。
|
53
|
+
しかし、なぜ*q++ではなく、q++なのでしょうか?
|
54
|
+
++してアドレスをずらしていきながら?:0をを探すのなら*q++ではないのですか?
|
55
|
+
|
56
|
+
まず、「q に入った文字列」ですが、
|
57
|
+
q はポインタ変数なので、29バイトの文字列は入りません。
|
58
|
+
q に入るのは、文字列の先頭アドレスです。
|
59
|
+
|
60
|
+
p = str; は p = &str[0]; と同じ意味です。
|
61
|
+
p には、str[0] のアドレスが入っています。
|
62
|
+
q = p を実行すると、q にも str[0] のアドレスが入ります。
|
63
|
+
p も q もポインタで、str[0] を指しているのです。
|
64
|
+
str[0] は文字列の先頭なので、p と q は文字列を指していると言っていいでしょう。
|
65
|
+
|
66
|
+
*q=='?' ですが、* は関節参照演算子なので、*q は q の指している変数になります。
|
67
|
+
q の値は str[0] のアドレスなので、*q は str[0] です。
|
68
|
+
*q=='?' は str[0]=='?' のことなのです。
|
69
|
+
|
70
|
+
q++ で、q が 1増えます。q の値は str[1] のアドレスになりました。
|
71
|
+
次の *q=='?' は str[1]=='?' のことなのです。
|
72
|
+
|
73
|
+
これを繰り返すと、str[12] が '?' なので、そこで forループを抜けます。
|
74
|
+
q は str[12] を指しています。q には str[12] のアドレスが入っています。
|
75
|
+
|
76
|
+
*q++ ですが、後置演算子++ のほうが、前置演算子* よりも優先順位が高いので、
|
77
|
+
*(q++) ということになります。
|
78
|
+
q++ で str[0] のアドレスを持っていた q が str[1] のアドレスを持つようになります。
|
79
|
+
ただし、後置演算子++ の演算結果は 1増えた q の値ではなく、元の値です。
|
80
|
+
ということは、 q の値は str[0] のアドレスです。
|
81
|
+
前置演算子* により *q++ は str[0] になります。
|
82
|
+
この str[0] という変数は、値を参照されることもなく、別の値を代入されること
|
83
|
+
もなく、何の意味もないことになります。
|
84
|
+
|
85
|
+
for (i = 0; a[i] != 0; i++) printf("%d\n", a[i]); を
|
86
|
+
for (i = 0; a[i] != 0; a[i++]) printf("%d\n", a[i]); と書いても同じように
|
87
|
+
動きますが、だれもそんな風には書きません。
|
88
|
+
|
89
|
+
for (q = p; !(*q == '?'); q++) を
|
90
|
+
for (q = p; !(*q == '?'); *q++) と書いても同じように動きますが、
|
91
|
+
そう書く意味はありません。
|