🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Q&A

解決済

6回答

2554閲覧

昇順ソート 関数なしでプログラム

chimera

総合スコア5

C

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

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

0グッド

0クリップ

投稿2019/12/21 13:27

編集2019/12/23 14:44

前提・実現したいこと

プログラミング初心者で勉強中です
配列を使って数値を小さい順から表示するプログラムを作りたいです
悪い箇所の指摘をお願いします

■■な機能を実装中に以下のエラーメッセージが発生しました。

コンパイルできましたが、数値入力後に出力されません

//数値10個を配列に入力し小さな数字から順番に //表示するプログラム include<stdio.h> int main(void){ int data[10]; //数字入力用 int i=0; //dt配列カウンタ int ii=0;  //比較判定用カウンタ int x=0; //値入れ替え用変数 int out=0; //並べ替えループ ブレーク変数 //=====================================入力 do{ printf("数値を入力=> "); scanf("%d",&data[i]); i++;}while(i<10); //=====================================処理 do{ for(ii=0;ii<=8;ii++){ if(data[i]<data[i+1]){ x=data[i];     //*交換 data[i]=data[i+1]; //* data[i+1]=x;   //* i++; out+=1; } } }while(out==100); //並べ替え終了 //=====================================出力 printf("昇順ソート :"); for(i=0;i<=9;i++){ printf("%d ",data[i]);} printf("\n"); return 0; }

ご指摘いただいたmarkdownに書き換えました。

試したこと

コメントアウトにて部分的に確認してみると
並べ替え判定以外の部分は正常に動いているようなのですが
原因がわかりません

補足情報(FW/ツールのバージョンなど)

Windows10
terapad
gcc

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

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

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

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

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

meg_

2019/12/21 13:36

「数値入力後に出力されません」とは「"昇順ソート :"」も出力されていないということですか?
chimera

2019/12/21 13:38

はい。 出力されません。
meg_

2019/12/21 13:44

数字を10回入力→プログラム終了 ということですか? それとも無限ループしている感じですか?
chimera

2019/12/21 13:48

返答ありがとうございます。 数字を10回入力までは正常に作動していて、 10回目を入力し終わった後から動かない状態で 現状はcontrol+cで終了させている状態です。 今のところ無限ループにはなっていません。
chimera

2019/12/21 13:50

エラーメッセージなども出てきません。
hayataka2049

2019/12/21 14:21

コードにはコードブロックを使うようにしてください(編集画面の<code>ボタンで挿入可能)
2KOH

2019/12/21 14:46

> 悪い箇所の指摘をお願いします とのことですが、コードの中の「処理」の部分のコードがあまりにメチャクチャで、悪い箇所を一つ一つ指摘するのが難しく、一から書き換えて正解のコードを丸ごと提示したほうが何倍も楽だろうというレベルです。 もっと簡単な問題から取り組むことをおすすめします。 それと、こういう質問では「昇順ソート」ではなく、アルゴリズム名を明示してください。 コードを見る感じだとバブルソートっぽいですが、そうならバブルソートであると記述するようにしてください。
chimera

2019/12/21 19:51

ご指摘いただいたコード挿入の件今後気を付けます
chimera

2019/12/21 19:59

2KOH さん 色々と勉強が足りずお手数かけてしまいすみません。 私自身もそう思います。 コードを頭の中で組み立てる状態でめちゃくちゃになってしまいます。 今後の勉強のためにも、何かいい勉強方法があればご教授ください。 それと、質問の記述方法の指摘についても意味が理解できていませんので、アルゴリズムと昇順ソートの違いも調べてみます。
chimera

2019/12/22 16:25

多数の回答、ご指摘ありがとうございました。 大変恐縮ですが、もし差し支えなければ今後のアドバイスなどもいただけると大変ありがたいです。自分に足りないものが多すぎてどのように勉強進めていけばいいのかよくわかっていません。 現状では学校でc言語の勉強をしていますが、授業だけでは実践で使えないレベルだと承知していますので、皆様の情報を参考にさせてください。
Orlofsky

2019/12/22 16:30

コードを見てもらうためには、Markdown できちんと字下げしましょう。
chimera

2019/12/23 14:49

ご指摘ありがとうございます。 遅くなりましたが、ご指摘いただいたMarkdownに書き換えました。 今後も利用させていただくので、ソースコード記載の際は気をつけます。
chimera

2019/12/24 12:35

皆様にベストアンサーをつけさせていただきたかったのですがかなわず、独断で選ばせていただきました。 大変勉強になりました。ありがとうございました。
guest

回答6

0

最後に入れ替えを行った位置を憶えておくと効率が良くなります。

C

