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

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

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

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

Q&A

解決済

5回答

1687閲覧

c言語 コード読み解き方法

GokaTokyo

総合スコア66

C

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

0グッド

1クリップ

投稿2017/12/10 13:24

挫折中、早めにコードを理解する方法ありますか?
例えば、下記コードに何するか、そのロジック全部わかりません。(泣)    

#include<stdio.h> #include<math.h> #define MAX 1000 int prime[MAX]; int isPrimeNaive(int n) { if(n <= 1) return 0; for(int i = 2; i < n; i++) if(n % i == 0) return 0; return 1; } int isPrime(int n) { if(n<= 1) return 0; if(n == 2) return 1; if(n%2 == 0) return 0; int limit = (int)sqrt((double)n); for(int i = 3; i <= limit; i=i+2) { if(n % i == 0) return 0; } return 1; } void sieve() { prime[0] = 0; prime[1] = 0; for(int i = 2; i < MAX; i++) prime[i] = 1; int limit = (int)sqrt((double)MAX); for(int i = 2; i <= limit; i++) { if(prime[i]) for(int j = i*i; j <= MAX; j+=i) prime[j] = 0; } } int isPrimeSieve(int n) { if(prime[n]) return 1; else return 0; } int main() { sieve(); printf("N=%d %d\n", 1, isPrime(1)); printf("N=%d %d\n", 2, isPrime(2)); printf("N=%d %d\n", 3, isPrime(3)); printf("N=%d %d\n", 4, isPrime(4)); printf("N=%d %d\n", 7, isPrime(7)); printf("N=%d %d\n", 9, isPrime(9)); printf("N=%d %d\n", 13, isPrime(13)); printf("N=%d %d\n", 17, isPrime(17)); printf("N=%d %d\n", 100, isPrime(100)); printf("N=%d %d\n", 23, isPrime(23)); printf("N=%d %d\n", 1, isPrime(1)); return 0; }

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

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

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

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

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

guest

回答5

0

理解できない場合は、次の2つのうちのどちらか、または両方が足りないので、足りるようにして下さい。
・C言語の理解
・扱っている題材の理解

例えば、将棋のプログラムを読んで理解する場合、将棋の知識が必要です。
これは素数のプログラムのようなので、素数の知識(ある数が素数かどうかをどうやって判断するかレベルの知識で十分)が必要です。

投稿2017/12/10 13:42

otn

総合スコア84423

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

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

strike1217

2017/12/10 13:45

失礼します。 このisPrime()って数学で出てきますよね。(数Aかな) 数学の理解も必要になってくるのではないですかね? 不要ですかな?
otn

2017/12/10 13:48

素数の知識が必要と書いていますよ。
strike1217

2017/12/10 14:14

あ、こりゃ失礼しました。 またやってしまった。
guest

0

ベストアンサー

コード読み解き方法

複雑だから分かりにくい。
分けると分かりやすい
だから、分かるまで分解します。

C言語は関数が基本的な単位ですので、
ひとつの関数だけを見てみましょう。

c

1int isPrime(int n)

まず、関数名が「Prime」だから、素数を求める関数だと分かります。

c

1int isPrime(int n) 2{ 3 return 0; 4 return 1; 5 return 0; 6 return 0; 7 return 1; 8}

次に、Return文だけ見ると、返り値は0か1の二択だと分かります。
引数がintで、返り値が0か1の関数。

c

1int isPrime(int n) 2{ 3 if(n<= 1) 4 if(n == 2) 5 if(n%2 == 0) 6 if(n % i == 0) 7}

そして、IF文だけ見ると、引数nに応じて分岐している。
正の整数か、2かどうか、剰余が0かによって分岐しています。

c

1int isPrime(int n) 2{ 3 if(n<= 1) 4 return 0; 5 if(n == 2) 6 return 1; 7 if(n%2 == 0) 8 return 0; 9}

前半の方が後半よりやさしいので、前半だけ見てみます。

負数やゼロだと0を返す。
引数nが2だと返り値1を返している。
偶数だと0を返す。
だから、素数だと1で、素数でないと0を返すと分かります。

c

1 int limit = (int)sqrt((double)n); 2 for(int i = 3; i <= limit; i=i+2)

後半、一番ゴチャゴチャして難しいところなので、
一行をさらに分けて考えます。

c

1 limit = ; 2 for(; i <= limit;)

「limit」はFor文の上限値だと分かります。

c

1sqrt()

「sqrt」は平方根を求める関数です。
だから、For文では、3からnの平方根まで、2ずつ増やして回している。
そういうループ構造が分かります。

関数の中は、IFの分岐とForのループが基本構造です。
それらが複雑な場合、フローチャート図解するのも有効です。

なぜ、平方根を使っているのかは、
「素数 平方根」で検索して、
今回の仕様である数学の知識を得ると分かります。

そしてまた、上から逐次で一行ずつ読むと、
初見の時より、かなり分かりやすくなっていると思います。

今回はmain関数にすでに書いてありますが、
テストを書いて動作を確認するのも大事です。


