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

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

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

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

Q&A

解決済

6回答

2006閲覧

C言語の数列の問題を配列を使って解きたいです

ON_theashtray

総合スコア16

C

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

0グッド

0クリップ

投稿2022/04/15 04:56

編集2022/04/15 05:14

C言語初学者です。
C言語の数列の問題で配列を使って解こうとするといつもエラーが出てしまい、自分で調べても何が間違えているのかわからなかったので質問させていただきました。
以下は与えられた問題です。

2つの数a0 = 0 a1 = 1が与えられたとき、an+2 = an +an+1 (n ≥ 0)で定義され る数列をフィボナッチ数列という。非負整数 n を入力すると 0 番目から n 番目ま でのフィボナッチ数列を表示するプログラムを作成せよ。

配列を利用して解くという問題指定もついていました。
最初に配列を指定するときの要素数をどうすればいいのかを特に教えてほしいです。
自分の能力不足は重々承知しているつもりですので優しく教えてほしいです。よろしくお願いします。
以下、エラーのコードです。

int main(){ int n,i,Fn; int a[]; printf("Enter the number:"); scanf("%d",&n); printf("0\n"); printf("1\n"); if (n>=2) { for (i=2; i<=n; i++) { a[i]=a[i-1]+a[i-2]; Fn=a[i]; printf("%d\n",Fn); } } return 0; }

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

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

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

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

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

Zuishin

2022/04/15 04:59

> 最初に配列を指定するときの要素数をどうすればいいのかを特に教えてほしいです。 配列は不要です。 どのように配列を使えという指示があるなら、それによって数が変わってくるでしょう。
maisumakun

2022/04/15 05:01

エラーが出た状態のコードと、実際に発生したエラーをご提示いただけませんでしょうか?
ON_theashtray

2022/04/15 05:25

どのように配列を使えという指示はありませんでした。 ただ、「配列を使用する」と記述してありました。
hoshi-takanori

2022/04/15 05:28

n の入力後に int a[n]; とか…。
Zuishin

2022/04/15 05:31

2 要素でデータをスライドしながら使うのも手ですが、3 要素のリングバッファを使いたいところです。 n 個の要素を確保するのであれば、int の最大値から、値がオーバーフローしない最大の n を求めるのが良いと思います。 そこまでしなくても、適当に大きい数を指定すれば、使いきれず終わると思います。
fana

2022/04/15 06:16

> 調べても何が間違えているのかわからなかった 「調べる」とは? 何が間違いなのかはエラーメッセージとして出ているのでは.
jimbe

2022/04/15 06:45 編集

>最初に配列を指定するときの要素数をどうすれば hoshi-takanori さんのコメントで十分な気がします。(出来る処理系か分かりませんが。)
Zuishin

2022/04/15 09:06 編集

可変長配列は C11 でオプションに格下げになったので(つまり方言扱いなので)、学習時に使用していいかは微妙かと。中学英語のテストで you のことを u と書くと不正解になるような。
hoshi-takanori

2022/04/15 22:46

C11 で可変長配列が削除されたのは知りませんでした。となると、選択肢は ・n の最大値を決めておく ・malloc などで動的に確保する ・処理系依存を承知で可変長配列 ・長さ 3 の配列を使い回す ってことになるでしょうか。 どれがいいかは出題者の意図を確認する必要があるかと…。
BeatStar

2022/04/16 08:10 編集

一つ目。「いつもエラーが出てしまい」とありますがどのようなエラーでしょうか? エラーの種類によって対処が全く変わってきます。 http://blog.livedoor.jp/crackstars/archives/17846001.html 二つ目。「自分で調べても」とありますが、どのように調べ、どのように試したのでしょうか? プログラマやSEは単に決まったコードを打つだけ…ではありません。不具合の原因を調査し修正することも含みます。デバッガで潜るとか、OS周りの調査とか。 質問者さんとしては何かしらの調査をしたのかもしれませんが、他のユーザは所詮赤の他人なのでどんな風に何をしたのかさえ言われないとわかりません。 三つ目。授業ではどこまで習ったか書きましょう。書かない場合は「実装できればいい」と考えられてしまいます。他の方も仰っているように教師が考えた答え以外は認めない場合もありますよ。
guest

回答6

0

ベストアンサー

十分おおきな配列を最初に確保しておけば良いです。
47回目でint型(32ビット整数)の上限を超えます。
95回目でlong long int 型(64ビット整数)の上限を超えます。
なので100程度確保しておけば十分です。
47以上の数値の場合、オーバーフローがおこり正しい結果が表示されませんが、そのままにしてあります。

C

