C言語関係掲示板

過去ログ

No.380.ソートを含むプログラム

[戻る] [ホームページ]
No.2531

コンパイルエラーがでていないのに動きません。
投稿者---すず(2002/08/29 10:24:18)


おはようございます。すずです。
ビルドもちゃんととおり、エラーがないはずなのに、動きません。
どこがおかしいのか教えてください。

問題は、2次元配列を使って、10人分の氏名入力をする、といったものです。
#include <stdio.h>

#define GETMAX 51 /* 入力文字の最大文字数    :51桁 */
#define ARRAY 10 /* 配列の最大値     : 10 */


/* プロトタイプ宣言 */
/*===============================================
MODULE : get_strInput
ABSTRACT : 入力関数
PARAMETER : char dt / O /格納するための配列
: int array/ I /順番
RETURN : int 0(リターンのみ)
or
0以外(カウント数)
DATE : 8/28 新規作成
NOTE : NULLストップにしてます
===============================================*/
extern int get_strInput(char dt[][GETMAX],int iArray);


int main( void )
{
char dt[ARRAY][GETMAX];
int iCount = 0;
int i,j,fLoop;

/* 配列の初期化 */
for ( i = 0; i < ARRAY ;i++ )
{
for ( j = 0; j < GETMAX ;j++ )
{
dt[i][j] = 0 ;
}
}

printf("%d字以内の文字を%d個入力してください。\n",GETMAX-1,ARRAY);

for( fLoop = 0 ; fLoop < ARRAY ; fLoop++ )
{
iCount = get_strInput( dt,fLoop );
if(iCount == 0 )
{
printf("何も入力されていません。入力はきちんとしましょう。\n");
fLoop--;
}
}

for ( i = 0 ; i < ARRAY ; i ++ )
{
printf( "入力された文字 = %s\n",dt[i][GETMAX] );
}

return ( 0 );
}

int get_strInput(char dt[][GETMAX],int iArray)
{
/* 入力文字、入力文字数 */
int iMoji=0,iKetasuu=0;

while((iMoji=getchar()) != EOF )
{
/* 改行判断 */
/* 改行がある場合 */
if(iMoji=='\n')
{
break; /* 入力終了 */
}
else
{
/* 入力された文字を保存 */
dt[iArray][iKetasuu] = iMoji;
/* 入力文字数をカウント */
iKetasuu++;
/* 文字数判断 */
/* 設定文字数オーバーの場合 */
if(iKetasuu >= GETMAX)
{
/* エラーの表示 */
printf("\n");
printf("%d字をオーバーしてるので%d字以内で入力してね\n",GETMAX-1,GETMAX-1);
printf("\n");
/* 入力文字数を初期化 */
iKetasuu=0;
/* 入力文字を初期化 */
iMoji=0;
/* 入力文字列の初期化 */
fflush(stdin);fflush(stdout);
}
}
}
/* 入力文字列の最後にNULL文字挿入 */
//dt[iArray][iKetasuu] = '\0' ;

return (iKetasuu); /* 戻り値にカウント数を設定(0:リターンのみ、その他:カウント数) */
}


No.2532

Re:コンパイルエラーがでていないのに動きません。
投稿者---Kaji(2002/08/29 11:43:16)


こんにちは。
get_strInputに二次元配列を渡すメリットが分からなかったので次のように直してみました。
どうでしょう?

ちなみにすずさんのソースが動かなかったのは
結果の出力のprintfが間違っていたからです。
違:printf( "入力された文字 = %s\n",dt[i][GETMAX] );
正:printf( "入力された文字 = %s\n",dt[i]);
これを直すだけでも動くはずです。


#include <stdio.h>

#define GETMAX 51
#define ARRAY 10


extern int get_strInput(char *dt);


int main( void )
{
        char dt[ARRAY][GETMAX];
        int i;
        
        memset(dt, '\0', sizeof(dt));
        
        printf("%d字以内の文字を%d個入力してください。\n",GETMAX-1,ARRAY);

        i = 0;
        while(i != ARRAY) {
                if(get_strInput( dt[i] ) != 0) {
                        i++;
                }
                else {
                        printf("何も入力されていません。入力はきちんとしましょう。\n");
                }
        }
        
        for ( i = 0 ; i < ARRAY ; i ++ ) {
                printf( "入力された文字 = %s\n", dt[i]);
        }

        return ( 0 );
}

int get_strInput(char * dt)
{
        int iMoji=0,iKetasuu=0;

        while((iMoji=getchar()) != EOF ) {
                if(iMoji=='\n') {
                        break;
                }
                else {
                        dt[iKetasuu] = iMoji;
                        
                        iKetasuu++;
                        
                        if(iKetasuu >= GETMAX) {
                                printf("\n");
                                printf("%d字をオーバーしてるので%d字以内で入力してね\n",GETMAX-1,GETMAX-1);
                                printf("\n");
                                
                                iKetasuu=0;
                                
                                iMoji=0;
                                
                                fflush(stdin);
                                fflush(stdout);
                        }
                }
        }

        return (iKetasuu);

}


No.2533

