バケットソート

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
うらはんちょう

バケットソート

#1

投稿記事 by うらはんちょう » 11年前

かなり初心者です。
バケットソートのプログラムを作っていてわからなくなったので質問します。
.txtファイルに1000以下のid(数字)が6つ書いてあって

ex)
12
350
159
...

この.txtファイルを読み込んで、バケットソートで昇順に並べ替えたいのですが、以下のコードのコメントの上の行が通りません
最初の void bucket_sort(A* as[], int n) ここは変えずに結果を出したいのです(学校の課題なので)がどうすればよいでしょうか?
コンパイルしてみると、 配列の添字が整数型ではありません と言われます。

コード:

void bucket_sort(A* as[], int n)
{
int i;
int j = 0;
A* buckets[1000] = {};

for(i = 0; i< 1000; i++){
buckets = 0;
}

for(i =0; i < n; i++) {

buckets[as] = as;

/*
asは.txtファイルのid それを配列buckets[]のid番目にいれたい
*/

}
for(i = 0; i<1000; i++){
if(0 < buckets){
as[j++] = buckets;
}
}
return;
}

non
記事: 1097
登録日時: 13年前

Re: バケットソート

#2

投稿記事 by non » 11年前

void bucket_sort(A* as[], int n)

A*ってのはなんですか?
説明をお願いします。
non

うらはんちょう

Re: バケットソート

#3

投稿記事 by うらはんちょう » 11年前

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define name_size 40
#define students_size 10

typedef struct
{
int id;
char name[name_size];
}A;

コードの最初はこんな感じです。

non
記事: 1097
登録日時: 13年前

Re: バケットソート

#4

投稿記事 by non » 11年前

asは整数じゃないよってのはわかりますが、全体像が見えませんね。
構造体の説明をするか、プログラムの全部を載せるか、情報が不足してます。
初心者とは言っても、構造体やファイル入力まですでに習っているのですし、もう少し詳しく情報を伝えてください。
non

うらはんちょう

Re: バケットソート

#5

投稿記事 by うらはんちょう » 11年前

プログラム全部のせます
いままでのプログラムの A と as は
A → Student
as → students

と考えてください。


#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define name_size 40
#define students_size 10

typedef struct
{
int id;
char name[name_size];
}Student;

void initialize_student(Student* student, int id,char* name);
int read_students(char* filename, Student* student[]);
void bucket_sort(Student* students[], int n);
void print_names(Student* students[], int n);

int main(void)
{
Student* student[40];
int i;
int students_count; /*ファイルから読み込んだ学生の人数*/
char filename[] = "student.txt";

students_count = read_students(filename,student);

bucket_sort(student, students_count);
print_names(student, students_count);

return 0;
}







void bucket_sort(Student* students[], int n)
{
int i;
int j = 0;
Student* buckets[1000] = {};

for(i = 0; i< 1000; i++){
buckets = 0;
}

for(i =0; i < n; i++) {



buckets[students] = students;

/*
studentsは.txtファイルのid それを配列bucket[]のid番目にいれたい
*/

}
for(i = 0; i<1000; i++){
if(0 < buckets){
students[j++] = buckets;
}
}
return;
}


void initialize_student(Student* student, int id, char* name)
{
student->id = id;
strcpy(student->name, name);
return;
}

int read_students(char* filename, Student* student[])
{
FILE* file;
int read_result;
int count = 0;
int id,result;
char name[name_size];

file = fopen(filename,"r");
if(file == NULL){
printf("File not exists\n");
return 1;
}

do{
result = fscanf(file,"%d %s",&id, name);
if(result == 2){
student[count] = calloc(sizeof(Student),1);
if(student[count] == NULL) exit(EXIT_FAILURE);
initialize_student(student[count],id,name);
count++;
}
} while (result != EOF);

fclose(file);
return count;
}

void print_names(Student* students[],int n)
{
int i;
for(i = 0; i < n; i++){
printf("%s\n",students->name);
}
return;
}

non
記事: 1097
登録日時: 13年前

Re: バケットソート

#6

投稿記事 by non » 11年前

