質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

1150閲覧

C言語について3つ質問ができました。

MitzKuno

総合スコア12

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2018/10/12 16:53

C言語を勉強していて、いくつか質問ができたので質問させてください。
質問は、3つあります。

『質問1』

#include <stdio.h> int main(void){ int a = 0; char b[] = "NET"; char c[4]; while(b[a] != '\0') { c[a] = b[2-a]; a++; } c[3] = '\0'; printf("%sは逆から読むと%s\n", b, c); return 0; }

教科書で文字列の勉強をしていて、この処理でNETからTENに反転するというのは理解できました。
ただ8行目のwhile文でbが\0以外である限り処理を繰り返すと書いてあるのに、{}内の処理内容では一生\0にならない内容になっていますよね。
これは、処理内容の結果が反転してTENになったら、それ以降のwhile文の処理は、コンピュータ内では勝手に終わっていると考えればいい(深く考えなくていい)のでしょうか?
それともこのwhile文には、何かこう書かなければ他に処理できない意図のようなものがあるのでしょうか?

『質問2』

#incude<stdio.h> int main(void){ char x = 4, y; char *p = &x; y = *p; printf("変数xの値は%dです\n", y); return 0; }

ポインタの勉強をしていて、冒頭のchar x = 4, y; という宣言が出てきたのですが、これは

char x = 4   char x = y

という宣言をまとめて書いたものなのでしょうか?それとも違うのでしょうか?
ここがわからなくて、何となく腑に落ちません。

『質問3』

#include <stdio.h> int main(void) { char s[] = "I love cat and dog."; //探す対象の文字列 char c = 'a'; //探す文字 char *p = s; int n = 0; printf(" \" %s \" の中から \' %c \' を探します\n", s, c); while (*p != '\0') { if (*p == c) { printf("%d文字目で発見しました\n", p-s+1); n++; } p++; } if (n == 0) printf("1つも見つかりませんでした\n"); else printf("全部で%d個見つかりました\n", n); return 0; }

こちらも処理内容は、一通り下まで読んだのですが、13行目の p-s+1 だけが、どういう計算なのかわかりませんでした。
後半の+1は、文字列の添字が0から始まるために"何文字目"を計算する際には1足す必要があるということだったと思うのですが、前半は全く理解できず、正直、p-s はどこをどう計算してるのか、お恥ずかしくも全部わかりません。

以上、3つが質問になります。
よろしければご教授していただきたいです。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

###『質問1』
char b[] = "NET";
と宣言することで、b[0]='N', b[1]='E', b[2]='T', b[3]='\0'
となると思います。
b[3]の時、whileの継続条件に反するので、whileループを脱します。

###『質問2』
char x = 4, y;

char x = 4;
char y;
と同等と思います。
C言語でポインタを語る上で、重要なのがは2つの意味があることを
理解することです。
1つはポインタを宣言するための
、もう一つは間接演算子としての*です。

###『質問3』
p, sはいずれもアドレスが入ると思います。
(実際にprintf("p=%p s=%p\n", p, s);とかで出ないでしょうか)
sは検索対象文字列の先頭アドレス、pは探す文字が見つかった位置のアドレスです。
pは一文字一文字探す度にインクリメントしているのでs-pで文字数が分かります。

たとえば検索対象文字列、探す文字が以下の場合、7-5+1=3で、3文字目に
見つかったことになります。

■探す文字:c
■検索対象文字列:abc
以下、メモリ上の配置。(実際のアドレスはもっと大きな値とは思いますが)

アドレス
5a
6b
7c

投稿2018/10/12 17:18

編集2018/10/12 17:20
otaks

総合スコア223

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MitzKuno

2018/10/16 13:51

質問1に関しては、自分の説明が不十分でした申し訳ありません。 tiitoiさんのところに改めて質問させていただいたので、割愛させていただきたいと存じ上げます。 質問2は、勉強になりました。 ありがとうございます。 質問3は、たしかにおっしゃる通りでした。 ヒントも含め、アドバイスありがとうございます。
guest

0

ベストアンサー

質問1

処理の流れは以下になります。

  1. b[0] != '\0': b[0] ('N') なので true となり、ループ継続。

  2. c[0] = b[2-0]; c[0] に b[2] ('T') を代入している

  3. a をインクリメントして a は 1 になる。

  4. b[1] != '\0': b[1] ('E') なので true となり、ループ継続。

  5. c[1] = b[2-1]; c[1] に b[1] ('E') を代入している。

  6. a をインクリメントして a は 2 になる。

  7. b[2] != '\0': b[2] ('T') なので true となり、ループ継続。

  8. c[2] = b[2-2]; c[2] に b[0] ('N') を代入している。

  9. a をインクリメントして a は 3 になる。

  10. b[3] != '\0': b[3] ('\0') なので false となり、ループを抜ける。