ご親切にありがとうございました。
投稿者---すず(2002/08/29 13:49:06)


すずです。
こんにちは。
>get_strInputに二次元配列を渡すメリットが分からなかったので次のように直してみました。
>どうでしょう?

二次元配列を渡した理由は、文字列をNULLストップにしたかったので、文字列の最後にNULLをいれる、と言う処理をしたいためにわたしました。
考え方がおかしいのでしょうか?
でも、kajiさんのプログラムのほうが、ずぅ〜っとわかりやすい、読みやすいプログラムですよね。

”ダレが見ても、一目でわかるプログラムを作成する”

自分の中でいつも心がけていることですが、なかなか、そういうわけにはいきません。もっともっと努力を重ねて、いつの日か、この目標を達成します。

>ちなみにすずさんのソースが動かなかったのは
>結果の出力のprintfが間違っていたからです。
>違:printf( "入力された文字 = %s\n",dt[i][GETMAX] );
>正:printf( "入力された文字 = %s\n",dt[i]);
>これを直すだけでも動くはずです。

たしかにそうですよね。
kajiさんに言われて気が付きました。
#define GETMAX 51をしてるので、コンパイラがメモリをよみとることができませんよね。お恥ずかしい限りです。初歩的なミスですね。
ご親切なアドバイス、本当にありがとうございます。

No.2534

ソート機能を追加。・・・、エラーだらけなのはなぜ??
投稿者---すず(2002/08/29 14:54:22)


すずです。続けて失礼します。

訂正したプログラムにソート機能を追加したのですが、コンパイルエラーが盛りだくさん。完璧だと思い込んでいたため、本当に泣きそうです。(;;)
なぜでしょう。教えてください。お願いします。


/* 省略 */
printf("%d字以内の文字を%d個入力してください。\n",GETMAX-1,ARRAY);

for( fLoop = 0 ; fLoop < ARRAY ; fLoop++ )
{
iCount = get_strInput( dt,fLoop );
if(iCount == 0 )
{
printf("何も入力されていません。入力はきちんとしましょう。\n");
fLoop--;
}
}

s_sort( dt );

for ( i = 0 ; i < ARRAY ; i ++ )
{
//printf( "入力された文字 = %s\n",dt[i][GETMAX] );
printf( "学籍番号%d  %s\n",i+1,dt[i]);
}

return ( 0 );
}

void s_sort(char dt[])
{
char *wkp;
int i, j;

for ( i=0;i<ARRAY-1;i++ )
{
for ( j=i+1; j<ARRAY; j++ )
{
/* 文字列の比較 */
if ( strcmp( dt[i], dt[j] ) > 0 )
{
/* ポインタ配列の入れ換え */
wkp = dt[i];
dt[i] = dt[j];
dt[j] = wkp;
}
}
}
}

No.2535

Re:ソート機能を追加。・・・、エラーだらけなのはなぜ??
投稿者---Kaji(2002/08/29 15:53:34)


まずこの配列はポインタ配列ではありません。単なる2次元配列です。
なのでポインタで置き換えることはできません。
失礼ですが、2次元配列とポインタ配列の違いを
ちゃんと理解されたほうが良いと思います。
こちらのホームページは分かり易いので参考にして下さい。

一応修正したソースをのせておきます。
結構いろんなところを変えていますがどうでしょう?


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

#define GETMAX 51
#define ARRAY 10


extern char * get_strInput();
void s_sort(char **dt);

int main( void )
{
        char *dt[ARRAY];
        int i;

        memset(dt, '\0', sizeof(dt));

        printf("%d字以内の文字を%d個入力してください。\n",GETMAX-1,ARRAY);

        i = 0;
        while(i != ARRAY) {
                if((dt[i] = get_strInput()) != NULL) {
                        i++;
                }
        }

        s_sort(dt);

        for ( i = 0 ; i < ARRAY ; i ++ ) {
                printf( "入力された文字 = %s\n", dt[i]);
        }

        return ( 0 );
}

char * get_strInput()
{
        char  buff[256];

        gets(buff);
        if(strlen(buff) >= GETMAX) {
                printf("%d字をオーバーしてるので%d字以内で入力してね\n",GETMAX-1,GETMAX-1);
                return NULL;
        }
        else if(strlen(buff) == 0) {
                printf("何も入力されていません。入力はきちんとしましょう。\n");
                return NULL;
        }

        return strdup(buff);
}

void s_sort(char **dt)
{
        char *wkp;
        int i, j;

        for ( i=0;i<ARRAY-1;i++ )  {
                for ( j=i+1; j<ARRAY; j++ ) {
                        if ( strcmp( dt[i], dt[j] ) > 0 )  {
                                wkp = dt[i];
                                dt[i] = dt[j];
                                dt[j] = wkp;
                        }
                }
        }
}





No.2537

勉強しなおしてきます。
投稿者---すず(2002/08/29 16:18:28)


>まずこの配列はポインタ配列ではありません。単なる2次元配列です。
>なのでポインタで置き換えることはできません。
>失礼ですが、2次元配列とポインタ配列の違いを
>ちゃんと理解されたほうが良いと思います。
>こちらのホームページは分かり易いので参考にして下さい。
>

