ページ 11

ポインタへのポインタを使ってクイックソート

Posted: 2010年6月27日(日) 12:46
by RAKI
[1] 初めてこのサイトを利用させてもらいます><
  初心者です。ポインタへのポインタを使ってquickSort関数を自分で作る学校の課題なのですが、 
  完成したとおもったらエラーがでてしまってどこが間違ってるかがよくわかりません。。
  

[1.1] 教科の合計点(sum)をクイックソートを用いて高→低順に並べていきたい。
[1.2] #include <stdio.h>
#include <stdlib.h>
struct student{
int number;
int math;
int eng;
int phy;
int sum;
struct student *next;
};
typedef struct student Student;
void swap(Student **x, Student **y);
void quickSort(Student **sort, int first, int c);
int main(void)
{
Student *top,**sort,**sortTop,*tmp;
char line[80];
int count=0,a=0;
top=(Student *)malloc(sizeof(Student));
top->number=-1; top->math=-1; top->eng=-1; top->phy=-1; top->sum=-1;
top->next=NULL;

while(fgets(line,sizeof(line),stdin)!=NULL){
tmp=(Student *)malloc(sizeof(Student));
if(tmp==NULL){
fprintf(stderr,"No more memory...\n");
return(1);
}
count++;
tmp->next=top->next;
top->next=tmp;
sscanf(line,"%d,%d,%d,%d",
&(tmp->number),
&(tmp->eng),
&(tmp->math),
&(tmp->phy));&(tmp->number),
tmp->sum=(tmp->eng)+(tmp->math)+(tmp->phy);
}
sort=(Student **)malloc((count+1)*sizeof(Student *));
sortTop=sort;
tmp=top->next;
while(tmp!=NULL){
*sort=tmp;
tmp=tmp->next;
sort++;
}
sort=NULL;
sort=sortTop;

quickSort(sort,a,count);

sort=sortTop;
while(*sort!=NULL){
fprintf(stdout,"%8d\t%3d\t%3d\t%3d\t%3d\n",
(*sort)->number,
(*sort)->eng,
(*sort)->math,
(*sort)->phy,
(*sort)->sum);
sort++;
}
return(0);
}

void quickSort(Student **sort, int first, int c)
{
Student **t1,**t2,**pivot;
int left,right;
left=first;
right=c;
t1=sort+first;
t2=sort+c;
pivot=sort+(c/2);

while(1){
while(((*t1)->sum)<((*pivot)->sum)){
t1++;
first++;
}
while(((*pivot)->sum)<((*t2)->sum)){
t2--;
c--;
}
if(t1 >= t2){
break;
}
swap(t1,t2);
t1++;
t2--;
first++;
c--;
}
if(left<first-1){
quickSort(sort,left,first-1);
}
if(c+1<right){
quickSort(sort,c+1,right);
}
return;
}
void swap(Student **x, Student **y)
{
Student *tmp;
tmp=*x;
*x=*y;
*y=tmp;
return;
}

 [1.3] このCソースをコンパイルした場合のコンパイルエラーが
    6[main]a 9272_cygtls::handle_exceptions:Error while dumping state
(probably corrupted stack)
    とでます。

どうしてこのようなコンパイルエラーがおきるのか、
またこの方法でのクイックソートは間違っていないのかを指導してもらえると助かります。
    

Re:ポインタへのポインタを使ってクイックソート

Posted: 2010年6月27日(日) 13:15
by たいちう
まずコンパイルエラーではなく、実行時エラーが出るようです。

ちゃんと見てないけど、実行時エラーの原因は、この部分。
t1=sort+first;
t2=sort+c;
まるで配列のように扱っていますが、mallocで別々に取得した構造体の
アドレスが、sizeof(Student)の間隔で並んでいることを期待するのが
間違いです。アドレスを表示して確認してください。
sortからt1を求めるには、リンクを順番に辿りましょう。

それとmallocで確保したメモリーはちゃんとfreeしましょう。


ついでにデバッグしやすいような工夫を1つ。
実行するたびに数値を入力するのは面倒なので、

--- data.txt ---
1,50,60,70
2,45,50,55
3,20,30,45

というものを用意し、

FILE *fp = fopen("data.txt", "r");

こうして、

//while(fgets(line,sizeof(line),stdin)!=NULL){
while(fgets(line,sizeof(line),fp)!=NULL){

こうします。

Re:ポインタへのポインタを使ってクイックソート

Posted: 2010年6月27日(日) 13:27
by たいちう
> ちゃんと見てないけど、実行時エラーの原因は、この部分。

申し訳ない、肝心の↑の部分は勘違いのようです。
後で時間が取れたらまた書きこみます。

Re:ポインタへのポインタを使ってクイックソート

Posted: 2010年6月27日(日) 15:36
by ISLe
> RAKI さん

quickSortに入って最初にt2が指しているところがどうなっているかをよーく考えてみてください。


> たいちう さん

> FILE *fp = fopen("data.txt", "r");
> こうして、
> //while(fgets(line,sizeof(line),stdin)!=NULL){
> while(fgets(line,sizeof(line),fp)!=NULL){
> こうします。

プログラム変更せずに

./a < data.txt

と実行するほうが楽じゃないでしょうか?

Re:ポインタへのポインタを使ってクイックソート

Posted: 2010年6月27日(日) 17:18
by たいちう
> プログラム変更せずに
>
> ./a < data.txt
>
> と実行するほうが楽じゃないでしょうか?

実行だけならば良いのですが、デバッガを使おうと思うと、
プロジェクトのプロパティの設定をいじらないといけません。
(私が今使っているVC++EE2008の場合)

RAKIさんの開発環境も、それをどの程度使いこなしているレベルも
分からないので、プログラムの変更の方がフォローが楽だと思いました。

Re:ポインタへのポインタを使ってクイックソート

Posted: 2010年6月28日(月) 00:05
by RAKI
みなさんアドバイスありがとうございます><
いちよアドバイスしてくださったところを考えていろいろやってはみたのですけど
どうもまだうまく動かなくて^^;
もう少しいろいろ考えて粘ってみます><b

Re:ポインタへのポインタを使ってクイックソート

Posted: 2010年6月28日(月) 02:38
by RAKI
> たいちう さん
--- data.txt ---
1,50,60,70
2,45,50,55
3,20,30,45
を作って実行してみました。
楽に実行できたのでためになりました!
ありがとでした。

> ISLe さん

quickSortに入って最初にt2が指しているところを考えたのですが、
NULLが入ってるのでしょうか・・・?

それと
./a < data.txt
と実行したらできました^^
ありがとでした。

画像

Re:ポインタへのポインタを使ってクイックソート

Posted: 2010年6月30日(水) 09:37
by たいちう
> quickSortに入って最初に t2が指しているところを考えたのですが、
> NULLが入ってるのでしょうか・・・?
quickSort(sort,a,count);
↓
void quickSort(Student **sort, int first, int c)
{
    ...
    t2=sort+c;
    ...
    while(((*pivot)->sum)<((*t2)->sum)){
データが3件の場合、
sort[0] ... 1人目のデータ
sort[1] ... 2人目のデータ
sort[2] ... 3人目のデータ
となりますが、sort+cは、4人目のデータを指しています。