質問2

char x = 4, y

は以下と同値です。変数 y は未初期化です。

char x = 4; char y;

質問3

p - s は p が文字を見つけた位置のポインタ、s は配列の先頭のポインタです。
文字列はメモリ上に連続して配置されていることを利用しています。

012345678910111213141516171819
Ilovecatanddog.\0

投稿2018/10/12 17:08

編集2018/10/12 17:30
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MitzKuno

2018/10/16 13:50

まず返信に3日以上かかってしまい、申し訳ありませんでした。 質問1に関してですが、自分の質問の仕方が悪かったです。 tiitoiのおっしゃる通り、ループ継続の部分は自分でもわかっていたのですが、 while(b[a] != ‘\0’) { c[a] = b[2-a]; a++ } において、冒頭で\0にならない限り繰り返すと宣言しているのに、処理内容のb[2-a]では、いつまでたってもb[3]がくることはないのでは?と思ってしまい、どう処理を終えているのだろうかと疑問に思ったと書きたかったんです。 文字列や条件式そのものが理解できていないわけではないんです。 理屈がどうなっているのか気になったのですが、考え過ぎでした。すみません。 質問2は、初見でした。 勉強になります。 ありがとうございます。 質問3のp-s+1ですが、 ポインタ(*p)に格納した値の中からc(a)に当てはまる値(8番目、11番目)を、ポインタの先頭で引き、我々が数える『1番目』と配列の『番号付けの0番』という差を補うために最後に1足している。 ということから、 8-0+1…9番目という答えが出る 11-0+1…12番目という答えが出る でよろしいのでしょうか。
tiitoi

2018/10/16 14:04

質問3ですがその認識であってます。
MitzKuno

2018/10/18 11:23

謎が解けました。 ありがとうございました。
MitzKuno

2018/10/19 04:47

すみません。 今さらながらですが、画面とにらめっこしてて気づいたのですが、質問1も解答されてる通りでした。 記述通り、b[3]までの式の処理をそのまま書いていただいていたのを今さら理解しました。 b[2-a]は、ただただcに代入しているだけの処理なのに、これを本来のbそのものにも影響すると勝手に考えて、いつまでもb[3]にならないじゃないかと勝手に思い込んでました。 bはちゃんと解答されていた通り、a++でb[3]までいってfalseで抜けますね。 文字式も条件式もまだまだでした…が、これで中途半端な理解から改めて抜け出せてよかったです。 本当に3つとも、丁寧に解説していただき、ありがとうございました。
guest

0

直接の回答は付いていますので、アドバイスを。

Cの勉強中とのことですが、質問1,質問2は、Cの基本のさらに一歩手前くらいのレベルのことなので、書籍で勉強していないのなら、入門書を買ってそれをちゃんと読み通すことをお勧めします。書籍で勉強してもこの質問が出るようであれば、別の本を探した方が良いかと。

質問3については、どのレベルで理解できていないのか分からないのですが、質問1,2よりはレベルが上の疑問だと思います。おそらく、よく聞く「ポインタが難しい」ということでしょうか。ポインタについては入門レベルを超えた人でも理解できない人がいるようなので、あせらずじっくりで良いかと思います。

投稿2018/10/12 17:56

otn

総合スコア84538

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MitzKuno

2018/10/16 13:52

…すみませんでした。
guest

0

質問1

「C言語の文字列とは?」という理解がまず必要です。
C言語の場合、文字列と言うのは結局以下の条件のデータです。

  1. charの配列である。
  2. 最後が'\0'(数値で0)である。

また、"NET"のように、「"」で囲ったものを文字列リテラルと呼びますが、
文字列リテラルは「書いた文字の並びと、末尾に'\0'を付加したchar配列」になります。
ですから、

C

1#include <stdio.h> 2int main(void) { 3 char s[] = "Hello"; 4 char s2[] = { 'H', 'e', 'l', 'l', 'o', '\0' }; 5 printf("s:%s, s2:%s\n", s, s2); 6 return 0; 7}
s:Hello, s2:Hello

配列sと配列s2は結局同じ意味になります。

...という下書きを始めていたらすでにtiitoiさんが回答されているので、ここまで。

投稿2018/10/12 17:26

daisuke7

総合スコア1563

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

daisuke7

2018/10/12 17:27

さらにotaksさんも。皆さん速いですね!
MitzKuno

2018/10/16 13:52

自分の質問の仕方が間違ってました。 申し訳ありません。 tiitoiさんのところに改めて質問させていただいたので、割愛させていただきたいと存じ上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問