回答編集履歴

6 コメントに対する回答を追加

kazuma-s

kazuma-s score 6160

2021/02/13 16:57  投稿

> p(ポインタ)のアドレスをq(ポインタ)に代入して、
ポインタ変数 p が保持している str[0] のアドレスをポインタ変数 q に代入して、
p も q も文字列 "str = ... str" を指すようになります。
> qのアドレスに入った文字列に含まれる?や:や0を探すために
q の指す文字列 "str = ... str" に含まれる '?' や ':' や '\0' を探すために
> qのアドレスをq++より++していき一致した場合
q の持つアドレスを 1つずつ進めて、str[0]、str[1]、str[2]、... を *q で
見ていき、一致する文字を探します。
> chに代入して、qに0を代入、
ch に代入するのは q の値ではなく、*q の値です。
それは '?' または ':' または '\0' です。
q に代入はしていません。*q に 0 (すなわち '\0')を代入しています。
> 文字列[str == NULL][\"(NULL)\"][str"]はchに入っていると思ったのですが、
文字列の長さは 28です。文字列の終端の '\0' を含めて 29バイトあります。
ch は int で 4バイトです。
ch に文字列を代入することはできません。
ch に代入しているのは *q の値。すなわち '?' または ':' または '\0' です。
> また if(ch==0) break;よりchに何も入らない(NULL)の後に
ch==0 の 0 は NULL ではなく、'\0' です。
ch に '?' でも ':' でもなく、'\0' が入っていた場合は、
もう次に探す文字列がないので break; で for(;;) の無限ループから脱出します。
> p = q+1;とありますが、これは何のための物でしょうか?
ch が '?' または ';' だった場合、次に探索する文字列をその次に進めるためです。
*q に 0 を代入して文字列を 2つに分割したあとの 2番目の文字列の先頭を
p が指すようにします。
**追記**
amazon で「苦しんで覚えるC言語」を検索して、「試し読み」で目次を見たら、
pp.252-354 が「第14章 文字列を扱う方法」と「第15章 ポインタ変数」だと分かりました。
説明はとても丁寧で分かりやすく書いてあります。
これを読んで、q と *q の違いが分からないはずがないと思うのですが、
まだ分からないのですね。
書名を教えてもらったので、次の質問には答えます。
> q=p; はpの値をqに代入します。そして
!(*q=='?' || *q==':' || *q==0); に進む、
qに入った文字列を一つとして扱うのではなく、文字列の文字一つ一つの文字のアドレスに含まれる?:0を探すために!(*q=='?' || *q==':' || *q==0);の形にした。
しかし、なぜ*q++ではなく、q++なのでしょうか?
++してアドレスをずらしていきながら?:0をを探すのなら*q++ではないのですか?
まず、「q に入った文字列」ですが、
q はポインタ変数なので、29バイトの文字列は入りません。
q に入るのは、文字列の先頭アドレスです。
p = str; は p = &str[0]; と同じ意味です。
p には、str[0] のアドレスが入っています。
q = p を実行すると、q にも str[0] のアドレスが入ります。
p も q もポインタで、str[0] を指しているのです。
str[0] は文字列の先頭なので、p と q は文字列を指していると言っていいでしょう。
*q=='?' ですが、* は間接演算子なので、*q は q の指している変数になります。
q の値は str[0] のアドレスなので、*q は str[0] です。
*q=='?' は str[0]=='?' のことなのです。
q++ で、q が 1増えます。q の値は str[1] のアドレスになりました。
次の *q=='?' は str[1]=='?' のことなのです。
これを繰り返すと、str[12] が '?' なので、そこで forループを抜けます。
q は str[12] を指しています。q には str[12] のアドレスが入っています。
*q++ ですが、後置演算子++ のほうが、前置演算子* よりも優先順位が高いので、
*(q++) ということになります。
q++ で str[0] のアドレスを持っていた q が str[1] のアドレスを持つようになります。
ただし、後置演算子++ の演算結果は 1増えた q の値ではなく、元の値です。
ということは、 q++ の値は str[0] のアドレスのままです。
前置演算子* により *q++ は str[0] になります。
この str[0] という変数は、値を参照されることもなく、別の値を代入されること
もなく、何の意味もないことになります。
for (i = 0; a[i] != 0; i++) printf("%d\n", a[i]); を
for (i = 0; a[i] != 0; a[i++]) printf("%d\n", a[i]); と書いても同じように
動きますが、だれもそんな風には書きません。
for (q = p; !(*q == '?'); q++) を
for (q = p; !(*q == '?'); *q++) と書いても同じように動きますが、
そう書く意味はありません。
**追記2**
ポインタを使わずに配列だけで書いてみました。
実行手順も実行結果もポインタを使ったものと同じです。
```C
#include <stdio.h>
#include <string.h>
int main(void)
{
   char str[] = "str == NULL ? \"(NULL)\" : str";
   int i, j;
   int ch;
   i = 0;
   for (;;) {
       for (j = i; !(str[j]=='?' || str[j]==':' || str[j]==0); j++) ;
       ch = str[j];
       str[j] = 0;
       printf("|%s|\n", &str[i]);
       if (ch == 0) break;
       i = j + 1;
   }
}
```
これなら理解できますか?
p は &str[i]、*p は str[i]、
q は &str[j]、*q は str[j] という関係です。
q は &str[j]、*q は str[j] という関係です。
**追記3**
> しかし、なぜ*q++ではなく、q++なのでしょうか?
++してアドレスをずらしていきながら?:0をを探すのなら*q++ではないのですか?
この質問に対して、i++ と a[i++] の例を出して、a[i++] は無意味であり、
同様に q++ で済むのに、*q++ と書くのは無意味である、
と回答しましたが、理解されなかったようですね。
```C
#include <stdio.h>
int main(void)
{
   int a[4] = { 3, 5, 7, 0 };
   char str[4] = "abc"; // char str[5] = { 'a', 'b', 'c', '\0' }; でも同じ
   for (int i = 0; a[i] != 0; i++) printf("%d ", a[i]);
   putchar('\n');
   for (int i = 0; a[i] != 0; a[i++]) printf("%d ", a[i]);
   putchar('\n');
   for (int i = 0; a[i] != 0; &a[i++]) printf("%d ", a[i]);
   putchar('\n');
   for (int i = 0; str[i] != 0; i++) printf("%s ", &str[i]);
   putchar('\n');
   for (int i = 0; str[i] != 0; str[i++]) printf("%s ", &str[i]);
   putchar('\n');
   for (int i = 0; str[i] != 0; &str[i++]) printf("%s ", &str[i]);
   putchar('\n');
   for (char *p = str; *p != 0; p++) printf("%s ", p);
   putchar('\n');
   for (char *p = str; *p != 0; *p++) printf("%s ", p);
   putchar('\n');
   for (char *p = str; *p != 0; &*p++) printf("%s ", p);
   putchar('\n');
}
```
i++ や p++ に意味があるのに、それに * や [] や & を付けてもその演算結果を
使わないのであれば無意味です。
わかりませんか?
5 誤字修正(関節参照 → 間接)