1#include <stdio.h> 2int main(){ 3 int n,i,Fn; 4 int a[100]; 5 printf("Enter the number:"); 6 scanf("%d",&n); 7 if (n < 0 || n > 99){ 8 printf("number is wrong!\n"); 9 return 0; 10 } 11 a[0] = 0; 12 a[1] = 1; 13 for (i = 0; i < 2; i++){ 14 Fn = a[i]; 15 printf("i=%d Fn=%d\n",i,Fn); 16 } 17 for (i=2; i<=n; i++) { 18 a[i]=a[i-1]+a[i-2]; 19 Fn=a[i]; 20 printf("i=%d Fn=%d\n",i,Fn); 21 } 22 return 0; 23} 24 25

投稿2022/04/15 08:23

編集2022/04/15 08:27
tatsu99

総合スコア5438

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

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

ON_theashtray

2022/04/19 04:51

皆さんの回答本当にわかりやすかったのですが、この方の回答が一番シンプルでわかりやすかったのでこの方をベストアンサーにさせていただきました。 本当にありがとうございました。
guest

0

コードを大雑把に読んでみましたが、大体の方向性はあっています。(実際には全く違うのだが、見当違いとまでは言えない気がするので)

まず、フィボナッチ数列の定義を確認してください。によると、

フィボナッチ数列は、「2つ前の項と1つ前の項を足し合わせていくことでできる数列」のことです。

とある。

つまり、初項と第二項の和が第三項、第二項と第三項の和が第四項…となっている数列のことですね。これをプログラミングとかは置いといて今回のルール(nまでのフィボナッチ数列とか)を用いて現実世界で考えてみてください。手作業でノートかなんかにフィボナッチ数列を書いていくのです。

今回は初項(= a0 ) と第二項(= a1 )が決められています。第三項つまりa2から a(n-1)までをやる。と。

漸化式an+2 = an +an+1 (n ≥ 0) を用いて考えると、現在の項を i とすると i = 0 (= 初項) を代入してみると
a2 = a0 + a1 となりますね。つまり第三項は初項と第二項の和になっています。
i = 1 も同様に考えると a3 = a1 + a2 となり、第四項 = 第三項 + 第二項 となっています。これをnまで繰り返すと考えるとどうでしょうか?(厳密には n-1 までですが)

そうすると初項から考えても i = 0~(n-1)で、その中を a[i+2] = a[i] + a[i+1] が漸化式(をそれっぽくしたもの)になる。

a0 = 0, a1 = 1 だとわかっているのだから最初から a[0] = 0, a[1] = 1 と入れておけば後はfor文とかで 0~(n-1)までの範囲をループさせながら上記の漸化式(もどき)を使って配列に突っ込んでいけばいいはずです。

後はそれをN個分ループしながら表示するだけです。

ただし、条件としてn ≥ 0があるのでこれも満たす必要があります。これは今回の質問みたいに

C

