• ベストアンサー

辞書順にソートしたいのですが・・・

C言語を始めたばかりの無知な自分で申し訳ないのですが学校で課題が出て分からなくて困っています。 課題は任意の長さの文字列(英字のみ)データをファイルから読み込み、辞書順に並べ替えるプログラムの作成です。文字列の最大長は64、データの最大個数は1000です。 一応自分で以下の状態まで作成したのですが、データが1000まで読み込んでくれません。申し訳ありませんが締め切りは明日なのでなるべく早くよろしくお願いします。 #include<stdio.h> #include<string.h> #include<strings.h> #define MAX 67 int main(void) { FILE *fp; char ex[1000][MAX],tmp[MAX],a[100]; int i,j,b; printf("Input filename:"); scanf("%s",a); fp = fopen(a,"r"); if(fp == NULL){ printf("Not open\n"); } for(i=0;!feof(fp);i++){ fgets(ex[i],MAX,fp); } for(i=0;i<=MAX-2;i++){ for(j=i+1;j<=MAX-1;j++){ b = strcasecmp(ex[i],ex[j]); if(b>0){ strcpy(tmp,ex[i]); strcpy(ex[i],ex[j]); strcpy(ex[j],tmp); } if(b==0 && *ex[i]<='z' && *ex[i]>='a' && *ex[j]<='Z' && *ex[j]>='A'){ strcpy(tmp,ex[i]); strcpy(ex[i],ex[j]); strcpy(ex[j],tmp); } } } for(i=0;i<=MAX-1;i++){ printf("%s",ex[i]); } fclose(fp); return 0; }

質問者が選んだベストアンサー

  • ベストアンサー
  • caceres
  • ベストアンサー率43% (61/140)
回答No.5

バージョンによるかもしれませんが。 BorlandCで strings.hとstrcasecmpはエラーになりませんか。存在しないようなので。 strcasecmpをstrcmpにして通しましたけど。 1 メモリモデルはラージにしておきましょう。   char ex[E_sizeMax][E_subMax] が大きいです。 2 char ex[E_sizeMax][E_subMax]はmainの外に出した方がよいです。 3 printf("Not open\n");   の下に exit()を追加しましょう。   ファイルが無くてもそのまま進んでしまいますよ。 4 word_num の定義を忘れずに。 5 malloc はHelpを読みましょう。 例 #include<mem.h> char *cp; cp=malloc(E_sizeMax * E_subMax );//メモリ確保 if(cp!=NULL){ for(i=0; i<E_sizeMax; i+=E_subMax ){ cp[i] =i; //以下も同じ位置のアクセスです。 *(cp+i) =i; //どれもE_subMax 毎にiを書いています。 //ただし*cpはcharなのでintの下位8bitしか 書き込めませんが。 } free(cp); //メモリ解放 } PCのOS上で動かす場合と組み込みCPUでOSなしの場合などメモリ環境により変数の確保の仕方も変わりますのでそれに応じて考えなければなりません。

battalion
質問者

お礼

なんとなくですが分かったような気がします。ありがとうございました。

すると、全ての回答が全文表示されます。

その他の回答 (4)

  • Werner
  • ベストアンサー率53% (395/735)
回答No.4

> 現在コンパイルできないのですが あまりよく見ていませんが、コンパイルエラーの原因は 全角スペースが混ざっているのと、 word_numが宣言されていないためではないですか?

battalion
質問者

補足

C言語と同様日本語も未熟で申し訳ないです。 コンパイルエラーするのではなく現在コンパイル出来る状態にありません。 現在使っているパソコンにborlandCがインストールされていないのです。

すると、全ての回答が全文表示されます。
  • Werner
  • ベストアンサー率53% (395/735)
回答No.3