kazuma-s

kazuma-s score 6160

2021/02/11 12:03  投稿

> p(ポインタ)のアドレスをq(ポインタ)に代入して、
ポインタ変数 p が保持している str[0] のアドレスをポインタ変数 q に代入して、
p も q も文字列 "str = ... str" を指すようになります。
> qのアドレスに入った文字列に含まれる?や:や0を探すために
q の指す文字列 "str = ... str" に含まれる '?' や ':' や '\0' を探すために
> qのアドレスをq++より++していき一致した場合
q の持つアドレスを 1つずつ進めて、str[0]、str[1]、str[2]、... を *q で
見ていき、一致する文字を探します。
> chに代入して、qに0を代入、
ch に代入するのは q の値ではなく、*q の値です。
それは '?' または ':' または '\0' です。
q に代入はしていません。*q に 0 (すなわち '\0')を代入しています。
> 文字列[str == NULL][\"(NULL)\"][str"]はchに入っていると思ったのですが、
文字列の長さは 28です。文字列の終端の '\0' を含めて 29バイトあります。
ch は int で 4バイトです。
ch に文字列を代入することはできません。
ch に代入しているのは *q の値。すなわち '?' または ':' または '\0' です。
> また if(ch==0) break;よりchに何も入らない(NULL)の後に
ch==0 の 0 は NULL ではなく、'\0' です。
ch に '?' でも ':' でもなく、'\0' が入っていた場合は、
もう次に探す文字列がないので break; で for(;;) の無限ループから脱出します。
> p = q+1;とありますが、これは何のための物でしょうか?
ch が '?' または ';' だった場合、次に探索する文字列をその次に進めるためです。
*q に 0 を代入して文字列を 2つに分割したあとの 2番目の文字列の先頭を
p が指すようにします。
**追記**
amazon で「苦しんで覚えるC言語」を検索して、「試し読み」で目次を見たら、
pp.252-354 が「第14章 文字列を扱う方法」と「第15章 ポインタ変数」だと分かりました。
説明はとても丁寧で分かりやすく書いてあります。
これを読んで、q と *q の違いが分からないはずがないと思うのですが、
まだ分からないのですね。
書名を教えてもらったので、次の質問には答えます。
> q=p; はpの値をqに代入します。そして
!(*q=='?' || *q==':' || *q==0); に進む、
qに入った文字列を一つとして扱うのではなく、文字列の文字一つ一つの文字のアドレスに含まれる?:0を探すために!(*q=='?' || *q==':' || *q==0);の形にした。
しかし、なぜ*q++ではなく、q++なのでしょうか?
++してアドレスをずらしていきながら?:0をを探すのなら*q++ではないのですか?
まず、「q に入った文字列」ですが、
q はポインタ変数なので、29バイトの文字列は入りません。
q に入るのは、文字列の先頭アドレスです。
p = str; は p = &str[0]; と同じ意味です。
p には、str[0] のアドレスが入っています。
q = p を実行すると、q にも str[0] のアドレスが入ります。
p も q もポインタで、str[0] を指しているのです。
str[0] は文字列の先頭なので、p と q は文字列を指していると言っていいでしょう。
q の値は str[0] のアドレスなので、*q は str[0] です。
*q=='?' は str[0]=='?' のことなのです。
q++ で、q が 1増えます。q の値は str[1] のアドレスになりました。
次の *q=='?' は str[1]=='?' のことなのです。
これを繰り返すと、str[12] が '?' なので、そこで forループを抜けます。
q は str[12] を指しています。q には str[12] のアドレスが入っています。
*q++ ですが、後置演算子++ のほうが、前置演算子* よりも優先順位が高いので、
*(q++) ということになります。
q++ で str[0] のアドレスを持っていた q が str[1] のアドレスを持つようになります。
ただし、後置演算子++ の演算結果は 1増えた q の値ではなく、元の値です。
ということは、 q++ の値は str[0] のアドレスのままです。
前置演算子* により *q++ は str[0] になります。
この str[0] という変数は、値を参照されることもなく、別の値を代入されること
もなく、何の意味もないことになります。
for (i = 0; a[i] != 0; i++) printf("%d\n", a[i]); を
for (i = 0; a[i] != 0; a[i++]) printf("%d\n", a[i]); と書いても同じように
動きますが、だれもそんな風には書きません。
for (q = p; !(*q == '?'); q++) を
for (q = p; !(*q == '?'); *q++) と書いても同じように動きますが、
そう書く意味はありません。
**追記2**
ポインタを使わずに配列だけで書いてみました。
実行手順も実行結果もポインタを使ったものと同じです。
```C
#include <stdio.h>
#include <string.h>
int main(void)
{
   char str[] = "str == NULL ? \"(NULL)\" : str";
   int i, j;
   int ch;
   i = 0;
   for (;;) {
       for (j = i; !(str[j]=='?' || str[j]==':' || str[j]==0); j++) ;
       ch = str[j];
       str[j] = 0;
       printf("|%s|\n", &str[i]);
       if (ch == 0) break;
       i = j + 1;
   }
}
```
これなら理解できますか?
p は &str[i]、*p は str[i]、
q は &str[j]、*q は str[j] という関係です。
4 配列版のコードを追加