1if( n >= 2 ){ 2 // 実際にフィボナッチ数列を求めて配列に入れる 3}

というようなやり方でもいいですが、ちょっと待ってください。フィボナッチ数列の定義ってなんでしたっけ?

2つ前の項と1つ前の項を足し合わせていくことでできる数列

でしたよね。

ということはNは2以上でないならそもそも求めることが不可能と言えるはずです。
ただし、フィボナッチ数列の定義はWikipediaによると

F0 = 0,
F1 = 1,
Fn+2 = Fn + Fn+1 (n ≥ 0)

という漸化式なので n が 0 未満なのは認めないということです。

でもユーザは何を入力するかわからないってことで nに何を入れてもバグらないように「nが0未満のとき」とかみたいにやる・やらないを分岐させる必要がありますね。

やる: nの値が0以上
やらない: nの値が0未満

となると、

C

1if( /* nの値が0以上 */ ){ 2 // フィボナッチ数列を求める 3}else{ // nの値が0未満 4 // 何もしない 5}

となるはずです。でも「nの値が0未満」のときの処理が「何もしない」ってもったいないですよね。余計なものですね。なので省きましょう。すると

C

1if( /* nの値が0以上のとき */ ){ 2 // フィボナッチ数列を求める 3}

となりますがちょっとくどいと思いませんか? 処理内容から考えて「0未満はイレギュラーな状況」と言えるはずです。ということは「0未満 -> 何もせずに終了」と言えるはずです。

つまり、

1. nの値を決める 2. nの値が0未満なら何もせずに終了 3. フィボナッチ数列を生成する 4. (3)の数列を表示する

みたいにすれば、(1)で n = -1 だったら (2)で条件を満たすのでここで終了。そうすると(3)に行くことができないですよね。

n = 1 なら (2)では条件を満たさないため(3)に。そしてそのままフィボナッチ数列を求めて表示。

こうすれば可読性が高まるはずです。

そして今回の問題での「エラーが出た(泣」ではおそらく「配列の要素数が指定されていない」系のエラーメッセージが出ているのではないかと妄想しています。

C言語の配列では要素数が指定されていないと使えません。必ず inrt arr[10];のような感じで要素数を指定します。でも今回の場合は要素数が不明瞭。条件として 100<N≦0 となっているのなら 最大の項数は100なので100-1 = 99 あれば十分だと思いますが不定なのででたらめにデカい数字でいいかと。

あるいは動的配列を学んだのであればmalloc/freeを使って動的配列で確保するとかでもいいです。

投稿2022/04/16 08:45

BeatStar

総合スコア4958

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

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

0

配列だけを使ってみました。

c

1#include <stdio.h> 2 3int main(void) 4{ 5 int a[3] = { 0, 1 }; 6 scanf("%d", a); 7 while (a[0]-- >= 0) 8 if (a[1] < a[2]) 9 printf("%d\n", a[1]), a[1] += a[2]; 10 else 11 printf("%d\n", a[2]), a[2] += a[1]; 12}

別解

c

1#include <stdio.h> 2 3int main(void) 4{ 5 int n, a[2] = { 0 }; 6 scanf("%d", &n); 7 for (a[n & 1] = 1; n-- >= 0; a[n & 1] = a[0] + a[1]) 8 printf("%d\n", a[n & 1]); 9}

投稿2022/04/15 12:49

編集2022/04/15 18:04
kazuma-s

総合スコア8224

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

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

0

a(n+2) = a(n) +a(n+1) を言い換えれば
a(n) = a(n-1) + a(n-2) なのだから

0 番目から n 番目ま でのフィボナッチ数列であるなら
総素数 N+1 の配列があれば十分です。

[追記] 配列を再帰で埋めてみた:

C

1#include <stdio.h> 2#include <stdlib.h> 3 4int Fn(int table[], int n) { 5 if ( table[n] < 0 ) 6 table[n] = n <= 2 ? n : Fn(table,n-1) + Fn(table, n-2); 7 return table[n]; 8} 9 10int main(){ 11 int n; 12 printf("Enter the number:"); 13 scanf("%d",&n); 14 15 int* table = malloc((n+1)*sizeof(int)); 16 for ( int i = 0; i <= n; ++i ) table[i] = -1; 17 18 Fn(table,n); 19 for ( int i = 0; i <= n; ++i ) { 20 printf("%d\n", table[i]); 21 } 22 23 free(table); 24 return 0; 25}

投稿2022/04/15 10:57

編集2022/04/16 02:37
episteme

総合スコア16614

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

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

0

数列を配列にすべて詰め込む必要がないなら3つの要素をを使いまわせばいい気がしました。

c

1#include <stdio.h> 2int main(void){ 3 4 int a[3]; 5 int n = 13; 6 7 if (n < 0) { 8 return -1; 9 } 10 11 if (n >= 0) { 12 printf("0\n"); 13 } 14 if (n >= 1) { 15 printf("1\n"); 16 } 17 a[0] = 0; 18 a[1] = 1; 19 20 for (int i = 0; i <= n - 2; i++) { 21 a[(i+2)%3] = a[(i+1)%3] + a[i%3]; 22 printf("%d\n", a[(i+2)%3]); 23 } 24 return 0; 25}

投稿2022/04/15 08:45

h-okhs

総合スコア149

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

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

0

何かしらの処理に必要な値を「とりあえず配列という形で持つ」ように実装すれば良いのでは.

C

1//※数値の型として何がよいのかわからんので… 2typedef unsigned int ValType; 3 4int main() 5{ 6 const unsigned int n = 8; //※nの入力処理は面倒なので省略 7 ValType Buff[2] = { 0, 1 }; //配列 8 unsigned char idx = 0; 9 10 //a0, a1 の表示 11 printf( "0\n1\n" ); 12 //a2以降の表示 13 for( unsigned int i=2; i<=n; ++i ) 14 { 15 Buff[idx] = Buff[0] + Buff[1]; 16 printf( "%u\n", Buff[idx] ); //※ここの書式指定については数値の型次第か 17 idx = (idx+1)&0x01; 18 } 19 return 0; 20}

投稿2022/04/15 06:14

fana

総合スコア11656

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

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

fana

2022/04/15 06:20

> 最初に配列を指定するときの要素数をどうすればいいのか 「必要な個数」にすればよい. で,必要な個数とはいくつなのか?というのを考えることは その問題を解く ということに含まれているのではあるまいか. 「X個あれば済むような処理方法(アルゴリズム)を考えて実装せよ」って話なのだろうから.
fana

2022/04/15 06:25

k番目の値を求めるのに k-1番目 と k-2番目 の値が必要,って話なら, とりあえず覚えておけば良さそうな値の個数は2個だ. k-3 番目とかそれよりも昔のデータは覚えていても使う機会が無いのだから,覚えておく必要は無い. で,必要な値を配列という形で持つというのなら,配列の必要な要素数は2だ.それだけの話. (まぁ,別に要素数が3個とか4個とかの配列にしておいても間違いとは言わないが,使わない要素を持つ意味は無いよね)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問