アプリ版:「スタンプのみでお礼する」機能のリリースについて

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;
}

A 回答 (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なしの場合などメモリ環境により変数の確保の仕方も変わりますのでそれに応じて考えなければなりません。
    • good
    • 0
この回答へのお礼

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

お礼日時:2006/10/11 01:32

> 現在コンパイルできないのですが


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

この回答への補足

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

補足日時:2006/10/10 23:05
    • good
    • 0

> 「読み込んだ単語の個数」ということは、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で文字列を入れ替えるのではなく、
文字列へのポインタだけを入れ替えた方が良さそうです。
(効率の問題なのでそのままでも動作には問題ないと思いますが。)

この回答への補足

度々の質問で恐縮です。

現在コンパイルできないのですがこのような感じでよろしいのでしょうか。



#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;
}

補足日時:2006/10/10 22:34
    • good
    • 0

とにかく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;
}
}

この回答への補足

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

補足日時:2006/10/10 22:46
    • good
    • 0

> for(i=0;i<=MAX-2;i++){


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

この回答への補足

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

補足日時:2006/10/10 21:50
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!