kajiさん、リンクされてないみたいです。

そうなんです。2次元配列とポインタ配列が頭の中でごちゃごちゃしてるんです。どうしたらよいものかと、一生懸命勉強してる途中なんです。理解を深めようと思い、今回の問題にチャレンジをしてみたのですが・・・、結果は見てのとおりです。

TDaさん、型の宣言には何となくですが、ちがうかなぁ・・・、程度には気がついていました。やっぱなんとなくじゃダメですね。もう一回、きちんと2次元配列と、ポインタの章で勉強しなおしてきます。

また、ご指導宜しくお願い致します。

No.2538

Re:勉強しなおしてきます。
投稿者---Kaji(2002/08/29 17:17:07)


>kajiさん、リンクされてないみたいです。
誤解されたようですね。このホームページという意味です。
失礼しました。


>TDaさん、型の宣言には何となくですが、ちがうかなぁ・・・、程度には気がついていました。やっぱなんとなくじゃダメですね。もう一回、きちんと2次元配列と、ポインタの章で勉強しなおしてきます。
解説のページも良いのですが過去ログにも有益な情報があります。
すずさんのようにポインタなどでつまづいて質問されているものなどが結構あります。
それらの質問に対する回答を見るのも勉強になると思います。

No.2539

ありがとうございます。
投稿者---すず(2002/08/29 17:47:11)


>解説のページも良いのですが過去ログにも有益な情報があります。
>すずさんのようにポインタなどでつまづいて質問されているものなどが結構あります。
>それらの質問に対する回答を見るのも勉強になると思います。


はい!!
ありがとうございます。
過去ログも含めて、自分が本当に理解できるよう努力していきます。
つまったときはまた書きこするので、そのときはまたよろしくお願い致します。

No.2540

Re:勉強しなおしてきます。
投稿者---かずま(2002/08/29 19:15:14)


> そうなんです。2次元配列とポインタ配列が頭の中でごちゃごちゃしてるんです。
> どうしたらよいものかと、一生懸命勉強してる途中なんです。理解を深めようと思い、
> 今回の問題にチャレンジをしてみたのですが・・・、結果は見てのとおりです。

C を一通り勉強したら、今度は C++ に挑戦してみてはいかがでしょう。

文字列型があって、何文字でも入るから、#define GETMAX 51 は不要。
サイズが変わる配列型があって、#define ARRAY 10 は不要。
したがって、2次元配列もポインタも不要。
sort も用意されているから、プログラムはこんなに簡単になります。
#include <iostream>   // cin, cout  標準入出力
#include <string>     // string,  getline()
#include <vector>     // vector { push_back(), size(), begin(), end() }
#include <algorithm>  // sort()
using namespace std;

int main()
{
    vector<string> data;  // 文字列の配列(サイズは可変)
    string         line;  // 文字列

    cout << "文字列を入力してください。(. で終わり)\n";
    while (getline(cin, line) && line != ".") {
        if (line == "")
            cout << "何も入力されていません。入力はきちんとしましょう。\n";
        else
            data.push_back(line);    // data に line を追加する
    }
    sort(data.begin(), data.end());  // data の先頭から末尾までをソートする

    for (size_t i = 0; i < data.size(); i++)
        cout << "学籍番号 " << i+1 << "   " << data[i] << "\n";
}


No.2541

Re:勉強しなおしてきます。
投稿者---かずま(2002/08/29 23:54:44)


> if (line == "")

これは、とてつもなく効率が悪いので、if (line.size() == 0) に訂正します。
if (line.empty()) と書いてもよく、g++ や VC++ では、最適化すれば
同じコードにコンパイルされます。


No.2542

一通り勉強した後・・・。
投稿者---すず(2002/08/30 09:15:44)


おはようございます。すずです。

>C を一通り勉強したら、今度は C++ に挑戦してみてはいかがでしょう。
>

ご親切にありがとうございます。
そうですね、Cを一通り勉強して、ある程度自分の中で自信が持てるようになったときには、C++に挑戦してみます。とりあえず今は欲張らないで、現状のC言語のマスターすることに専念します。昨日もあれからずっとポインタを勉強しなおしていました。過去ログもかなり活用してます。皆さん、多くの方が同じように詰まって、そして克服していってるんだなと思うとがんばろうという気持ちが湧いてきます。
また詰まったときには宜しくお願い致します。

No.2536

Re:ソート機能を追加。・・・、エラーだらけなのはなぜ??
投稿者---TDa(2002/08/29 15:56:18)


こんにちは。全体は目を通していませんが明らかな間違いを見つけました。

s_sort( dt );  /* 呼び出し部分 */
void s_sort(char dt[])  /* 定義部分 */

このs_sort()ですが実引数がchar dt[ARRAY][GETMAX]を渡していますよね。
ですから型が違います。
これは
void s_sort(char dt[][GETMAX])あるいは
void s_sort(char (*dt)[GETMAX])
としなくてはなりません。

それに合わせて
char *wkp;も char (*wkp)[GETMAX];としましょう。