早めにコードを理解する方法

「毎回こんなことやってたら遅いでしょ」と思うかもしれません。

慣れてきたら、こんな風に読む必要はなくなります。
しかし、最初のうちは、一行ずつていねいに読みます。

「かけ算の九九」とかを覚えるのと同じで、
基礎をやるときは、ゆっくり時間をかけた方が、最終的に早く済みます
「急がば回れ」、「ウサギとカメ」の話です。

投稿2017/12/11 08:18

編集2017/12/11 08:24
LLman

総合スコア5592

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

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

0

一般論でいうと、コードの読解とは文章問題を解くのと同じです。明確に意図がある記述をされたコードから意図を読み取るのですから、文章読解よりは慣れれば簡単です。

ただ、プログラムの場合はその意図が「何らかの動作をさせること」であり、ものによってはその動作についての知識がないと意味が解けないというのがあります。

関数 isPrime の動作を書き記すと、

  1. 与えられた引数が 1以下 の場合は 0 を返す
  2. 与えられた引数が 2 の場合は 1 を返す
  3. 与えられた関数が 2で割り切れる(=2以外の自然数である偶数) 場合は 0 を返す
  4. 上記 1~3 に当てはまらない(3以上の奇数)は、

 その数の平方根までの整数で順次割ってみて、割り切れる数がある場合は 0 を返す
割り切れなかったら 1 を返す

となります。が、これがイコール素数を求めるものである、というのは、素数とはどういうものかを知らなければ回答できないわけです。
ですからプログラムを読解する場合、まずそのプログラムがどういう用途で使われるために作られたものであるかを知らないと、正しく解釈することができません。誰であれ、自分の知識にないものは解釈できないのですから。

投稿2017/12/11 08:42

tacsheaven

総合スコア13703

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

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

0

細かく(例えば分岐ごとに)printfを挟んで変数が、その時どうなっているかを調べる

最終手段
ソースレベルデバッガを使ってステップ実行し、変数の動きを調べる

慣れてくると自分の頭のなかにCインタプリタが出来上がる

解析しながらコメント書いてくのもいいよ

c

1// nは素数? 2int isPrime(int n) 3{ 4 // 1 未満は素数ではない 5 if(n<= 1) 6 return 0; 7 // 2は素数 8 if(n == 2) 9 return 1; 10 // 2を除く偶数は素数ではない 11 if(n%2 == 0) 12 return 0; 13 // 3 ~ x ~ sqrt(n)で割り切れるnは素数ではない 14 int limit = (int)sqrt((double)n); 15 for(int i = 3; i <= limit; i=i+2) 16 { 17 if(n % i == 0) 18 return 0; 19 } 20 // 3~sqrt(n)までで割り切れない数は素数 21 return 1; 22}

c

1// 篩 2void sieve() 3{ 4 // 0と1は素数ではない 5 prime[0] = 0; prime[1] = 0; 6 // 2以上の数には素数の疑惑がある 7 for(int i = 2; i < MAX; i++) 8 prime[i] = 1; 9 // 素数でない数N(MAX以下)はsqrt(MAX)までの素数で割り切れる筈 10 int limit = (int)sqrt((double)MAX); 11 12 for(int i = 2; i <= limit; i++) 13 { 14 // i は疑惑が残っているなら素数 15 if(prime[i]) 16 // i * i 以上のiの倍数は素数ではない 17 // (それ未満のiの倍数は既にフラグ消去済み) 18 for(int j = i*i; j <= MAX; j+=i) 19 prime[j] = 0; 20 } 21} 22 23// 篩で残ったものは素数 24int isPrimeSieve(int n) 25{ 26 if(prime[n]) 27 return 1; 28 else 29 return 0; 30} 31

投稿2017/12/10 15:13

asm

総合スコア15147

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

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

0

コード読解大原則(でっち上げ)

1. 関数を見たらまず呼び出されているか確認スべし。例えばisPrimeNaiveisPrimeSieveは呼ばれていない。
2. 関数ごとに、引数で渡されてくる入力、引数ではない形で入ってくる(グローバル変数、標準入力など)入力、戻り値(出力)、引数経由で返される出力(ポインタを介して)、引数ではない形の出力(グローバル変数、標準出力など)を調べる。
3. 関数の呼び出し箇所を見て入力と出力がどう作られ利用されるか確認する。
4. 変数名を辞書を引くとかして処理のヒントを得る

今回の場合は素数探索ですね。isPrimeに渡される引数が素数なら1、そうでなければ0を返します。

isPrimeNaiveisPrimeSieveは呼ばれていませんが、isPrimeと引数・戻り値の型が同じで名前も似ているので別のアルゴリズムで同じ結果を得るためのものとわかります。isPrimeSieveはグローバル変数であるprimeを参照しており、呼び出し前にこれを適切に初期する必要があることがわかり、それをしているのがsieve関数ですね。

投稿2017/12/10 14:00

yumetodo

総合スコア5850

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問