ページ 11

無題

Posted: 2009年10月21日(水) 12:49
by 男子
ファイルから読み込んだ文字列を辞書順にヒープソートするソースです。
先日も質問したのですがまだ正常に動きません。swap関数は問題ないと思います。実行すると辞書順になるんですが文字が欠けていたり改行が異常だったりします。どこがいけないですか?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define NS 3 /* 入力の最大数 */
#define WC 10      /* 入力の1行の文字数 */


void Hpsort(char s[/url][WC], int n);
void DownHeap(char s[ ][WC], int leaf, int root);
void swap( char *a, char *b );



void Hpsort(char s[/url][WC], int n) {
int leaf, root;

leaf = n; /* 初期値は末尾の要素 */
root = n/2; /* 初期値はその親 */

while (root > 0 ) {   /* 半順序木を構成 */
DownHeap(s, leaf, root);
root--;
}

while(leaf >0) {
swap(s[1], s[leaf]); /* 半順序木の根と末尾の要素を交換 */
leaf--; /* 末尾の要素を半順序木から外す */
DownHeap(s, leaf, 1); /* 半順序木を再構成する */
}
}


void DownHeap(char s[ ][WC], int leaf, int root){
int i;

i = root * 2;
while (i <= leaf) {
if (i < leaf && (strcmp(s[i + 1], s))>0) /* a と a[i + 1] の大きい方と */
i++;
if ((strcmp(s[root], s))>0) /* a[root] と比較 */
break; /* 子の方が大きければ */
swap(s[root], s); /* 交換 */

root = i; /* 更にその子についても調べる */
i = root * 2;
}
}


void swap( char *a, char *b ){
char tmp;
while ( (*a != '\0') && (*b != '\0') ){
tmp = *a;*a = *b;*b = tmp;
a++;
b++;
}

if( *b == '\0' ){
while ( *a != '\0' ){
*b++ = *a; *a++ = '\0';
}
}else if( *a == '\0' ){
while ( *b != '\0' ){
*a++ = *b; *b++ = '\0';
}
}
*a = '\0';
*b = '\0';
}



main(int argc, char *argv[/url]) {
  FILE *fp;
  char s[NS][WC];
  int i;
  
  if ((argc==1) || (argc>=3)) {
    printf("Input filename\n"); 
    exit(1);
  }
  fp=fopen(argv[1],"r");
  if(fp==NULL){
  printf("file not found\n");
  exit(0);
  }
  
  for(i=1;i<=NS;i++){
  fgets(s,WC,fp);
  }


for (i=1 ; i<=NS; i++) {
  printf("%s\n",s);}
  Hpsort(s,NS);
 

 for (i=1; i<=NS; i++) {
    printf("%s\n",s);}
  
  


  fclose(fp);
  exit(0);
}

Re:無題

Posted: 2009年10月21日(水) 15:13
by くぁwせd
読み込むファイルはどのような内容ですか?
#define NS 3 /* 入力の最大数 */
#define WC 10 /* 入力の1行の文字数 */
より多かったりしませんか?

Re:無題

Posted: 2009年10月21日(水) 15:23
by pooka
前回の分を見てみましたが、配列の添字を1から始めるのであれば
char s[NS+1][WC];
のように1つ多く確保しないといけません。
前回のboxさんの回答と合わせて確認してみてください。


>文字が欠けていたり改行が異常だったりします
#define&#160;WC&#160;10&#160;&#160;&#160;&#160;&#160;&#160;/* 入力の1行の文字数 */
とありますが、ファイルには1行に10文字書かれているのでしょうか?
fgets(s,WC,fp);
これだと最大9文字までしか読み取りません。

fgetsについて
ttp://www.bohyoh.com/CandCPP/C/Library/fgets.html

あと上のサイトを見ても分かる通り、改行文字も格納するので、
fgetsで読み取った後、改行文字を'\0'に置き換えてみてください。

それとmain関数の最後でexit(0);とするのもどうかなと思うので
int&#160;main()として、return&#160;0;とする方が良いのではないでしょうか?

Re:無題

Posted: 2009年10月22日(木) 11:23
by 男子
返信ありがとうございます。char s[NS+1][WC];と宣言したらすこし改善しました。いろんなファイル(単語数や文字数がバラバラ)から読み取れるようにしたいんですが、NSやWCを固定してるとまずいですよね?最大の値にしておけばいいのですか?