kazuma-s

kazuma-s score 6160

2021/02/02 16:14  投稿

> p(ポインタ)のアドレスをq(ポインタ)に代入して、
ポインタ変数 p が保持している str[0] のアドレスをポインタ変数 q に代入して、
p も q も文字列 "str = ... str" を指すようになります。
> qのアドレスに入った文字列に含まれる?や:や0を探すために
q の指す文字列 "str = ... str" に含まれる '?' や ':' や '\0' を探すために
> qのアドレスをq++より++していき一致した場合
q の持つアドレスを 1つずつ進めて、str[0]、str[1]、str[2]、... を *q で
見ていき、一致する文字を探します。
> chに代入して、qに0を代入、
ch に代入するのは q の値ではなく、*q の値です。
それは '?' または ':' または '\0' です。
q に代入はしていません。*q に 0 (すなわち '\0')を代入しています。
> 文字列[str == NULL][\"(NULL)\"][str"]はchに入っていると思ったのですが、
文字列の長さは 28です。文字列の終端の '\0' を含めて 29バイトあります。
ch は int で 4バイトです。
ch に文字列を代入することはできません。
ch に代入しているのは *q の値。すなわち '?' または ':' または '\0' です。
> また if(ch==0) break;よりchに何も入らない(NULL)の後に
ch==0 の 0 は NULL ではなく、'\0' です。
ch に '?' でも ':' でもなく、'\0' が入っていた場合は、
もう次に探す文字列がないので break; で for(;;) の無限ループから脱出します。
> p = q+1;とありますが、これは何のための物でしょうか?
ch が '?' または ';' だった場合、次に探索する文字列をその次に進めるためです。
*q に 0 を代入して文字列を 2つに分割したあとの 2番目の文字列の先頭を
p が指すようにします。
**追記**
amazon で「苦しんで覚えるC言語」を検索して、「試し読み」で目次を見たら、
pp.252-354 が「第14章 文字列を扱う方法」と「第15章 ポインタ変数」だと分かりました。
説明はとても丁寧で分かりやすく書いてあります。
これを読んで、q と *q の違いが分からないはずがないと思うのですが、
まだ分からないのですね。
書名を教えてもらったので、次の質問には答えます。
> q=p; はpの値をqに代入します。そして
!(*q=='?' || *q==':' || *q==0); に進む、
qに入った文字列を一つとして扱うのではなく、文字列の文字一つ一つの文字のアドレスに含まれる?:0を探すために!(*q=='?' || *q==':' || *q==0);の形にした。
しかし、なぜ*q++ではなく、q++なのでしょうか?
++してアドレスをずらしていきながら?:0をを探すのなら*q++ではないのですか?
まず、「q に入った文字列」ですが、
q はポインタ変数なので、29バイトの文字列は入りません。
q に入るのは、文字列の先頭アドレスです。
p = str; は p = &str[0]; と同じ意味です。
p には、str[0] のアドレスが入っています。
q = p を実行すると、q にも str[0] のアドレスが入ります。
p も q もポインタで、str[0] を指しているのです。
str[0] は文字列の先頭なので、p と q は文字列を指していると言っていいでしょう。
*q=='?' ですが、* は関節参照演算子なので、*q は q の指している変数になります。
q の値は str[0] のアドレスなので、*q は str[0] です。
*q=='?' は str[0]=='?' のことなのです。
q++ で、q が 1増えます。q の値は str[1] のアドレスになりました。
次の *q=='?' は str[1]=='?' のことなのです。
これを繰り返すと、str[12] が '?' なので、そこで forループを抜けます。
q は str[12] を指しています。q には str[12] のアドレスが入っています。
*q++ ですが、後置演算子++ のほうが、前置演算子* よりも優先順位が高いので、
*(q++) ということになります。
q++ で str[0] のアドレスを持っていた q が str[1] のアドレスを持つようになります。
ただし、後置演算子++ の演算結果は 1増えた q の値ではなく、元の値です。
ということは、 q++ の値は str[0] のアドレスのままです。
前置演算子* により *q++ は str[0] になります。
この str[0] という変数は、値を参照されることもなく、別の値を代入されること
もなく、何の意味もないことになります。
for (i = 0; a[i] != 0; i++) printf("%d\n", a[i]); を
for (i = 0; a[i] != 0; a[i++]) printf("%d\n", a[i]); と書いても同じように
動きますが、だれもそんな風には書きません。
for (q = p; !(*q == '?'); q++) を
for (q = p; !(*q == '?'); *q++) と書いても同じように動きますが、
そう書く意味はありません。
そう書く意味はありません。
**追記2**
ポインタを使わずに配列だけで書いてみました。
実行手順も実行結果もポインタを使ったものと同じです。
```C
#include <stdio.h>
#include <string.h>
int main(void)
{
   char str[] = "str == NULL ? \"(NULL)\" : str";
   int i, j;
   int ch;
   i = 0;
   for (;;) {
       for (j = i; !(str[j]=='?' || str[j]==':' || str[j]==0); j++) ;
       ch = str[j];
       str[j] = 0;
       printf("|%s|\n", &str[i]);
       if (ch == 0) break;
       i = j + 1;
   }
}
```
これなら理解できますか?
p は &str[i]、*p は str[i]、
q は &str[j]、*q は str[j] という関係です。
3 説明の修正