1#include <stdio.h> 2 3#define N 10 4 5int main(void) 6{ 7 int dt[N], x, i, j, k; 8 9 for (i = 0; i < N; i++) { 10 printf("数値を入力してくださいー>"); 11 scanf("%d", &dt[i]); 12 } 13 for (j = N - 1; j > 0; j = k) { // j+1 以降はソート済み 14 for (k = i = 0; i < j; i++) { // k は最後に入れ替えた位置 15 if (dt[i] > dt[i+1]) { // 降順だったら 16 x = dt[i]; dt[i] = dt[i+1]; dt[i+1] = x; // 入れ替える 17 k = i; // 最後に入れ替えた位置を更新 18 } 19 } 20 } 21 printf("昇順ソート :"); 22 for (i = 0; i < N; i++) { 23 printf(" %d", dt[i]); 24 } 25 return 0; 26}

投稿2019/12/23 00:28

編集2019/12/23 04:02
kazuma-s

総合スコア8224

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

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

chimera

2019/12/23 16:56

kazuma-sさんありがとうございます。 早速コンパイルして実行してみました。 正直に申しますとまだ動きが完全に理解できておりません。 ・・・途中にprintfでj,k,i,の動き方を見たりして何となくつかめてきました。 ただやはりfor文の式の入れ方が、自分の定型的な記入とちがって常に動いている変数を変数で比較し合っているので考え付かないループの条件でした。 プログラム書き始める段階では、ソートの比較回数のループは徐々に減らしていければ無駄がないよなぁとは思っていたのですが、コードに書く技術がなく、考えうる限りの考えで書いたのですがやはりできるんだと痛感しております。 このような条件を設定するときにはある種のひらめきのような部分なのでしょうか?それとも経験のたまものなのでしょうか?
guest

0

最初に提示された方のソースを変えました。(forの1重ループ)
降順にソートされているので昇順になるようにしました。
入れ替えが発生する都度、その回数を数え、入れ替えがなくなるまで繰り返すようにしています。

C

1#include <stdio.h> 2int main(void) 3{ 4 5 int data[10]; //数字入力用 6 int i = 0; //dt配列カウンタ 7 //比較判定用カウンタ 8 int x = 0; //値入れ替え用変数 9 int out = 0; //並べ替え回数カウンタ 10 11//=====================================入力 12 do { 13 printf("数値を入力=> "); 14 scanf("%d", &data[i]); 15 i++; 16 } while (i < 10); 17//=====================================処理 18 do { 19 out = 0; //並べ替え回数クリア 20 for (i = 0; i <= 8; i++) { 21 if (data[i] > data[i + 1]) { 22 x = data[i]; //*交換 23 data[i] = data[i + 1]; //* 24 data[i + 1] = x; //*並べ替え回数カウントアップ 25 out += 1; 26 } 27 } 28 } while (out != 0); //並べ替えがなくなるまで繰り返す 29//=====================================出力 30 printf("昇順ソート :"); 31 for (i = 0; i <= 9; i++) { 32 printf("%d ", data[i]); 33 } 34 printf("\n"); 35 return 0; 36} 37

投稿2019/12/22 03:57

tatsu99

総合スコア5493

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

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

chimera

2019/12/22 16:12

ご指摘ありがとうございます。 並べ替え判定の関係演算子の使い方をa>b(aよりbのほうが大きい)であれば交換するに変えさせていただきます。 そして、並べ替えが終了した際のブレーク手法として使われている等価演算子(!=)についても最初意味がよくわからなかったのですが、 whileの条件式が真であれば継続、偽であればブレークという判定を 並べ替えカウンターにより、終了時0になるので、(0!=0)となり、偽になりますので、whileの条件式に偽が入りブレークになるという使い方が上手だなと感じました。そういう使い方も有りなんだと気づけました! for,while,do~whileしかりですが、使い方って色々あって奥が深いんですね。大変勉強になりました。ありがとうございました。
chimera

2019/12/22 16:13

(bよりaのほうが大きい)でした。失礼しました
guest

0