> 「読み込んだ単語の個数」ということは、3つのforは以下のようにすればいいのでしょうか? > for(i=0;i<=998;i++) 必ず1000個読み込むというのならそれでよいのかもしれませんが(あまり良くないけど)、 1000個読み込むと決まっているわけではないですよね? 普通は、読み込んだ単語の数を数えておいてそれを使うと思います。 #define E_sizeMax 1000 #define E_subMax 67 for(i=0; i<E_sizeMax; i++){  if( feof(fp) ){break;}  fgets(ex[i],E_subMax,fp); } word_num=i; /*word_numに読み込んだ単語数が入る*/ なお効率を考えると、 strcpyで文字列を入れ替えるのではなく、 文字列へのポインタだけを入れ替えた方が良さそうです。 (効率の問題なのでそのままでも動作には問題ないと思いますが。)

battalion
質問者

補足

度々の質問で恐縮です。 現在コンパイルできないのですがこのような感じでよろしいのでしょうか。 #include<stdio.h> #include<string.h> #include<strings.h> #define E_sizeMax 1000 #define E_subMax 67 int main(void) { FILE *fp; char ex[E_sizeMax][E_subMax],tmp[E_subMax],a[100]; int i,j,b; printf("Input filename:"); scanf("%s",a); fp = fopen(a,"r"); if(fp == NULL){ printf("Not open\n"); } for(i=0; i<E_sizeMax; i++){  if( feof(fp) ){ break; }  fgets(ex[i],E_subMax,fp); } word_num=i; for(i=0;i<=word_num-1;i++){ for(j=i+1;j<=word_num;j++){ b = strcasecmp(ex[i],ex[j]); if(b>0){ strcpy(tmp,ex[i]); strcpy(ex[i],ex[j]); strcpy(ex[j],tmp); } if(b==0 && *ex[i]<='z' && *ex[i]>='a' && *ex[j]<='Z' && *ex[j]>='A'){ strcpy(tmp,ex[i]); strcpy(ex[i],ex[j]); strcpy(ex[j],tmp); } } } for(i=0;i<=word_num-1;i++){ printf("%s",ex[i]); } fclose(fp); return 0; }

すると、全ての回答が全文表示されます。
  • caceres
  • ベストアンサー率43% (61/140)
回答No.2

とにかくCは「安全に」を心がけて書きましょう。 >char ex[1000][MAX] 67*1000 だから67000byteですよ。 サイズが大きい変数は内部変数ではない方が安全ですよ。 またはmallocでメモリ確保してポインタで処理するのが定石です。 いつも実行環境のスタックサイズを忘れずに。 32bitでコンパイルすれば取りあえず読み込めるみたいですがメモリモデルには注意しましょう。 >for(i=0;!feof(fp);i++){ これでは1000回で止まる補償がないのでループはあくまでも同じ次元で処理するため配列のサイズにしましょう。  その上でforの中で!feof(fp)によりBreakすべきです。 例  #define E_sizeMax  1000  #define E_subMax 67 char ex[E_sizeMax][E_subMax] for(i=0; (E_sizeMax-1) ;i++){ if(!feof(fp){ }else{ break; } }

battalion
質問者

補足

超未熟者の自分にはちょっと難しい気がします。 mallocって???って感じの状態なんで。 出来れば自分なんかで分かるよう具体的に教えていただけないでしょうか。

すると、全ての回答が全文表示されます。
  • Werner
  • ベストアンサー率53% (395/735)
回答No.1

> for(i=0;i<=MAX-2;i++){ > for(j=i+1;j<=MAX-1;j++){ > for(i=0;i<=MAX-1;i++){ この3カ所の MAX は「各単語の最大長」だと思いますが、 本来は「読み込んだ単語の個数」であるべきでは?

battalion
質問者

補足

「読み込んだ単語の個数」ということは、3つのforは以下のようにすればいいのでしょうか? for(i=0;i<=998;i++) for(j=i+1;j<=999;j++) for(i=0;i<=999;i++)

すると、全ての回答が全文表示されます。

関連するQ&A