kazuma-s

kazuma-s score 6160

2021/02/02 03:12  投稿

> p(ポインタ)のアドレスをq(ポインタ)に代入して、
ポインタ変数 p が保持している str[0] のアドレスをポインタ変数 q に代入して、
p も q も文字列 "str = ... str" を指すようになります。
> qのアドレスに入った文字列に含まれる?や:や0を探すために
q の指す文字列 "str = ... str" に含まれる '?' や ':' や '\0' を探すために
> qのアドレスをq++より++していき一致した場合
q の持つアドレスを 1つずつ進めて、str[0]、str[1]、str[2]、... を *q で
見ていき、一致する文字を探します。
> chに代入して、qに0を代入、
ch に代入するのは q の値ではなく、*q の値です。
それは '?' または ':' または '\0' です。
q に代入はしていません。*q に 0 (すなわち '\0')を代入しています。
> 文字列[str == NULL][\"(NULL)\"][str"]はchに入っていると思ったのですが、
文字列の長さは 28です。文字列の終端の '\0' を含めて 29バイトあります。
ch は int で 4バイトです。
ch に文字列を代入することはできません。
ch に代入しているのは *q の値。すなわち '?' または ':' または '\0' です。
> また if(ch==0) break;よりchに何も入らない(NULL)の後に
ch==0 の 0 は NULL ではなく、'\0' です。
ch に '?' でも ':' でもなく、'\0' が入っていた場合は、
もう次に探す文字列がないので break; で for(;;) の無限ループから脱出します。
> p = q+1;とありますが、これは何のための物でしょうか?
ch が '?' または ';' だった場合、次に探索する文字列をその次に進めるためです。
*q に 0 を代入して文字列を 2つに分割したあとの 2番目の文字列の先頭を
p が指すようにします。
**追記**
amazon で「苦しんで覚えるC言語」を検索して、「試し読み」で目次を見たら、
pp.252-354 が「第14章 文字列を扱う方法」と「第15章 ポインタ変数」だと分かりました。
説明はとても丁寧で分かりやすく書いてあります。
これを読んで、q と *q の違いが分からないはずがないと思うのですが、
まだ分からないのですね。
書名を教えてもらったので、次の質問には答えます。
> q=p; はpの値をqに代入します。そして
!(*q=='?' || *q==':' || *q==0); に進む、
qに入った文字列を一つとして扱うのではなく、文字列の文字一つ一つの文字のアドレスに含まれる?:0を探すために!(*q=='?' || *q==':' || *q==0);の形にした。
しかし、なぜ*q++ではなく、q++なのでしょうか?
++してアドレスをずらしていきながら?:0をを探すのなら*q++ではないのですか?
まず、「q に入った文字列」ですが、
q はポインタ変数なので、29バイトの文字列は入りません。
q に入るのは、文字列の先頭アドレスです。
p = str; は p = &str[0]; と同じ意味です。
p には、str[0] のアドレスが入っています。
q = p を実行すると、q にも str[0] のアドレスが入ります。
p も q もポインタで、str[0] を指しているのです。
str[0] は文字列の先頭なので、p と q は文字列を指していると言っていいでしょう。
*q=='?' ですが、* は関節参照演算子なので、*q は q の指している変数になります。
q の値は str[0] のアドレスなので、*q は str[0] です。
*q=='?' は str[0]=='?' のことなのです。
q++ で、q が 1増えます。q の値は str[1] のアドレスになりました。
次の *q=='?' は str[1]=='?' のことなのです。
これを繰り返すと、str[12] が '?' なので、そこで forループを抜けます。
q は str[12] を指しています。q には str[12] のアドレスが入っています。
*q++ ですが、後置演算子++ のほうが、前置演算子* よりも優先順位が高いので、
*(q++) ということになります。
q++ で str[0] のアドレスを持っていた q が str[1] のアドレスを持つようになります。
ただし、後置演算子++ の演算結果は 1増えた q の値ではなく、元の値です。
ということは、 q++ の値は str[0] のアドレスのままです。
前置演算子* により *q++ は str[0] になります。
この str[0] という変数は、値を参照されることもなく、別の値を代入されること
もなく、何の意味もないことになります。
for (i = 0; a[i] != 0; i++) printf("%d\n", a[i]); を
for (i = 0; a[i] != 0; a[i++]) printf("%d\n", a[i]); と書いても同じように
動きますが、だれもそんな風には書きません。
for (q = p; !(*q == '?'); q++) を
for (q = p; !(*q == '?'); *q++) と書いても同じように動きますが、
そう書く意味はありません。
2 説明の修正

