C言語関係掲示板

過去ログ

No.1341 10件の文章を2次元配列に格納し、表示する

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

10件の文章を2次元配列に格納し、表示する
投稿者---ΔΓβ(2004/11/16 21:11:36)


はじめまして。ちょっとした知人の出したプログラムをといているのですが、行き詰ってしまいました。

2次元配列に文章を格納するプログラムなのですが、以下の仕様を満たすことが出来ません。

・文章の長さは10文字以下、11文字以上入力されたときは先頭から10文字までを有効とし、以降は無視
・文章の最大件数は10件
・10件目の入力が完了するか、文章の1文字目に0が入力された場合は入力を終了し、それまでのデータを表示
・改行のみの入力の場合、エラーメッセージを表示し再入力

現在まで出来ているソースは下のようになりますが

#include <stdio.h>

int main()
{
    char name[10][10]; 
    int i; 

    for (i = 0; i < 10; i++) {
        printf("name[%d]:", i); 
        scanf("%s", name[i]);
        
        printf("現在%d件目\n", i+1); 

    }

    for (i = 0; i < 10; i++) {
        printf("name[%d] = %s\n", i, name[i]); 
    }


    return(0); 
}




満たしているのは10件までというものだけなのですが、これ以上は思いつきません。
どなたか教えていただけると幸いです。


No.18176

Re:10件の文章を2次元配列に格納し、表示する
投稿者---KING・王(2004/11/17 00:56:21)


> char name[10][10];

このままでは、10文字の文字列を入力すると、オーバフローが発生します。

> scanf("%s", name[i]);

scanf()では、入力される文字の制限ができないので、10文字以上のデータを入力された場合、
name[i]に10文字以上のデータが格納され、オーバフローを起こします。

>・文章の長さは10文字以下、11文字以上入力されたときは先頭から10文字までを有効とし、以降は無視


私ならとりあえず以下のようにします。
#255文字以上のデータを入力されるとオーバーフローします。

char name[10][11]; 
char buf[256];// 入力データ用バッファ

scanf("%d", buf );//一旦バッファにデータを格納する
strncpy( name[i], buf, 10 );// 入力バッファより10文字分コピーする
name[i][11] = '\0';//10文字以上の場合のために、末端のNULLを付加しておく。


>・10件目の入力が完了するか、文章の1文字目に0が入力された場合は入力を終了し、それまでのデータを表示

if( name[i][0] == '0' ){//入力の先頭の文字が'0'かチェックする
    break;//ループを抜ける
}
#先の例を用いてる場合、name[i][0]の部分はbuf[0]でも可


>・改行のみの入力の場合、エラーメッセージを表示し再入力

改行のみの入力の判定に関しては、scanf()の使い方と動作にいまいち自信がないので、
他の識者の方におまかせるとして、エラーメッセージの表示と再入力に関しては、
次のような形はどうでしょうか?

if( /*改行のみの入力と判定*/ ){
    printf( "正しくデータを入力して下さい\n" );
    i--;//ループで同じiの値を繰り返すために、iの値を
        //デクリメントしておく。
    continue;
}


scanf()系の動作に関しては、いまいち自信がありませんので、
識者の方々、フォローをお願いします。


No.18189

Re:10件の文章を2次元配列に格納し、表示する
投稿者---ΔΓβ(2004/11/17 12:39:18)


色々考えた結果、scanfではなくgetcharを使用することにしたのですが……改行の際に再入力がどうしても出来ません。
下にソースを張ります。

<pre>#include &lt;stdio.h&gt;
#define MAXCHAR 10

main()
{
char name[10][11] = {0};
int c = 0, i, j;
int count = 0, che1 = 0, che2 = 0;

for (i = 0; i &lt; 10; i++) {
printf(&quot;氏名%d入力:&quot;, i + 1);
j = 0;
che1 = 0;

while ((c= getchar()) != '\n' &amp;&amp; j &lt; MAXCHAR) {
name[i][j++] = c;

if (che1 == 0 &amp;&amp; c == '0') {
che2 = 1;
}

if (che1 == 0 &amp;&amp; c == '\n') {
i = i - 1;
printf(&quot;再入力&quot;);
break;
}

che1 = 1;

}
fflush(stdin);
name[i][MAXCHAR + 1] = '\0';
count = count + 1;

printf(&quot;累計件数:%d\n&quot;, count);

if (che2 == 1) {
break;
}
}

for (i = 0; i &lt; count -1; i++) {
printf(&quot;%d件目:&quot;, i+1);
for (j = 0; j &lt; 10; j++) {
printf(&quot;%c&quot;, name[i][j]);
}
putchar('\n');
}
}

どなたかご教授をお願いいたします。


No.18193

Re:10件の文章を2次元配列に格納し、表示する
投稿者---あかま(2004/11/17 13:38:26)


>色々考えた結果、scanfではなくgetcharを使用することにしたのですが……改行の際に再入力がどうしても出来ません。
一文字目が改行だったらループあたりでやり直せばいいです。

>下にソースを張ります。
文字化け。これだとコピペで使えないです。
確認画面があるのですから、しっかり確認してから投稿してください。
それでも投稿しちゃったなら投稿しなおしがよいかと。


No.18194

Re:10件の文章を2次元配列に格納し、表示する
投稿者---ΔΓβ(2004/11/17 14:21:43)


すいません、よく確認せず貼り付けてしまいました。
まだ改行のみの入力の場合、再入力は出来ていませんが……。

#include <stdio.h>
#define MAXCHAR 10

