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

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

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

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

4回答

6418閲覧

【C言語の質問です】整数nまでの合計を表示するプログラムを作成するには・・

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2016/02/25 01:13

*たくさんの方よりご指摘をいただけてとてもありたいです。
引き続き、よろしくお願い致します。

C言語を勉強している初心者のものです。

今課題をいただき、その作成をしております。
先日提出(全18問)したのですが、大部分が間違っているので、
再度問題を見なおした上で提出してくれと言われてしまいました。

今回は課題なので、間違っている点を教えていただけませんでした。
個人的には、どの辺りが間違っているのかわからないため、
客観的な視点が欲しく、今回ご相談させていただきました。

回答の例を提示されているのですが、
nが大きくなるとで画面の見栄えが悪くなると思い、
同じような表示にはしませんでした。
また懸念点として、nが大きくなるにつれて
intでは処理しきれなくなってしまうのでと思ったのですが、
この場合、いかがでしょうか。

回答が趣旨と外れているように感じましたら
ご指摘いただけますと幸いです。

【問題】
正の整数nを入力し、1+2+3+....nの結果を表示するプログラムを作成せよ。

例)「4」を入力した際には1+2+3+4の結果、「10」となる。

【回答】

#include <stdio.h> int main(void) { int score; printf("整数を入力してください。"); scanf("%d",&score); if (score >= 0) { printf("入力した整数までの合計は%dとなります。\n",(1 + score) * score / 2); } else { printf("再度整数を入力してください"); } return 0; }

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

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

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

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

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

guest

回答4

0

投稿されている質問を幾つか拝見しましたが、
多くで共通して問題になるのはscanf周りくらいですかね。
恐怖?のscanf
scanfでエラー対応 OKweb

後あるとすれば、課題冊子の冒頭等で「明示されていない限り処理は関数を作成してそこで行いなさい」のような記述は無かったでしょうか?
「大部分が間違っている」と評する程の箇所が他に見当たらないんですよね...

投稿2016/02/25 01:29

編集2016/02/25 01:41
hirohiro

総合スコア2068

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

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

hirohiro

2016/02/25 01:56

しかしscanfを問題視してるなら「再度問題を見なおした上で」というのも変なんですよね。 それで、共通ルールの見落としがあるんじゃないかな~っと思いました。 個々の問題に書いていないが、冒頭や最後にフォーマットや形式のルール記載があったり等
退会済みユーザー

退会済みユーザー

2016/02/25 02:23

ご回答ありがとうございます! ご指摘いただいたscanfまわりいただいたURLを参考にさせていただきながら 自分の中で整理整頓してみます。 >後あるとすれば、課題冊子の冒頭等で「明示されていない限り処理は関数を作成してそ>こで行いなさい」のような記述は無かったでしょうか? 上記のような記述はありませんでした。。。 記述内容としては、Webで調査しながら課題を解いてくれということでした・・・ ご指摘頂いているところをなおしながら頑張ってみます!!
退会済みユーザー

退会済みユーザー

2016/02/25 07:57

scanf関数のURL早速確認させていただきました。 業務では使われていないのですね笑 fgets 関数とsscanf関数を使っているという記事が多かったので、 この2つの勉強も行っていきたいと思います。 ありがとうございました!!
guest

0

Chironian様、majiponi様とのディスカッションに参加しようと思ったのですが、コード量がインデントなしではどうにも見づらくなりますので、解答欄にて首を突っ込ませていただきます。

tomo3さんのコードの問題点については以下のコード上で指摘しますが、わたしのコードについても、なにぶん境界条件の話なので、うっかりポカ等ありそうです。

C