kazuma-s

kazuma-s score 6160

2021/02/02 03:11  投稿

> p(ポインタ)のアドレスをq(ポインタ)に代入して、
ポインタ変数 p が保持している str[0] のアドレスをポインタ変数 q に代入して、
p も q も文字列 "str = ... str" を指すようになります。
> qのアドレスに入った文字列に含まれる?や:や0を探すために
q の指す文字列 "str = ... str" に含まれる '?' や ':' や '\0' を探すために
> qのアドレスをq++より++していき一致した場合
q の持つアドレスを 1つずつ進めて、str[0]、str[1]、str[2]、... を *q で
見ていき、一致する文字を探します。
> chに代入して、qに0を代入、
ch に代入するのは q の値ではなく、*q の値です。
それは '?' または ':' または '\0' です。
q に代入はしていません。*q に 0 (すなわち '\0')を代入しています。
> 文字列[str == NULL][\"(NULL)\"][str"]はchに入っていると思ったのですが、
文字列の長さは 28です。文字列の終端の '\0' を含めて 29バイトあります。
ch は int で 4バイトです。
ch に文字列を代入することはできません。
ch に代入しているのは *q の値。すなわち '?' または ':' または '\0' です。
> また if(ch==0) break;よりchに何も入らない(NULL)の後に
ch==0 の 0 は NULL ではなく、'\0' です。
ch に '?' でも ':' でもなく、'\0' が入っていた場合は、
もう次に探す文字列がないので break; で for(;;) の無限ループから脱出します。
> p = q+1;とありますが、これは何のための物でしょうか?
ch が '?' または ';' だった場合、次に探索する文字列をその次に進めるためです。
*q に 0 を代入して文字列を 2つに分割したあとの 2番目の文字列の先頭を
p が指すようにします。
**追記**
amazon で「苦しんで覚えるC言語」を検索して、「試し読み」で目次を見たら、
pp.252-354 が「第14章 文字列を扱う方法」と「第15章 ポインタ変数」だと分かりました。
説明はとても丁寧で分かりやすく書いてあります。
これを読んで、q と *q の違いが分からないはずがないと思うのですが、
まだ分からないのですね。
書名を教えてもらったので、次の質問には答えます。
> q=p; はpの値をqに代入します。そして
!(*q=='?' || *q==':' || *q==0); に進む、
qに入った文字列を一つとして扱うのではなく、文字列の文字一つ一つの文字のアドレスに含まれる?:0を探すために!(*q=='?' || *q==':' || *q==0);の形にした。
しかし、なぜ*q++ではなく、q++なのでしょうか?
++してアドレスをずらしていきながら?:0をを探すのなら*q++ではないのですか?
まず、「q に入った文字列」ですが、
q はポインタ変数なので、29バイトの文字列は入りません。
q に入るのは、文字列の先頭アドレスです。
p = str; は p = &str[0]; と同じ意味です。
p には、str[0] のアドレスが入っています。
q = p を実行すると、q にも str[0] のアドレスが入ります。
p も q もポインタで、str[0] を指しているのです。
str[0] は文字列の先頭なので、p と q は文字列を指していると言っていいでしょう。
*q=='?' ですが、* は関節参照演算子なので、*q は q の指している変数になります。
q の値は str[0] のアドレスなので、*q は str[0] です。
*q=='?' は str[0]=='?' のことなのです。
q++ で、q が 1増えます。q の値は str[1] のアドレスになりました。
次の *q=='?' は str[1]=='?' のことなのです。
これを繰り返すと、str[12] が '?' なので、そこで forループを抜けます。
q は str[12] を指しています。q には str[12] のアドレスが入っています。
*q++ ですが、後置演算子++ のほうが、前置演算子* よりも優先順位が高いので、
*(q++) ということになります。
q++ で str[0] のアドレスを持っていた q が str[1] のアドレスを持つようになります。
ただし、後置演算子++ の演算結果は 1増えた q の値ではなく、元の値です。
ということは、 q の値は str[0] のアドレスです。
ということは、 q++ の値は str[0] のアドレスのままです。
前置演算子* により *q++ は str[0] になります。
この str[0] という変数は、値を参照されることもなく、別の値を代入されること
もなく、何の意味もないことになります。
for (i = 0; a[i] != 0; i++) printf("%d\n", a[i]); を
for (i = 0; a[i] != 0; a[i++]) printf("%d\n", a[i]); と書いても同じように
動きますが、だれもそんな風には書きません。
for (q = p; !(*q == '?'); q++) を
for (q = p; !(*q == '?'); *q++) と書いても同じように動きますが、
そう書く意味はありません。
1 コメントの質問への回答を追加

