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

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

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

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

Q&A

解決済

5回答

468閲覧

c言語の配列のプログラム問題

takemark20

総合スコア9

C

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

0グッド

0クリップ

投稿2018/05/01 15:38

前提・実現したいこと

6 人で50m走を走ったときの各コースのタイムと順位を配列に格納し、順位順にコースとタイムを表示するプログラムを作成しなさい。

1コース 6.8秒 2位
2コース 6.5秒 1位
3コース 7.9秒 6位
4コース 7.2秒 4位
5コース 7.1秒 3位
6コース 7.6秒 5位
というのを順位順に並びなおしたいです。

なお、それぞれの配列は変えずにそのまま使用したいです。

発生している問題・エラーメッセージ

上手く並べられません。

<実行結果>
1コース 6.8秒 2位
2コース 6.5秒 1位
3コース 7.9秒 6位
4コース 7.2秒 4位
5コース 7.1秒 3位
6コース 7.6秒 5位

1位 1コース 6.5秒
2位 2コース 6.0秒
3位 3コース 7.1秒
4位 4コース 7.0秒
5位 5コース 7.0秒
6位 6コース 7.6秒

このようになります。
例えばtimeという配列とjyuniという配列を関連づける、といったことは可能なのでしょうか?

下のソースコードを見てもらえばわかるんですが、j[6]を順位順に並べ替えても、
c6とt6を順位順に並べられません。

該当のソースコード

c

1#include<stdio.h> 2int main() 3{ 4 float t[6] = {6.8, 6.5, 7.9, 7.2, 7.1, 7.6}; 5 int j[6] = {2, 1, 6, 4, 3, 5}; 6 int c[6] = {1, 2, 3, 4, 5, 6}; 7 int i, k, work, work2; 8 9 //配列表示 10 for(i=0; i<6; i++){ 11 printf("%dコース %.1f秒 %d位\n", c[i], t[i], j[i]); 12 } 13 14 //並び替え 15 for(i=0; i<=3; i++){ 16 for(k=5; k>=i+1; k--){ 17 if(j[k]<j[k-1]){ 18 work = j[k]; 19 j[k] = j[k-1]; 20 j[k-1] = work; 21 } 22 } 23 } 24 printf("\n"); 25 26 for(i=0; i<=3; i++){ 27 for(k=i+1; k<=5; k++){ 28 if(t[i]>t[k]){ 29 work2 = t[i]; 30 t[i] = t[k]; 31 t[k] = work2; 32 } 33 } 34 } 35 printf("\n"); 36 37 //結果表示 38 for(i=0; i<6; i++){ 39 printf("%d位 %dコース %.1f秒\n", j[i], c[i], t[i]); 40 } 41 printf("\n"); 42 return 0; 43} 44

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

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

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

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

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

guest

回答5

0

既に答えが出ていますので参考までに

本問題は不自然です。

順位が与えられているのに並び替えを要求するというのはナンセンスです。本来ならば並び替えてから順位を決めるべきです。

本課題の場合はバケットソートができてしまいます。

これは特殊なソートアルゴリズムであり、限定された状況下でしか使用できず、汎用性がありません。ただし、この時間計算量はO(N)であり理論上のヒープ、マージソートを上回る性能となります。もちろん、実用上はクイックソートよりも速くなります。

(脱線しますが、クイックソートの時間計算量はO(N×N)です。マージソート、ヒープソートと同じくO(N×logN)と記述する資料をよく見かけますが、理論上ではクイックソートの時間計算量はマージソート、ヒープソートに劣ります。実用上、余程極端でない限りはクイックソートの方が速いですが。)

バケットソートの具体的なアルゴリズム

大きな配列を用意し、ソートキーをインデックスとして値を書き込んでいきます。この処理が終わったら、配列の先頭から順に読み取れば整列済みのデータになっています。(本課題の場合は、「順位」がソートキーです)

投稿2018/05/02 21:26

HogeAnimalLover

総合スコア4830

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

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

kawakawa2018

2018/05/02 22:37

コメントするか迷いましたが、 BeatStarさんの回答とコメントの内容を 見て納得しました。 前程があって、それがよい回答案、解決策を妨げているとき どうやって質問者に伝えるか悩みます。 回答を求められても 前程の確かさ、条件の正しさがないと回答できないと 思います。 はっきりと意見してる人がいるなと すごいなと、思いました。 おかしいと思って、この質問をスルーした人も多い?。 即答すると加点の仕組みも???な感じですね。 どう回答をするのがいいのか、考えるきっかけを。 いいプラクティスを 得ました。 ありがとうございます。
HogeAnimalLover

2018/05/03 15:05

ご意見ありがとうございます。私は本件のように、質問の本筋に大きくそれた回答もかなりしています。これは賛否両論のようで、マイナス評価をもらうことも若干あります。 (このGWにたまたま気が付いたのですが、過去の私の脱線した回答について某大型掲示板でネタにされていました。その質問自体も漠然としたものであり、叩かれてもいましたが、それだけ注目もされているのだなあと感慨深いものでもありました。)
kawakawa2018

2018/05/03 15:15

そうでしたか。うまくteratailを使いこなさないといけないですね。 ”この質問に関して”は おかしいと思って、この質問をスルーした人も ”若干名”いるはずです この点でHogeAnimalLoverさんは正しい。 いずれにせよ注意することもあるとわかりました。 気をつけて利用します。 ありがとうございます。
guest

0

ベストアンサー

順序について並び替えるときに、他の要素も一緒に並び替えちゃえばいいです。

C