1#include <stdio.h> 2#include <limits.h> 3 4int IsOverflow(int); 5 6int main(void) 7{ 8 int score, answer; 9 unsigned int i; // unsigned は、+オンリーの数字だよ、という意味です 10 printf("正の整数を入力してください。\n"); 11 scanf("%d",&score); 12 13// over(score); // over関数内で return を呼んでもその関数を抜けるだけです。 14 15 if (!IsOverflow(score)) // if it is not overflowed と、自然な英語で記述できます*下解説 16 { 17 answer = 0; 18 for (i = 1; i <= score; i++) // 記述ミス:for内で int i を宣言できるのはC++です 19 { // C ではその記法を用いるとエラーになります 20 answer = answer + i; 21 } 22 printf("1から%dまでの合計数値は%dです。\n",score,answer); 23 } else { 24 printf("エラー:オーバーフロー!\n"); 25 } 26 return 0; 27} 28 29//******************************************************************************************** 30/** 31 * @brief Overflow しているか否か. 32 * @note 何かが「○○」である事を確認する関数は Is○○ という名前で定義されることが 33 * 多いです。こうすることで 34 * if (IsOverflow) { ~ 35 * の形、つまり英語で if it is overflow, then ~ の形で読むことができるように 36 * なるからです。ある程度基本が身についてきたならば、プログラミング作法などの本 37 * やウェブページを勉強なさると読みやすいコードが書けるようになりますよ 38 * 39 * @param[in] score 対象スコア. 40 * 41 * @retval 1 オーバーフローするよ 42 * @retval 0 オーバーフローしないよ 43 */ 44//******************************************************************************************** 45int IsOverflow (int score) 46{ 47#if 0 48 if (score > INT_MAX/score - 1) 49 { 50 printf("error"); 51// break ; // 記述ミス:ループ、switch文の中にない break; 52 } else if (score < 0) { // 記述ミス修正(else の後に;) 53 printf("error\n正の整数を入力してください。"); 54 } 55 return 0; 56#elif 0 57 // 上の記述を直してみた 58 int ret = 0; // ret = false; 59 if (score > INT_MAX/score - 1 ) 60 { 61 ret = 1; // ret = true; 62 } 63 return ret; // score がオーバーフローする場合のみ1:trueが返される 64#else 65 // ちゅうか実装されているアルゴリズム的にオーバーフローの条件変わってるやんけ! 66 /* 67 計算処理途中で計算結果より大きくなることがないので、最終結果が限界を超えないこと 68 を確認しなきゃいけない。つまり 69 (1+score)*score/2 < limit 70 1+score < (limit/score) *2 71 score < (limit/score)*2 -1 72 ここで score > 2 は自明であるから(limit/score)*2 < limit 73 */ 74 int ret = 0; // ret = false; 75 if (score > (INT_MAX/score)*2 - 1 ) 76 { 77 ret = 1; // ret = true; 78 } 79 80 return ret; // score がオーバーフローする場合のみ1:trueが返される 81#endif 82} 83 84/* 85#if ~ #else ~ #endif について 86#if はプリプロセス命令といって、#include や #define の仲間です。 87今は詳しく知らなくてもいいですが、とりあえず 88#if 1 89 (1) 90#else 91 (2) 92#endif 93について、コンパイラが(2)を無視して(1)のみコンパイルするんだな~と覚えていただければ十分です。 94今回はこれの if 0, つまり逆の場合ですね 95*/ 96

tomo3さんの実装的にそれまでのディスカッションで出てきたリミットと変わっていましたので、全面的に書き直しました。
それまでのリミットでは
46340の時1073720970
が限界ですが、計算しなおしたリミットだと
65535の時2147450880
が限界となります。

投稿2016/02/26 16:04

編集2016/02/27 06:03
WoodenHamlet

総合スコア306

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

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

退会済みユーザー

退会済みユーザー

2016/02/28 01:39

ご回答ありがとうございます。 また解説もありがとうございます!!! 解説を読ませていただきながら理解を深めていきたいと思います!
majiponi

2016/02/28 10:26

補足ありがとうございます。アルゴリズムの変更で限界値が変わることは認識していたのですが、本質からそれてしまいそうだったのであえて書いていませんでした。でも一言触れるべきですよね…。 (scoreとscore+1のどちらかは偶数なので、偶数側を2で割ってから掛ける、というのが私の案でした。) scanfオーバーフローは、規格書を読み直してはじめて気が付きました。ご指摘ありがとうございます。scoreが0の場合は、投稿者の最初のコードで1以上が保証されていたので、書く必要はないと思い省略しました。 他の方も指摘されていますが、本当はかなり難しい問題です。どこまで初学者に教えるかも大変難しい。正直、オーバーフロー検出すら、まだ教える段階ではないと個人的には考えています。 多倍長整数の入力、計算などを0から実装すれば、どのような入力にも対応できますが、そこまで求められているとは思えません。double型を利用すれば、「ある程度の」大きい数字にも耐えられますが、限界はあります。どこまで対応するかは、指定されなければ、プログラマの裁量によるところが大きいわけで、正直、最初の解答でも私なら正答として扱います。議論に参加されている皆様は、どのように教えるべきだとお考えですか?
ozwk

2016/02/28 11:24

他の問題のレベルを見る限り オーバーフローの考慮は問題になっていないのではと思います。 出題者は単にループを使って欲しかったのだと思います。 (「大部分が間違っている」というのにこの解答が含まれているのか不明ですが。) でもパフォーマンスのことを考えると最初の解答のほうがいいですよね。
WoodenHamlet

2016/02/28 15:30