kazuma-s

kazuma-s score 6160

2021/02/02 02:58  投稿

> p(ポインタ)のアドレスをq(ポインタ)に代入して、
ポインタ変数 p が保持している str[0] のアドレスをポインタ変数 q に代入して、
p も q も文字列 "str = ... str" を指すようになります。
> qのアドレスに入った文字列に含まれる?や:や0を探すために
q の指す文字列 "str = ... str" に含まれる '?' や ':' や '\0' を探すために
> qのアドレスをq++より++していき一致した場合
q の持つアドレスを 1つずつ進めて、str[0]、str[1]、str[2]、... を *q で
見ていき、一致する文字を探します。
> chに代入して、qに0を代入、
ch に代入するのは q の値ではなく、*q の値です。
それは '?' または ':' または '\0' です。
q に代入はしていません。*q に 0 (すなわち '\0')を代入しています。
> 文字列[str == NULL][\"(NULL)\"][str"]はchに入っていると思ったのですが、
文字列の長さは 28です。文字列の終端の '\0' を含めて 29バイトあります。
ch は int で 4バイトです。
ch に文字列を代入することはできません。
ch に代入しているのは *q の値。すなわち '?' または ':' または '\0' です。
> また if(ch==0) break;よりchに何も入らない(NULL)の後に
ch==0 の 0 は NULL ではなく、'\0' です。
ch に '?' でも ':' でもなく、'\0' が入っていた場合は、
もう次に探す文字列がないので break; で for(;;) の無限ループから脱出します。
> p = q+1;とありますが、これは何のための物でしょうか?
ch が '?' または ';' だった場合、次に探索する文字列をその次に進めるためです。
*q に 0 を代入して文字列を 2つに分割したあとの 2番目の文字列の先頭を
p が指すようにします。
p が指すようにします。
**追記**
amazon で「苦しんで覚えるC言語」を検索して、「試し読み」で目次を見たら、
pp.252-354 が「第14章 文字列を扱う方法」と「第15章 ポインタ変数」だと分かりました。
説明はとても丁寧で分かりやすく書いてあります。
これを読んで、q と *q の違いが分からないはずがないと思うのですが、
まだ分からないのですね。
書名を教えてもらったので、次の質問には答えます。
> q=p; はpの値をqに代入します。そして
!(*q=='?' || *q==':' || *q==0); に進む、
qに入った文字列を一つとして扱うのではなく、文字列の文字一つ一つの文字のアドレスに含まれる?:0を探すために!(*q=='?' || *q==':' || *q==0);の形にした。
しかし、なぜ*q++ではなく、q++なのでしょうか?
++してアドレスをずらしていきながら?:0をを探すのなら*q++ではないのですか?
まず、「q に入った文字列」ですが、
q はポインタ変数なので、29バイトの文字列は入りません。
q に入るのは、文字列の先頭アドレスです。
p = str; は p = &str[0]; と同じ意味です。
p には、str[0] のアドレスが入っています。
q = p を実行すると、q にも str[0] のアドレスが入ります。
p も q もポインタで、str[0] を指しているのです。
str[0] は文字列の先頭なので、p と q は文字列を指していると言っていいでしょう。
*q=='?' ですが、* は関節参照演算子なので、*q は q の指している変数になります。
q の値は str[0] のアドレスなので、*q は str[0] です。
*q=='?' は str[0]=='?' のことなのです。
q++ で、q が 1増えます。q の値は str[1] のアドレスになりました。
次の *q=='?' は str[1]=='?' のことなのです。
これを繰り返すと、str[12] が '?' なので、そこで forループを抜けます。
q は str[12] を指しています。q には str[12] のアドレスが入っています。
*q++ ですが、後置演算子++ のほうが、前置演算子* よりも優先順位が高いので、
*(q++) ということになります。
q++ で str[0] のアドレスを持っていた q が str[1] のアドレスを持つようになります。
ただし、後置演算子++ の演算結果は 1増えた q の値ではなく、元の値です。
ということは、 q の値は str[0] のアドレスです。
前置演算子* により *q++ は str[0] になります。
この str[0] という変数は、値を参照されることもなく、別の値を代入されること
もなく、何の意味もないことになります。
for (i = 0; a[i] != 0; i++) printf("%d\n", a[i]); を
for (i = 0; a[i] != 0; a[i++]) printf("%d\n", a[i]); と書いても同じように
動きますが、だれもそんな風には書きません。
for (q = p; !(*q == '?'); q++) を
for (q = p; !(*q == '?'); *q++) と書いても同じように動きますが、
そう書く意味はありません。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る