main()
{
    int c1 = 0, check = 0, check2 = 0, i, j, count = 0;

    char str[11][MAXCHAR + 1] = {0};

    for (j = 0; j < 10; j++){
        printf("文字列%dを入力:", j + 1); 
        i = 0;
        check = 0;
    /*改行、あるいはMaccharを超えるまで文字を入力*/
        while ((c1 = getchar()) != '\n' && i < MAXCHAR) {
            str[j][i++] = c1;

            if (check == 0 && c1 == '0'){
                check2 = 1;
            }
            else if (check == 0 && c1 == '1'){
                j = j - 1;
                count = count - 1;
                printf("再入力:\n");
                break;
            }

        check = 1;
        }

        fflush( stdin );
        str[j][MAXCHAR + 1] = '\0';
        count = count + 1;

        printf("累積レコード数:%d\n", count);

        if (check2 == 1){
            printf("終了\n");
            break;
        }

    }

    for(j = 0;j < count; j++){
        printf("%d件目:", j + 1);
        for(i = 0; i < 10; i++){
            printf("%c", str[j][i]);
        }
        putchar('\n');
    }
}



こちらがソースになります。
以前の投稿は消させていただきますのでお願いいたします。


No.18195

Re:10件の文章を2次元配列に格納し、表示する
投稿者---ΔΓβ(2004/11/17 14:27:47)



>こちらがソースになります。
>以前の投稿は消させていただきますのでお願いいたします。

すいません、以前の投稿はパスワードを失念してしまい消すことが出来ませんでした。


No.18204

Re:10件の文章を2次元配列に格納し、表示する
投稿者---あかま(2004/11/17 18:43:09)




>すいません、よく確認せず貼り付けてしまいました。
>まだ改行のみの入力の場合、再入力は出来ていませんが……。
内側のwhile内で

if(i==0 && c1 == '\n') エラー表示&どこぞへ飛ぶ

みたいのを入れればいいのではないでしょうかね。


No.18205

Re:10件の文章を2次元配列に格納し、表示する
投稿者---ΔΓβ(2004/11/17 19:29:37)


>内側のwhile内で
>
>if(i==0 && c1 == '\n') エラー表示&どこぞへ飛ぶ
>
>みたいのを入れればいいのではないでしょうかね。

やってみたのですが、どうしても「\n」では反応しないのです。
数値の「1」や文字「a」などでは反応があるのですが……。


No.18207

Re:10件の文章を2次元配列に格納し、表示する
投稿者---かずま(2004/11/17 21:06:21)


>>内側のwhile内で
>>
>>if(i==0 && c1 == '\n') エラー表示&どこぞへ飛ぶ
>>
>>みたいのを入れればいいのではないでしょうかね。
>
> やってみたのですが、どうしても「\n」では反応しないのです。
> 数値の「1」や文字「a」などでは反応があるのですが……。

どんなコードを書かれたのかわかりませんが、c1 が '\n' でなかったら
while 内に入るわけですから、while 内で if (... c1 == '\n') とやっても
無意味です。

それから、11文字以上の入力を捨てるために fflush(stdin) を実行して
いますが、これは VC++ や BC++ では思ったとおり動きますが、gcc では
何もしてくれません。C の規格では、出力ストリームにのみはたらくことが
規定させていて、入力ストリームに対しては未定義となっています。



No.18206

Re:10件の文章を2次元配列に格納し、表示する
投稿者---かずま(2004/11/17 20:58:53)


> 私ならとりあえず以下のようにします。
> #255文字以上のデータを入力されるとオーバーフローします。
> char name[10][11]; 
> char buf[256];// 入力データ用バッファ
> 
> scanf("%d", buf );//一旦バッファにデータを格納する
> strncpy( name[i], buf, 10 );// 入力バッファより10文字分コピーする
> name[i][11] = '\0';//10文字以上の場合のために、末端のNULLを付加しておく。

255文字ではオーバーフローしません。
"%d" は、文字列を読み込むのに使いません。
"%255s" にすると、バッファーオーバーフローによるプログラムの破壊は
防げますが、実行結果が思ったとおりになるとは限りません。
name[i][11] は参照してはいけません。name[i][10] の間違いでしょう。
'\0' のことを NULL というのは不適切です。



No.18211

Re:10件の文章を2次元配列に格納し、表示する
投稿者---KING・王(2004/11/17 23:27:28)


ご指摘ありがとうございます。
なんか、細かいミスばかりでぼろぼろ。。。

それぞれ、以下の間違いです。

> scanf("%d", buf );//一旦バッファにデータを格納する

=> scanf("%s", buf );

> name[i][11] = '\0';//10文字以上の場合のために、末端のNULLを付加しておく。

=>name[i][10] = '\0';




No.18209

Re:10件の文章を2次元配列に格納し、表示する
投稿者---かずま(2004/11/17 21:52:26)


参考となるプログラムですが、このプログラムは未完成です。
EOF の処理が抜けているので、とんでもないことになる可能性があります。
#include <stdio.h>

#define MAXCHAR  10
#define MAXSTR   10

int main(void)
{
    int i, n, c;  char str[MAXSTR][MAXCHAR + 1];

    for (n = 0; n < MAXSTR; ) {
        printf("文字列%dを入力:", n + 1); 
        for (i = 0; (c = getchar()) != '\n'; )
            if (i < MAXCHAR) str[n][i++] = c;
        str[n][i] = '\0';
        if (str[n][0] == '0') break;
        if (str[n][0] == '\0') printf("再入力:\n");
        else printf("累積レコード数:%d\n", ++n);
    }
    for (i = 0; i < n; i++)
        printf("%d件目:%s\n", i + 1, str[i]);
    return 0;
}