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

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

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

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

ソート

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

Q&A

解決済

2回答

6864閲覧

C言語で都道府県を表示するプログラムで、選択ソートが機能していません

TK0107

総合スコア11

C

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

ソート

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

0グッド

0クリップ

投稿2017/06/12 13:53

名前、面積、人口、人口密度からなる構造体を配列で宣言し、テキストファイルから都道府県名、人口、面積を読み取って、そこから人口密度を計算し、配列に代入したら、人口密度でソート(選択ソート)し、表示せよという問題です。

C

1#include <stdio.h> 2#include <string.h> 3 4typedef struct 5{ 6 char name[40]; 7 int population; 8 int area; 9 double density; 10} pref_t; 11 12pref_t syokika(char name[], int population, int area) 13{ 14 pref_t z; 15 strcpy(z.name, name); 16 z.population = population; 17 z.area = area; 18 z.density = (double)population / (double)area; 19 20 return (z); 21} 22 23void sentaku_sort(pref_t pref[47]) 24{ 25 26 int i, j, p; 27 double min; 28 pref_t temp, mini; 29 30 for (i = 0; i < 46; i++) 31 { 32 min = pref[i].density;//暫定的に先頭を最小の人口密度とする 33 for (j = i + 1; j < 47; j++) //このループを抜けるとminiに人口密度が最小の都道府県が入る 34 { 35 if (min > pref[j].density) 36 { 37 p = j; //人口密度最小がどこにあったのかを記憶しておく 38 mini = pref[j]; //人口密度が最小の都道府県そのものを入れる 39 } 40 } //中のループここまで 41 //ここからは実際に構造体ごと入れ替える 42 temp = pref[i]; 43 pref[i] = mini; 44 pref[p] = temp; 45 } 46} 47 48int main() 49{ 50 51 char name[40]; 52 int area; 53 int population; 54 FILE *fp; 55 fp = fopen("prefectures.txt", "r"); 56 pref_t pref[47]; 57 int i = 0; 58 59 if (fp == NULL) 60 { 61 printf("そのファイルは存在しません。\n"); 62 } 63 else 64 { 65 while (fscanf(fp, "Name:%s Area:%d Population:%d\n", name, &area, &population) == 3) 66 { 67 pref[i] = syokika(name, population, area); 68 i++; 69 } 70 printf("%s\n",pref[46].name);//test1 71 sentaku_sort(pref); 72 printf("ここまでその2\n");//test2 73 74 for (i = 0; i < 47; i++) 75 { 76 printf("都道府県名:%s,面積:%d,人口:%d,人口密度:%lf\n", pref[i].name, pref[i].area, pref[i].population, pref[i].density); 77 } 78 79 } 80 81 fclose(fp); 82 return 0; 83} 84 85``````prefectures.txt 86 87Name:HOKKAIDO Area:83454 Population:5679000 88 89Name:AOMORI Area:9235 Population:1474000 90 919293 94Name:OKINAWA Area:2272 Population:1329000 95

sentaku_sortが機能しておらず、実行してもtest2の「ここまでその2」が表示されていません。
test1はきちんと表示できているので、配列に代入自体は実装できています。
何か間違った書き方をしてしまっているのでしょうか…
ご教授お願い致します。

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

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

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

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

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

guest

回答2

0

ベストアンサー

ソートの部分を少し修正してみました。

c

1#include <stdio.h> 2#include <string.h> 3 4typedef struct 5{ 6 char name[40]; 7 int population; 8 int area; 9 double density; 10} pref_t; 11 12pref_t syokika(char name[], int population, int area) 13{ 14 pref_t z; 15 strcpy(z.name, name); 16 z.population = population; 17 z.area = area; 18 z.density = (double)population / (double)area; 19 20 return (z); 21} 22 23void sentaku_sort(pref_t pref[47]) 24{ 25 26 int i, j, p; 27 double min; 28 pref_t temp, mini; 29 int sw = 0; //入れ替えスイッチ 30 31 for (i = 0; i < 46; i++) 32 { 33 sw=0; 34 min = pref[i].density;//暫定的に先頭を最小の人口密度とする 35 for (j = i + 1; j < 47; j++) //このループを抜けるとminiに人口密度が最小の都道府県が入る 36 { 37 if (min > pref[j].density) 38 { 39 p = j; //人口密度最小がどこにあったのかを記憶しておく 40 mini = pref[j]; //人口密度が最小の都道府県そのものを入れる 41 sw=1; 42 } 43 } //中のループここまで 44 //ここからは実際に構造体ごと入れ替える 45 if (sw==1){ 46 temp = pref[i]; 47 pref[i] = mini; 48 pref[p] = temp; 49 i--; //入れ替えが発生開始点戻し 50 } 51 } 52} 53 54int main() 55{ 56 57 char name[40]; 58 int area; 59 int population; 60 FILE *fp; 61 fp = fopen("prefectures.txt", "r"); 62 pref_t pref[47]; 63 int i = 0; 64 65 if (fp == NULL) 66 { 67 printf("そのファイルは存在しません。\n"); 68 } 69 else 70 { 71 while (fscanf(fp, "Name:%s Area:%d Population:%d\n", name, &area, &population) == 3) 72 { 73 pref[i] = syokika(name, population, area); 74 i++; 75 } 76 printf("%s\n",pref[46].name);//test1 77 sentaku_sort(pref); 78 printf("ここまでその2\n");//test2 79 80 for (i = 0; i < 47; i++) 81 { 82 printf("都道府県名:%s,面積:%d,人口:%d,人口密度:%lf\n", pref[i].name, pref[i].area, pref[i].population, pref[i].density); 83 } 84 85 } 86 87 fclose(fp); 88 return 0; 89} 90