2重ループの方のソースを変えました。
あきらかな間違いは、
for(i=0;i<=9;i++){
の個所です。
この場合、i=9で実行されるので、dt[i+1]=x;のとき、dt[10]=xとなり
メモリが破壊されます。for(i=0;i<=8;i++){としないといけません。

次は、解釈の問題ですが、あなたのコードの結果ではdtの配列に降順に設定されています。
表示するときに、お尻から表示しているので、画面には、昇順に出力されますが・・・・

dtの配列に昇順に設定されるようにするためには、以下のようにすべきです。

C

1#include <stdio.h> 2int main(void) 3{ 4 5 int dt[10], x, i = 0, ii = 0; 6//入力 7 for (i = 0; i < 10; i++) { 8 printf("数値を入力してくださいー>"); 9 scanf("%d", &dt[i]); 10 } 11 12 for (ii = 0; ii <= 9; ii++) { 13 for (i = 0; i <= 8; i++) { 14 if (dt[i] > dt[i + 1]) { 15/*入れ替え*/ x = dt[i]; 16 dt[i] = dt[i + 1]; 17 dt[i + 1] = x; 18 } 19 } 20 } 21 printf("昇順ソート :"); 22 for (ii = 0; ii < 10; ii++) { 23 printf(" %d", dt[ii]); 24 } 25 26 return (0); 27} 28

投稿2019/12/22 03:53

tatsu99

総合スコア5493

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

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

chimera

2019/12/22 14:30

ご指摘ありがとうございます。 おっしゃる通りで、範囲外のところまで比較されてしまう条件になっていました。メモリに悪影響が出るというのも初めて知りました。 組み込みのためにc言語を勉強しているので、メモリの概念についても勉強していきます。 私のコードですと、最後にわざわざ10番目から1番目に出力するという労力が無駄でした。ここについても条件設定の際に上手に考えられず結果的に最後に必要な状態で出力してごまかすような格好になってしまっています。 判定から無駄がないコードをかけるように勉強します。 ありがとうございました。
guest

0

ベストアンサー

やろうとしていることはバブルソートですね。
回答として出された方に対してコメントします。
まずdt[i+1]がdt[10]になる可能性があるのがまずいです。

それ以外は大体できていますが、効率に問題があるでしょう。

C

1printf("昇順ソート :"); 2for(ii = 9;ii >= 0; ii--) 3 printf(" %d",dt[ii]);

まず出力部で出力順序を反転させるならソート時の判定を逆にしておくべきです。
すなわち

C

1for (ii = 0; ii <= 9; ii++) { 2 for (i = 0; i < 9; i++) { 3 if (dt[i] > dt[i + 1]) { 4 x = dt[i]; 5 dt[i] = dt[i + 1]; 6 dt[i + 1] = x; 7 } 8 } 9}

のようにすれば昇順にソートしてくれます。
更に、1度目のループで配列の最大値が一番後ろに移動していることが保証されているので
2度目のループでは最後の要素をチェックする必要はなく、ソートの範囲を狭めることができます。

C

1for (len = 10; len >= 2; len--) { 2 for (i = 0; i < len - 1; i++) { 3 if (dt[i] > dt[i + 1]) { 4 x = dt[i]; 5 dt[i] = dt[i + 1]; 6 dt[i + 1] = x; 7 } 8 } 9}

lenはソート範囲の長さで、長さ2の時までチェックを行います。
内側のループはi+1にアクセスすることがあるので、iがlen-2までになるように
i < len - 1 を終了条件にします。

投稿2019/12/22 03:22

編集2019/12/22 04:07
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

chimera

2019/12/22 14:20

ご指摘ありがとうございます もやっとしていた部分がズバリ指摘されていて、ものすごく勉強になりました。 [dt]+1のアクセス範囲の考え方。判定条件で小さいほうから一発で並べ替えが終わるようにする。 また、自分の考えが及ばなかった部分についても、なるほど!と気づけました。 最初の並べ替えで最大値をdt[9]に格納できるので、二回目の並べ替えループ時にはdt[9]は省いて、dt[8]までチェックするの部分にです。 それを繰り返してどんどんループを減らせるんですね! 外ループと内ループの変数の使い方が大変勉強になりました。 ほかのプログラムにも応用が利きそうなのでfor文の使い方をもっと勉強してみます ありがとうございました!
guest

0

何も表示されないというのがわかりませんが、ぱっと見で間違っているところは

C

1}while(out==100); //並べ替え終了

のループ条件。while文のループ条件は条件が「真」である間なので、outが100でないとループは回りません。並べ替えを一箇所行ったところで、このループを抜け出て、次に制御が移ります。
(なので、本当はここで「昇順ソート」が表示されるはずなんですよね)

後、上限値等の設定がバラバラです。入力する数字の個数は10個であるのに対し、ソート対象になっているのが9個になっています。

後、変数iが再初期化されていないので、data[10]からソート対象にしてますね。これで、触っちゃいけないところに触っちゃってるんじゃないかな。

とりあえず、要素数やらをそれを扱う変数を見直した方がいいと思います。

投稿2019/12/21 14:20

archiver

総合スコア1567

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

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

0

自分なりに色々変えてみて何とか出力されました。

include<stdio.h>

1int main(void){ 2 3int dt[10],x,i=0,ii=0; 4//入力 5 for(i=0;i<10;i++){ 6 printf("数値を入力してくださいー>"); 7 scanf("%d",&dt[i]); 8 } 9 10 for(ii=0;ii<=9;ii++){ 11 for(i=0;i<=9;i++){ 12 if(dt[i]<dt[i+1]){ 13/*入れ替え*/ x=dt[i]; dt[i]=dt[i+1]; dt[i+1]=x;} 14       } 15    } 16 printf("昇順ソート :"); 17//出力 for(ii=9;ii>=0;ii--){ printf(" %d",dt[ii]);} 18 19 return (0); 20} 21コード

for文の入力
for文の二重ループで並べ替え
に変更しました。
プログラムは動きましたが、私自身の勉強のためにも
改善案のご指摘を頂戴したく思います。
ぜひよろしくお願いします。

投稿2019/12/21 20:10

chimera

総合スコア5

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

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

kaina

2019/12/24 03:19

インデントがバラバラです、いい加減なインデントでは無く、きちんと基礎を勉強して下さい。 また、全角スペースが混在しています、エラーとなる場合もありますので、 こちらも注意して下さい。
chimera

2019/12/24 12:29

ご指摘ありがとうございます。 インデントについての基礎がなっていませんでした。 文章の段落のように思っていましたので、段落を下げてわかりやすくするよう心掛けていたのですが、見る人によって感覚が違うのでよりお手本的なインデントを勉強したいと思います。 関数の終わりの}だったり、制御文の終わりの}が一番わかりやすいのはどこなのか試行錯誤してました。 今回ソースコードのUPの仕方もまずかったので、皆さんに見ていただけるようにきをつけます。 また、参考にするコードによって若干の違いがあるので具体的に示していただけると大変ありがたいです。 今私が勉強している教科書にはタブでの字下げ、意味の違う文は間隔をあける。などとしか書いてありませんでしたので。またこのサイトで色々拝見していく中で自分なりによりよく見やすいように修正していきますので、また機会があればご指摘頂戴したく思います。 ありがとうございました。
javahack

