質問内容
プログラミング初心者です。今回が初めての質問になります。
私なりに素数を判定するプログラムを書いてみたのですが、main関数内で3回"return 0"と記述しています。このように1つの関数内で複数のreturn文を用いることは文法上問題あるでしょうか?
return文は関数の最後に使うものというイメージがあるので、このような使い方が正しいのか悩んでおります。
文法上問題なかったとしても、このようなコードは美しくないとされるでしょうか?
回答よろしくお願いいたします。
該当のソースコード
C言語
1#include <stdio.h> 2 3int main(void) 4{ 5 int i, num; 6 7 printf("自然数を入力してください。\n"); 8 scanf("%d", &num); 9 10 if (num == 1) 11 { 12 printf("%dは素数ではありません。\n", num); 13 return 0; 14 } 15 16 for (i = 2; i < num; i++) 17 if (num % i == 0) 18 { 19 printf("%dは素数ではありません。\n", num); 20 return 0; 21 } 22 23 printf("%dは素数です。\n", num); 24 return 0; 25}
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答6件
0
ベストアンサー
言語仕様には以下のように明記されています。 (C99 の項目 6.8.6.4 の第二段落から抜粋)
A function may have any number of return statements.
(一つの関数は,任意の個数のreturn文をもってもよい。)
作法として美しいかどうかというのは総合的な判断なのでこの場合についての皆さんの意見が他の場合にそのまま当てはめられるわけではないということは強く主張しておきます。 どちらかを常に適用するという教条主義に陥らないように各状況をよく把握して考えてください。
投稿2022/02/16 02:31
総合スコア5684
0
まず根本的なこととして、「文法上問題がないか」というのはコンパイラに聞けば分かる話なので、
貴方のプログラムをコンパイラがエラーや警告を出さずにコンパイルしてくれたのなら、
他人に訊くまでもなく、それが「問題ない」という答えだと判断できます。
(まぁ、コンパイラによって多少の違い(方言)はあるようですが、本件のような重要な点はまず同じです。)
その上で「これは良い書き方なのか?」と疑問を持つのなら、それは良いことだと思いますし、この場合は疑問を持って正解です。
で、既に他の回答者の方々が仰っている通り、returnは必要に応じた数を書くのが適切です。
「returnを複数書いていいのか?」というのはどちらかと言うと心配のベクトルが逆で、
「returnをただ1つにすることに(大した根拠もなく)こだわってはまずいのではないか?」と心配した方が良いです。
return文は関数の最後に使うものというイメージがある
との事ですが、できれば、何故そのようなイメージを抱くに至ったのか教えて欲しいです。
勉強中に見たサンプルコードが、たまたまそういうものばかりだったとかでしょうか?
私も「ガード節」でググってみましたが、例えばこんなサイトがヒットしますね。
初心者向け。覚えておきたい 「ガード節」という書き方。 - Qiita https://qiita.com/kouyan/items/7b8b456b626447a1e24e
この解説はPHPの話ですが、本質的な所はどの言語でも同じなので理解できると思います。
人間の脳の記憶領域というのは狭いものなので、考えるべきことを可能な限り減らしてあげることが大事です。
例えば、貴方が(不幸にも!)他人の書いた関数の途中のある行を読んでいるとして、
それより上のif節の中にreturnがあれば、「if節の条件に当てはまる場合」は考慮しなくて済むことになり、理解がしやすくなります。
if節に対応するelse節を使えば同様のことはできますが、それをやっていくとネストがどんどん深くなって可読性が下がるので、典型的な悪いコードの一種になります。
言い換えれば、returnするということは、「この場合のことは、ここより下ではもう考えなくていいよ!」と、コードを読んでいる人に言ってあげる行為だと言えるでしょう。
文法上問題なかったとしても、このようなコードは美しくないとされるでしょうか?
「美しくない」という表現を使っていることがちょっと気になったので、蛇足的ですが所見を書いておきます。
コードの「美しさ」に配慮するのは良いことなので、それはそれで大事にしてください。
ただ、本件に関しては、「美しい」かどうかの問題に留まらず、「可読性」「保守性」と言った現実的な問題が実際に発生するからこちらの方が良いとされているのだ、と理解して欲しいです。
ある方法が良い/悪いとされるのにはそれなりの合理的な理由があるものであり、純粋に「美しさ」だけが問題になるようなケースはさほど多くないでしょう。
例えば「#include <stdio.h>」を「おまじない」と呼ぶような風潮に対しても私は良くないな~といつも思うのですが、
それと同様に、「美しいか否か」という曖昧な観点でコードの是非の判断をするのは、問題の本質をぼやけさせ、思考停止を生む要因になり得るので危険ではないか…と私は思います。
コードの書き方の理由を問われた時に、「一般に、これが美しい書き方だとされているのでこう書きました」と受け売りだけの回答をするようなプログラマは、私に言わせれば信頼性が低いです。
こういう理由があるからこう書いているんだよ、とちゃんと説明できるような人になって欲しいですね。
投稿2022/02/24 08:06
総合スコア37
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
文法上はなんの縛りもありません。
文法の縛りではありませんが、誤ってunreachableな部分を作ってしまうとコンパイラは警告ぐらいはしてくることが多いでしょう。
かつて、「入り口一つ、出口も一つが美しいんだ」という主張を聞いたことはありますが、あまり流行ってはいないようです。デバッグ時に関数を出る時にブレークを張るのも簡単でしょ? みたいなことも言っていたように思います。
私的には、returnというよりは外部への出力処理(質問の場合ではprintf)を一箇所にまとめたいなぁという意識があるので、このプログラムを私の趣味に合わせて書くと結果としてreturnが一つになったりします。しかしこれは組み込み屋的な都合によるものですので、一般論かと言われるとちょっと。
C
1nt main(void) 2{ 3 int i, num; 4 const char* result="です"; 5 const char* notPrime="ではありません"; 6 7 printf("自然数を入力してください。\n"); 8 scanf("%d", &num); 9 10 if (num != 1) 11 { 12 for (i = 2; i < num; i++) { 13 if (num % i == 0) 14 { 15 result=notPrime; 16 break; 17 } 18 } 19 } 20 printf("%dは素数%s。\n", num, result); 21 return 0; 22}
投稿2022/02/15 22:59
総合スコア7703
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/02/16 11:09
2022/02/16 15:11
2022/02/18 06:29
0
「条件を満たさない場合にさっさとreturn
する」ことは、ガード節と名前が付く程度には一般的な書き方です。
投稿2022/02/15 22:59
総合スコア145982
0
このように1つの関数内で複数のreturn文を用いることは文法上問題あるでしょうか?
問題ないです
それよりも、returnが実行されないパスが無いように注意しましょう
コンパイルオプションで、ワーニングを全有効にしておけば、そういう基本的な抜けを指摘してくれるんで、おすすめです。
#が、余計なお世話の指摘もガンガン出てくるんで初心者のうちは混乱するかも
投稿2022/02/15 22:42
総合スコア88040
0
幾つあっても問題ありません。
むしろ、必要なら速やかに終了すると言うことはコードを分かり易くすると思います。(異論はあるかも知れません。)
素数の判定部分を関数として分けると、"素数ではありません"の表示が1つに出来ます。
c
1#include <stdio.h> 2 3int isPrimeNumbers(int n) 4{ 5 if (n == 1) 6 return 0; 7 8 for (int i = 2; i < n; i++) 9 if (n % i == 0) 10 return 0; 11 12 return 1; 13} 14 15int main(void) 16{ 17 int num; 18 19 printf("自然数を入力してください。\n"); 20 scanf("%d", &num); 21 22 if (isPrimeNumbers(num)) 23 printf("%dは素数です。\n", num); 24 else 25 printf("%dは素数ではありません。\n", num); 26 27 return 0; 28}
ついでに、変数は最初に全て宣言するもの、というのも可能なら止められた方が(個人的には)良いと思います。
投稿2022/02/15 17:40
編集2022/02/15 19:09総合スコア13204
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/02/16 15:06