まあたしかに私もオーバーフローは今回の問題では特に問題にはしてないと思います。 ちょっと詰め込みすぎた感は有りますが、質問者さんが chironian 様の回答へのコメントでいろいろ頑張っていらっしゃるようなので張り切ってしまいました。
Chironian

2016/02/28 16:03

majiponiさん。 > 議論に参加されている皆様は、どのように教えるべきだとお考えですか? 最初に回答へ記載したように、初心者へ求めるのは明らかに過剰と思います。 でも、いつかは知るべきことですし、本人にやる気があるのなら無理のない範囲でフォローするのもありかなって思ってます。
guest

0

この課題が何を狙っているのかによるのでは。
変数を使った計算の演習を目的としているのなら、
変数aに1を代入
変数aに2を足す
変数aに3を足す
・・・
というのをプログラムでうまく書くにはどうしたらいいのか?という観点で作るべきですね。
(つまりループの演習につながる)
そうでなくて計算で一発!というなら今のままで、scanf周りの整理で良いと思います。
恐らく初歩の課題と思われるので、入力処理のエラー処理云々よりかは前者かと思います。

投稿2016/02/25 07:50

ttyp03

総合スコア16998

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

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

退会済みユーザー

退会済みユーザー

2016/02/25 08:00

ご回答ありがとうございます。 たしかにループの演習目的の課題のような気がしてきました。 なので、両方用意することにしました。 ありがとうございます!早速作成してみます。
guest

0

こんにちは。

「正の整数n」ということなので、入力先はunsigned intではないかと思います。
書式指定子に注意下さい。
なお、0が入力された時の振る舞いにも注意下さい。


【閑話休題】
他に、整数のオーバーフローもあると言えばあります。googleさえ見落とした不具合ですし、初心者に求めるのは明らかに過剰です。とは言え、知っておくに越したことはないので、簡単に。

(1 + score) * scoreの部分がint型で表現できる値を超えると結果は未定義となります。
対策としては、limits.hに、各整数型で表現できる値の範囲が定義されてます。そのルート付近以上の値が入力されるとオーバーフローするので、そのような値が入力されたら範囲外エラーにすることです。

投稿2016/02/25 01:44

Chironian

総合スコア23272

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

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

退会済みユーザー

退会済みユーザー

2016/02/25 02:20

ご回答ありがとうございます。 早速unsigned intについて調べて修正してみたいと思います。 また整数のオーバーフローの件ご教示いただきありがとうございました。 いただいたURLを早速拝見させていただきます!!
WoodenHamlet

2016/02/25 02:52

「正の整数」に関して言えば if (score >= 0) // <- score == 0 は正の整数ではナイ { printf("入力した整数までの合計は%dとなります。\n",(1 + score) * score / 2); }
退会済みユーザー

退会済みユーザー

2016/02/25 07:55

すいません、【 (score >= 0) // <- score == 0 】 こちらは、左側は右側でも代用できるという意味でしょうか。
Chironian

2016/02/25 08:49

「正の整数」に0は含まないのでは?って指摘だと思いますよ。
退会済みユーザー

退会済みユーザー

2016/02/25 09:52

そういうことですね! 補足ありがとうございました!!
退会済みユーザー

退会済みユーザー

2016/02/25 14:02

すいません、limits.hを使い、数値がint型で表現できる数を超えた時には、 エラーがでるようにソースを作りたいのですが、 イメージとしてはこのような感じでしょうか。 ※ソースをループにしました。 またプロトタイプ宣言する形で作成したのですが、 この場合、エラーになってしまいます・・・ なにかヒント等いただけると嬉しいです。。。。 #include <stdio.h> #include <limits.h> int over (void); int main(void) { int score , answer , i; printf("正の整数を入力してください。\n"); scanf("%d",&score); answer = 0; i = 1; while (i <= score) { answer = answer + i; i++; } printf("1から%dまでの合計数値は%dです。\n",score,answer); return 0; } int over (void) { if (score > INT_MAX) { printf("error"); } else if (score < 0) { printf("error\n正の整数を入力してください。"); } return 0; }
Chironian

2016/02/25 14:53