こちらの方が分かり易いと思います。最小値で入れ替えが発生します。

c

1#include <stdio.h> 2#include <string.h> 3 4typedef struct 5{ 6 char name[40]; 7 int population; 8 int area; 9 double density; 10} pref_t; 11 12pref_t syokika(char name[], int population, int area) 13{ 14 pref_t z; 15 strcpy(z.name, name); 16 z.population = population; 17 z.area = area; 18 z.density = (double)population / (double)area; 19 20 return (z); 21} 22 23void sentaku_sort(pref_t pref[47]) 24{ 25 26 int i, j, p; 27 double min; 28 pref_t temp, mini; 29 int sw = 0; //入れ替えスイッチ 30 31 for (i = 0; i < 46; i++) 32 { 33 sw=0; 34 mini = pref[i]; //暫定的に先頭を最小の人口密度とする 35 for (j = i + 1; j < 47; j++) //このループを抜けるとminiに人口密度が最小の都道府県が入る 36 { 37 if (mini.density > pref[j].density) 38 { 39 p = j; //人口密度最小がどこにあったのかを記憶しておく 40 mini = pref[j]; //人口密度が最小の都道府県そのものを入れる 41 sw=1; 42 } 43 } //中のループここまで 44 //ここからは実際に構造体ごと入れ替える 45 if (sw==1){ 46 temp = pref[i]; 47 pref[i] = mini; 48 pref[p] = temp; 49 } 50 } 51} 52 53int main() 54{ 55 56 char name[40]; 57 int area; 58 int population; 59 FILE *fp; 60 fp = fopen("prefectures.txt", "r"); 61 pref_t pref[47]; 62 int i = 0; 63 64 if (fp == NULL) 65 { 66 printf("そのファイルは存在しません。\n"); 67 } 68 else 69 { 70 while (fscanf(fp, "Name:%s Area:%d Population:%d\n", name, &area, &population) == 3) 71 { 72 pref[i] = syokika(name, population, area); 73 i++; 74 } 75 printf("%s\n",pref[46].name);//test1 76 sentaku_sort(pref); 77 printf("ここまでその2\n");//test2 78 79 for (i = 0; i < 47; i++) 80 { 81 printf("都道府県名:%s,面積:%d,人口:%d,人口密度:%lf\n", pref[i].name, pref[i].area, pref[i].population, pref[i].density); 82 } 83 84 } 85 86 fclose(fp); 87 return 0; 88}

投稿2017/06/12 15:38

編集2017/06/12 16:54
A.Ichi

総合スコア4070

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

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

TK0107

2017/06/12 16:17

ありがとうございます!正常に動作しました。 ただ、なぜ入れ替えるフラグ?を設定すると正しく動作したのかが掴みにくかったです。 良ければ解説お願いできないでしょうか?よろしくお願いいたします。
A.Ichi

2017/06/13 01:59 編集

一般的ですがバブルソートです。入れ替えが発生したら同じ開始位置に戻り比較を開始します。入れ替えが発生しなくなったら時点で終了するのが良いですが有る分回ってます。泡のように水面に浮いていくのでバブルソートと言うのでしょうね。
A.Ichi

2017/06/13 02:00

追加の方をご参考としてください。
guest

0

選択ソートのやり方が正しくないです。
test2にいかないのはiのループで最初に代入したminがもし最小だった場合、jのループの min > pref[j].density は常に偽ですから実行されません。
そうするとpが初期化されていないので不定値になるため適当なところにpref[p] = tempを実行した結果
アクセス違反でクラッシュしてるんだと思います。

一度別プログラムで整数の配列とかで選択ソートを作ってみてはどうでしょう?

投稿2017/06/12 14:27

編集2017/06/12 16:26
toki_td

総合スコア2850

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

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

TK0107

2017/06/12 14:43

void sentaku_sort(int a[], int n) { int i, j, p , w , k , tmp , min; for (i = 0; i < n-1; i++) { min = a[i]; for(j = i+1; j < n ; j++) { if(min > a[j]) { p = j; min = a[j]; } } tmp = a[i]; a[i] = min; a[p] = tmp; } } 元々、選択ソートを実装する問題があったので、そこから真似たのですが、真似の仕方がまずかったのでしょうか?
toki_td

2017/06/12 16:23

(符号が逆と書いてたのは僕が見間違えてました。すみません、回答修正済みです) そのソートが正しくないですね。0 2 1とかをソートしようとしたら a[p] = tmp の行でpが不定値のためクラッシュするか変な値になるんじゃないかな?たまたま動くかもしれませんけど。 A.Ichiさんの書かれているようにフラグを持たせるか min = a[i]; の次に p = i; としておく必要があります。
toki_td

2017/06/12 16:29

あとminiも代入してないか。フラグのほうがいいですね。
TK0107

2017/06/13 03:37

ありがとうございます。確かに不定を代入しようとしてクラッシュしていました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問