同じidのものをbuckets入れてしまえば、同じidがあると、nameが上書きされてしまいますが、同一のidはないのでしょうか?

また
Student* buckets[1000] = {};
は、どういう意味で使ってますか?
non

うらはんちょう

Re: バケットソート

#7

投稿記事 by うらはんちょう » 11年前

同一のIDはないという前提でお願いします。

バケットソートのところだけ書く課題で
Student* buckets[1000] = {};
のところは、もともとかいてあったものなんですけど

おそらく、配列buckets[]とは
要素が1000個入る箱を用意したってことだと思います。

non
記事: 1097
登録日時: 13年前

Re: バケットソート

#8

投稿記事 by non » 11年前

うらはんちょう さんが書きました:同一のIDはないという前提でお願いします。

バケットソートのところだけ書く課題で
Student* buckets[1000] = {};
のところは、もともとかいてあったものなんですけど
すると、ポインタの配列を使えってことなのですね。
Student backets[1000];
ではないのは間違いないですね。
うらはんちょう さんが書きました: おそらく、配列buckets[]とは
要素が1000個入る箱を用意したってことだと思います。
ポインタの配列を1000個用意しているのですよ。
実際のバケツは別に用意しなくてはいけません。
Student backets[1000];
の方が簡単なんですねどね。
non

うらはんちょう

Re: バケットソート

#9

投稿記事 by うらはんちょう » 11年前

>ポインタの配列を1000個用意しているのですよ。
>実際のバケツは別に用意しなくてはいけません。
>Student backets[1000];
>の方が簡単なんですねどね。

んー、なるほど。
Student* buckets[1000] = {};
は、ポインタの配列で
もうひとつ、配列を用意するですか。。。

わかったような、わからないような、なんですが。

buckets[students] = students;

この、studentsの代入は Student* buckets[1000] = {};
のポインタの配列に代入していいんですか?

違うなら、どのようにすればいいのでしょうか?

studentsをint型にすれば解決するものと思ってたのですが。

non
記事: 1097
登録日時: 13年前

Re: バケットソート

#10

投稿記事 by non » 11年前

うらはんちょう さんが書きました:>ポインタの配列を1000個用意しているのですよ。
>実際のバケツは別に用意しなくてはいけません。
>Student backets[1000];
>の方が簡単なんですねどね。

んー、なるほど。
Student* buckets[1000] = {};
は、ポインタの配列で
もうひとつ、配列を用意するですか。。。

この、studentsの代入は Student* buckets[1000] = {};
のポインタの配列に代入していいんですか?



いえ、既に使っているcallocなどを使って動的にメモリを確保します。
それより、私は、ポインタ配列にするのは先生の指示かと尋ねたのです。
non

うらはんちょう

Re: バケットソート

#11

投稿記事 by うらはんちょう » 11年前

はい、指示です。

non
記事: 1097
登録日時: 13年前

Re: バケットソート

#12

投稿記事 by non » 11年前

うらはんちょう さんが書きました:はい、指示です。
そうですか。それなら、最初から1000個分の領域を確保する方法と、idがあるところの領域だけを確保する方法が
あります。どちらにしますか。

また、
Student* buckets[1000] = {};

Student* buckets[1000] ;
ではないかと思うのですが。 ={}; を つけるのも先生の指示ですか?


どっちにしても、
for(i = 0; i< 1000; i++){
buckets = 0;
}
はおかしいです。
buckets はポインタです。
これは、うらはんちょうが考えた部分ですよね。
何をしたかったのですか?
non

うらはんちょう

Re: バケットソート

#13

投稿記事 by うらはんちょう » 11年前

>そうですか。それなら、最初から1000個分の領域を確保する方法と、idがあるところの領域だけを確保する方>>法が
>あります。どちらにしますか。


最初から1000個分の領域を確保する方法でおねがいします。


>また、
>Student* buckets[1000] = {};
>は
>Student* buckets[1000] ;
>ではないかと思うのですが。 ={}; を つけるのも先生の指示ですか?