1for(i=0; i<=3; i++){ 2 for(k=5; k>=i+1; k--){ 3 if(j[k]<j[k-1]){ 4 // jに関するスワップ 5 work = j[k]; 6 j[k] = j[k-1]; 7 j[k-1] = work; 8 9 // tに関するスワップ 10 ... 11 12 // cに関するスワップ 13 ... 14 } 15 } 16}

それと、変数名を考え直すよう、強く推奨します
名前が適当すぎると、後から読み返す際に無駄な苦労をしなければなりません。

投稿2018/05/01 15:43

LouiS0616

総合スコア35660

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

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

takemark20

2018/05/02 09:52

回答ありがとうございます。 その方法でしっかりと動いたんですが、タイムの小数点以下が上手く表示されません。 1位 2コース 6.0秒 2位 1コース 6.8秒 3位 5コース 7.0秒 4位 4コース 7.0秒 5位 6コース 7.0秒 6位 3コース 7.9秒 このようになってしまいます。 どうすればよいでしょうか? それと、変数名のアドバイスありがとうございます。
LouiS0616

2018/05/02 09:55

データを入れ替える際にうっかりミスをしているのが濃厚です。 今一度確認してみてください。
takemark20

2018/05/03 10:05

for(i=0; i<=3; i++){ for(k=5; k>=i+1; k--){ if(j[k]<j[k-1]){ //順位 work = j[k]; j[k] = j[k-1]; j[k-1] = work; //時間 work2 = t[k]; t[k] = t[k-1]; t[k-1] = work2; このように書いたのですが、どこが問題かわかりません。 どういう事でしょうか?
LouiS0616

2018/05/03 10:06

work2の型がintだからじゃないですか?
takemark20

2018/05/03 14:39

そういえばそうでした... 見落としてました、無事にうごきました。ありがとうございました。
guest

0

配列のインデックスを格納した配列を用意して、それをソートするのが良いでしょう。
また、ソートは自前で実装する必要はありません。つman qsort

c

1#include <stdio.h> 2#include <stdlib.h> 3 4int cmp_t(const int *p1, const int *p2, float *t) 5{ 6 if (t[*p1] < t[*p2]) { 7 return -1; 8 } 9 if (t[*p1] > t[*p2]) { 10 return 1; 11 } 12 return 0; 13} 14 15int main(void) 16{ 17 float t[6] = {6.8, 6.5, 7.9, 7.2, 7.1, 7.6}; 18 int j[6] = {2, 1, 6, 4, 3, 5}; 19 int c[6] = {1, 2, 3, 4, 5, 6}; 20 int idx[6] = {0, 1, 2, 3, 4, 5}; 21 int i; 22 23 for (i = 0; i < 6; i++) { 24 printf("%dコース %.1f秒 %d位\n", c[idx[i]], t[idx[i]], j[idx[i]]); 25 } 26 printf("\n"); 27 28 qsort_r(idx, 6, sizeof(int), cmp_t, t); 29 30 for (i = 0; i < 6; i++) { 31 printf("%d位 %dコース %.1f秒\n", j[idx[i]], c[idx[i]], t[idx[i]]); 32 } 33 printf("\n"); 34}

投稿2018/05/01 18:58

編集2018/05/01 19:05
hichon

総合スコア5737

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

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

0

正解は他の方だと思いますが、私ならこういう風にする...という感じで書きますね。

方法1: 構造体を用意し、それに格納する。その後、ソートして表示する。

たとえば、

C

1struct Time{ 2 float t; // タイム 3 int c; // コース 4 int n; // 順位 ( number ) 5};

として、

Time::t を基準にしてソートするとか。

でも、"配列を使って"...ですからねぇ。イメージできない...

投稿2018/05/02 02:36

BeatStar

総合スコア4958

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

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

a_saitoh

2018/05/02 07:21

構造体の配列も配列には違いないので、「配列を使って。」る解答になってるとおもいますよ
BeatStar

2018/05/02 08:42

a_saitohさん。やっぱりそうですよね。 やはり、私なら構造体でやりますね。
HogeAnimalLover

2018/05/02 21:06

自分も問題文読んで同様に思ったところです。本課題では順位が天下り的に提示されていますが、順位を決定してから並び替えるならば、先に並び替えた方が手っ取り早いですね。
guest

0

実際の競技会でレース内容(各コースのタイムと順位)を記録したら、それを電子掲示板に表示するという状況が想像されますね。

コース数の上限はそんなに多くないでしょうから、ソートせずに単に順位別に検索して表示していってみました。

* 同着だった場合は、コース番号の若い方が先に表示されます。
* コースが棄権や失格だった場合は順位の配列に コース番号以外の数 (0 とか、99 とか)を入力することにします。

order.c

c

1#include<stdio.h> 2 3#define NUM (6) // コースの数 4 5int main() 6{ 7 float time[NUM] = {6.8, 6.5, 7.9, 7.2, 7.1, 7.6}; 8 int runk[NUM] = {2, 1, 6, 4, 3, 5}; 9 10 // 配列表示 11 for (int i = 0; i < NUM; i++) { 12 printf("%dコース %.1f秒 %d位\n", i + 1, time[i], runk[i]); 13 } 14 printf("\n"); 15 16 // 順位順に表示 17 for (int j = 1; j <= NUM; j++) { 18 // 順位が j のコースを探す 19 for (int i = 0; i < NUM; i++) { 20 if (runk[i] == j) { 21 // 見つけたコース番号、タイムを表示する 22 printf("%d位 %dコース %.1f秒\n", j, i + 1, time[i]); 23 } 24 } 25 } 26 return 0; 27}

実行例
イメージ説明

投稿2018/05/03 00:08

katoy

総合スコア22324

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問