頑張ってますね。 まず、単純なC言語的なミスですが、scoreはmain()関数内で定義したローカル変数ですのでmain()関数の中だけしかアクセスできません。over()でアクセスしたい場合はoverへ渡す必要が有ります。(関数について分からない時はここが参考になりそうです。→http://www9.plala.or.jp/sgwr-t/c/sec11.html) 次に、同様にC言語的な問題ですが、over()を呼び出してないです。ということは、チェックされません。 後、while文で処理してますが、そのまんまfor文をわざわざwhile文にしてます。for文で書きましょう。 肝心のオーバーフロー対策ですが、これはなかなか難しいです。 そもそもint型のscoreの値がINT_MAXを超えることはありません。INT_MAXはint型で表現できる最大値ですから。つまり、scoreの値がINT_MAXを超えるかも知れない計算をする前に、超えないことをチェックする必要が有ります。 元のプログラムで、(1+score)*scoreを計算していたと思います。これがINT_MAXを超えるとオーバーフローですね。 つまり、(1+score)*score > INT_MAXが成立するとオーバーフローということですね。しかし、この式は当然ですが、オーバーフローするのでこのままでは計算できません。 そこで、式を変形します。これは中学生レベルの普通の数学です。 (1+socre)*score > INT_MAX (1+score)は正なので、両辺を(1+score)で割って、 score > INT_MAX/(1+score) これが成立するとオーバーフローします。そしで、この式の計算過程でオーバーフローしませんので、判定可能です。 答えを見ると簡単なのですが、初心者が自力で考えつくのはちょっとあり得ないと思いますので、先生が怪訝に思うかも知れません。 でも、新しい方のプログラムであれば、初心者でもありえるかも。単にanswerに足し算する前にオーバーフローしないか確認すればよいのですから。
majiponi

2016/02/26 01:58

Chironianさんのコメント中、誤りがあったので補足。 > そこで、式を変形します。これは中学生レベルの普通の数学です。 > (1+score)*score > INT_MAX > (1+score)は正なので、両辺を(1+score)で割って、 > score > INT_MAX/(1+score) > これが成立するとオーバーフローします。そしで、この式の計算過程でオーバーフローしませんので、判定可能です。 (誤字を修正した上で該当箇所を引用) 「(1+score)は正なので」、の部分が誤りです。もし、scoreがINT_MAXの場合、1+scoreはint型で表現できず、(大体の場合は)オーバーフローした結果、負の値になります。 score > INT_MAX/score - 1 とすれば、オーバーフローせずに検出することができます。
退会済みユーザー

退会済みユーザー

2016/02/26 04:15

Chironianさん、majiponiさん ご回答ありがとうございます。 いやー奥が深いというか難しいですね。。 やっていて楽しいのですが、時間がかかりすぎているのが、 自分でも悔しい点です。。。 ミスのご指摘ありがとうございました。 早速直してみます。 またオーバーフロー対策についても記載いただいた内容を参考にさせていただきます。 ありがとうございました!!
退会済みユーザー

退会済みユーザー

2016/02/26 04:44

すいません、もう1点質問させてください。。。 ご指摘いただいた点直ったかなという状況なのですが、 今後は、オーバーフロー対策のところで、 うまくいかなくなってしまいまいました。 オーバーフローする数値を入力するとerror出るのですが、 そこで止まらず、printfで設定している文章を全部出すような形になってきてしまいました。 具体的にはこのような感じです。 >errorerror >正の整数を入力してください。1から-・・・(数値】までの合計数値は0です。 break文で処理を終わらせようとしたのですが、 ifの中に入れると位置が間違っているとなってしまいます。 すいません、アドバンスいただけますと幸いです。。。 #include <stdio.h> #include <limits.h> int over (int); int main(void) { int score,answer,i; printf("正の整数を入力してください。\n"); scanf("%d",&score); over(score); answer = 0; for (int i = 1; i <= score; i++) { answer = answer + i; } printf("1から%dまでの合計数値は%dです。\n",score,answer); return 0; } int over (int score) { if (score > INT_MAX/score - 1) { printf("error"); break ; } else (score < 0); { printf("error\n正の整数を入力してください。"); } return 0; }
Chironian

2016/02/28 03:55 編集

majiponiさん。 フォローありがとうございます。 scoreがINT_MAXの時を忘れてました。...でも、実はINT_MAXを超える巨大な数字が入力された時は、scanf()自体がオーバーフローするので更なる対策が必要になるのですよ。マジで頭痛いです。 ところで、majiponiさんの案の場合scoreが0の時オーバーフローしますが、score==0はエラーにするのが妥当ですので、そのエラーチェックを先に行えば良いですね。 tomo3さん。 0を入力してみてください。落ちると思います。0で割るとダメなので。 先にscoreが0以下の時のエラーチェックをすればよいですね。 > そこで止まらず、printfで設定している文章を全部出すような形になってきてしまいました。 このような時は、over()関数の戻り値で制御することが多いです。 例えば、異常時0、正常時1を返却し、main()関数でその戻り値をチェックして0なら直ぐにreturnする等です。 あ、あと、どうもタイプミスではないようですので、1つだけ。 「アドバンス(advance)」ではなく「アドバイス(advice)」ですよ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問