void bucket_sort(Student* students[], int n)
{
int i;
int j = 0;
Student* buckets[1000] = {};


void bucket_sortのここまでは
元から指示されていました。
よって={}; を つけるのも指示です。


>どっちにしても、
>for(i = 0; i< 1000; i++){
>buckets = 0;
>}
>はおかしいです。
>buckets はポインタです。
>これは、うらはんちょうが考えた部分ですよね。
>何をしたかったのですか?


確かにおかしいですね
ここは、省いてもらっていいです。

non
記事: 1097
登録日時: 13年前

Re: バケットソート

#14

投稿記事 by non » 11年前

>よって={}; を つけるのも指示です。

そうなんですか。初期値を入れないなら意味がないと思うのですが・・・・。
私が、勉強不足で意味が分からないだけなのでしょう。

>最初から1000個分の領域を確保する方法でおねがいします。
なら、ポインタでない方が簡単なのですが、
先生としては、最終的な形として、リスト構造にしたいのかもしれませんね。

では、
for(i = 0; i< 1000; i++){
buckets = 0;
}
の部分で、callocしてメモリを確保してください。

また
>buckets[students] = students;

buckets[students->id] = *students;
になりますが、意味が分かりますか?
non

うらはんちょう

Re: バケットソート

#15

投稿記事 by うらはんちょう » 11年前

>では、
>for(i = 0; i< 1000; i++){
> buckets = 0;
> }
>の部分で、callocしてメモリを確保してください。

callocと言うのは、はじめて聞いたのですが、ググってみて大体意味はわかりました。
idがあるところの領域だけを確保する方法と言うのを使うと
callocというのは使わなくていいのですか?
どちらにしても使うなら、どう書けば良いかご教授おねがいします。

>また
>buckets[students] = students;
>は
>buckets[students->id] = *students;
>になりますが、意味が分かりますか?

アロー演算子ですね、
構造体のメンバをポインタが指すとき使うやつ
でも、要はbuckets[]のなかのid番目にstudentsが入ったってことですか?

non
記事: 1097
登録日時: 13年前

Re: バケットソート

#16

投稿記事 by non » 11年前

うらはんちょう さんが書きました: callocと言うのは、はじめて聞いたのですが、ググってみて大体意味はわかりました。
idがあるところの領域だけを確保する方法と言うのを使うと
callocというのは使わなくていいのですか?
どちらにしても使うなら、どう書けば良いかご教授おねがいします。
すでに、あなたが使っているから、callocを使うように指示したのですよ。
何をわけのかからないことを・・・
non

うらはんちょう

Re: バケットソート

#17

投稿記事 by うらはんちょう » 11年前

>すでに、あなたが使っているから、callocを使うように指示したのですよ。
>何をわけのかからないことを・・・

つかってるところありますね
でも、そこは課題を渡されたときから書いてあったので
私が使えていたわけではないです。

do{
result = fscanf(file,"%d %s",&id, name);
if(result == 2){
student[count] = calloc(sizeof(Student),1);
if(student[count] == NULL) exit(EXIT_FAILURE);
initialize_student(student[count],id,name);
count++;
}
} while (result != EOF);

ここですね
こんな感じで書けばいいと

かずま

Re: バケットソート

#18

投稿記事 by かずま » 11年前

non さんが書きました: ポインタの配列を1000個用意しているのですよ。
実際のバケツは別に用意しなくてはいけません。
Student backets[1000];
の方が簡単なんですねどね。
配列を 1000個用意しているのではありません。
要素がポインタで、それが 1000個ある配列を 1個用意しています。
バケツはポインタだけで十分です。別に用意する必要はありません。
Student *backets[1000]; の方が簡単です。
non さんが書きました: そうですか。それなら、最初から1000個分の領域を確保する方法と、idがあるところの領域だけを確保する方法が
あります。どちらにしますか。
データの領域は、読み込み時にすでに行われているので、もうこれ以上
確保する必要はありません。
non さんが書きました: また、
Student* buckets[1000] = {};

Student* buckets[1000] ;
ではないかと思うのですが。 ={}; を つけるのも先生の指示ですか?
おそらく、授業では gcc を使っているんだと思います。
確かに、標準の C では、値が一つもない初期化子は許されませんが、
gcc では許されています。
Student* buckets[1000] = { 0 };
または、
Student* buckets[1000] = { NULL };
と書くほうがよいと思います。
値を一つ書いておけば、残りの 999個もすべて NULL で初期化されます。
宣言時に初期化していますから、次の for 文で 0 を代入する必要はありません。

元のプログラムは、
buckets[students] = students; を
buckets[students->id] = students; にすることと、

if(0 < buckets){ を
if (buckets != NULL) { にすることだけで正しいプログラムになります。

もっとも、read_students() が読み込んだデータの個数を返すのに、
フィルのオープンに失敗したときに 1 を返すのは変ですが。

うらはんちょう さんが書きました: .txtファイルに1000以下のid(数字)が6つ書いてあって

ex)
12
350
159
...

12 名前1
350 名前2
159 名前3
...
ですよね。

non
記事: 1097
登録日時: 13年前

Re: バケットソート

#19

投稿記事 by non » 11年前

かずまさんへ、
私がやりかたを勘違いしていました。ポインタを使って並び替えを変えるだけでよかったのですね。
別の領域をバケツで用意し、そちらに値を転送した後、studentに戻すのかと思ってました。

うらはんちょう さんへ
勘違いして、面倒な方法をお伝えしてしまいました。失礼しました。
non

non
記事: 1097
登録日時: 13年前

Re: バケットソート

#20

投稿記事 by non » 11年前

かずま さんが書きました:
non さんが書きました: ポインタの配列を1000個用意しているのですよ。
配列を 1000個用意しているのではありません。
要素がポインタで、それが 1000個ある配列を 1個用意しています。
この部分は、頭の中では、間違っていたわけではありませんが、表現方法がよくなかったですね。
誤解を生みました。

「要素がポインタで、それが 1000個ある配列を 用意しています。」
「1個」は書かない方が良いかと。
non

うらはんちょう

Re: バケットソート

#21

投稿記事 by うらはんちょう » 11年前

>おそらく、授業では gcc を使っているんだと思います。

そうです、gccをつかっています。

>確かに、標準の C では、値が一つもない初期化子は許されませんが、
>gcc では許されています。

Cでも使っているものによって変わってくるんですね。今度質問する機会があったらgccを使っていると書きたいとおもいます。

>Student* buckets[1000] = { 0 };
>または、
>Student* buckets[1000] = { NULL };
>と書くほうがよいと思います。
>値を一つ書いておけば、残りの 999個もすべて NULL で初期化されます。
>宣言時に初期化していますから、次の for 文で 0 を代入する必要はありません。

Student* buckets[1000] = { 0 };
のとことは、={}でも、ちゃんとした答えがでてきました。
={NULL}で全部初期化できるんですね、覚えておきます。

>元のプログラムは、
>buckets[students] = students; を
>buckets[students->id] = students; にすることと、

>if(0 < buckets){ を
>if (buckets != NULL) { にすることだけで正しいプログラムになります。

おっしゃるとおり、正しいプログラムになりました。ありがとうございます。
if(0 < buckets){
はなぜいけないのでしょうか?

うらはんちょう

Re: バケットソート

#22

投稿記事 by うらはんちょう » 11年前

ハッカーさん、かずまさん
貴重なお時間を使って、質問に答えていただきありがとうございました。
色々勉強になりました。
もっと、Cを勉強しようとおもいます。
もし、また質問に来たときはご指導ご鞭撻のほどをよろしくお願いします。

non
記事: 1097
登録日時: 13年前

Re: バケットソート

#23

投稿記事 by non » 11年前

うらはんちょう さんが書きました: if(0 < buckets){
はなぜいけないのでしょうか?


bucketsはポインタですからアドレスが入ります。
確かに、NULLは0ですから、動くとは思いますが、0番地を指しているという意味ではなく
構造体を指していないよという意味でNULLにします。
non

うらはんちょう

Re: バケットソート

#24

投稿記事 by うらはんちょう » 11年前

わかりました。
ありがとうございます。

閉鎖

“C言語何でも質問掲示板” へ戻る