2019/12/24 16:46

横から失礼します。 インデントについては「コーディング規約」をキーワードに検索するといろいろでてきますので参考にしてください。 言語によっては標準規約が存在する場合もあります。
kaina

2019/12/25 00:56

プログラムはテキストエディタで行っているのでしょうか? もしそうであればIDE(Integrated Development Environment) の使用を検討してみて下さい。 未だとVisual Studio Codeが流行りかな? IDEを使用すると自動でインデントを付与する設定を利用出来ます。 他にも様々な利便性がありますので、もし使用していないのであれば、導入して下さい。
chimera

2019/12/25 13:16

コーディング規約ですね、検索してみます。当分c言語の勉強になると思うのでよく見ておきます。
chimera

2019/12/25 13:40

プログラムは」TERAパッド、 勉強場所ではubuntuでnanoを使っています。 統合開発環境は使わないでプログラム言語の勉強をしています。 ある程度プログラムの周辺知識がわかってきたら統合開発環境を使おうと思います。
javahack

2019/12/25 14:27 編集

再度失礼します。 kainaさんの提案を支持します。初心者だからこそIDEを使うべき。 teratailに寄せられる初心者の質問の多くは ・関数、変数の綴り間違い ・全角スペース使用 ・閉じカッコが足りない(または多すぎ) といった単純なミスです。 これらのことはIDEを使っていればほぼ回避できるものです。 スタート地点で躓いて学習が進まないのは時間の無駄です。
chimera

2019/12/25 15:19

ご指摘ありがとうございます。 確かに言われている事はその通りだと思います。 学習機関の縛りのような物なのでしょうか? 最初期のことは何もわからずXcodeでc言語のコードを書いてたのですが、 使わないで勉強していくと言う事は、コードを書いてコンパイルやリンカ、アセンブリ、機械語周辺の流れなどの仕組みを知ってもらうためという意図なのでしょうか?
kaina

2019/12/26 11:55

別にIDEを使用したからといってコンパイルやリンカ、アセンブラなどの仕組みが 理解出来ないということは無いと思います。 結局そういった深い部分まで学習する意欲が一番大事であり、今回質問したような 単純ミスはIDEを使用することでかなりの部分削減することが可能となります。 その削減できた時間を使用し、コンパイルやリンカ、アセンブリ、機械語周辺の流れなどの 仕組みを学習出来ると考えてはいかがでしょうか?
chimera

2019/12/26 13:39

確かにその通りだと思います。 できる限り早くコードが書けるようになりたいので、自宅ではXCodeなどで勉強したいと思います。 ハードウェア寄りの言語の勉強も大事だと思います、、、が今はまずc言語の基本部分を固めながら勉強を進めたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問