配列の配列の動的確保について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
おーばー

配列の配列の動的確保について

#1

投稿記事 by おーばー » 7年前

コード:

 int main(void)
 {
  int no=0,i,j;
  int size=256;
  char **s=NULL;
  for(j=0;no!=EOF;j++){  
   char buf[256];
   for(i=0;no!='\n';i++){
    if(i==0)printf("%d個目 ",j+1);
    no=getchar();
    if(no!='\n')
    buf[i]=no;
    }
   if(j==0)s=malloc(sizeof(char*)*256);
   
   s[j]=malloc(sizeof(char)*256);
   buf[i]='\0';
   strcpy(s[j],buf);
   
   if((no=getchar())=='\n')break;
  }
  for(i=0;i<3;i++)
  printf("%s\n",s[i]);
  return 0;
  }
こちらのプログラムで質問があります
このプログラムの自分の中での目的は入力されたものを配列bufに格納して、そしてbufの文字数をもとにcharのポインタのポインタであるsを二次元配列を実現させたいなと思っています
getcharでは改行されたのを確認すると一つの文字列の入力の終了を意味させるためにfor文の条件を上記のように記述しました,
また文字列の頭から改行されたことを確認するとすべての入力の終了を意味させるためにbreak文でfor文からでるように記述しました
いざ実行させると最後のprintf文で自分の思うものとは違った表示が出ます

入力
aa
bb
cc
dd
ee
ff


出力

1個目 aa
bb
2個目 cc
3個目 dd
4個目 ee
5個目 ff
6個目
aa
ba
ca

入力出力はともにこのような感じです
理想は
aa
bb
ccと入力すると
1個目aa
2個目bb
3個目cc
と出力されてほしいです

box
記事: 2002
登録日時: 13年前

Re: 配列の配列の動的確保について

#2

投稿記事 by box » 7年前

こんな感じでしょうか。入力時、いきなりエンターキーを押すとそこで入力を終わるようにしています。

コード:

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

#define SIZE (256)

int main(void)
{
    char **s;
    int i, j;

    s = malloc(sizeof(char *) * SIZE);
    if (!s) fprintf(stderr, "memory allocation error\n"), exit(1);

    for (i = 0; i < SIZE; i++) {
        char buf[SIZE];

        fgets(buf, SIZE, stdin);
        if (buf[0] == '\n') break;
        buf[strlen(buf)-1] = '\0';
        s[i] = malloc(sizeof(char) * (strlen(buf) + 1));
        if (!s[i]) fprintf(stderr, "memory allocation error\n"), exit(1);
        strcpy(s[i], buf);
    }

    for (j = 0; j < i; j++) {
        printf("%d個目:", j + 1);
        printf("%s\n", s[j]);
    }

    for (j = 0; j < i; j++) free(s[j]);
    free(s);
    return 0;
}
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 配列の配列の動的確保について

#3

投稿記事 by みけCAT » 7年前

iのループの後getcharで読み込んだ文字を捨てている上、改行文字が来た時に書き込まないのにiだけ増え、ヌル文字を書き込む位置が間違っているのが良くないでしょう。
文字数をもとにしていない、エラーチェックをしていないなどの改善するべき点は残っていますが、とりあえず少しの修正でまともな出力になるようにしてみました。

コード:

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

int main(void)
{
	int no=0,i,j;
	int size=256;
	char **s=NULL;
	for(j=0;no!=EOF;j++){  
		char buf[256];
		for(i=0;;i++){
			if(i==0)printf("%d個目 ",j+1);
			no=getchar();
			if(no=='\n' || no==EOF)break;
			buf[i]=no;
		}
		if(i==0)break;
		if(j==0)s=malloc(sizeof(char*)*256);

		s[j]=malloc(sizeof(char)*256);
		buf[i]='\0';
		strcpy(s[j],buf);

	}
	for(i=0;i<3;i++)
		printf("%s\n",s[i]);
	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

おーばー

Re: 配列の配列の動的確保について

#4

投稿記事 by おーばー » 7年前

boxさんの18行目のfgets関数はwhile((no=getchar)!='EOF'||no!='\n');を短く書いたという認識でいいのでしょうか?
意味の分からないことを言ってしまっていたのならすみません...
自分の中ではfgets関数は指定されたストリームから指定した文字列を入れる場所に入れていく,という機能だと思っています.

おーばー

Re: 配列の配列の動的確保について

#5

投稿記事 by おーばー » 7年前

"みけCAT"さん別のトピックでの助言,大変助かっています
今回もプログラムの問題点を指摘してくださって勉強になります!
オフトピック
少し本題と外れますが.. 改行後に前の行にカーソル移動をさせることは可能ですか?

box
記事: 2002
登録日時: 13年前

Re: 配列の配列の動的確保について

#6

投稿記事 by box » 7年前

おーばー さんが書きました:boxさんの18行目のfgets関数はwhile((no=getchar)!='EOF'||no!='\n');を短く書いたという認識でいいのでしょうか?
fgets() のリファレンスを見ていただくのがいちばん確実だと思います。
私ごときがヘタな回答をしてしまってどなたかから突っ込みが入るのがこわいですから。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 配列の配列の動的確保について

#7

投稿記事 by みけCAT » 7年前

おーばー さんが書きました:boxさんの18行目のfgets関数はwhile((no=getchar)!='EOF'||no!='\n');を短く書いたという認識でいいのでしょうか?
いいえ。
まず、あなたのコードは以下の点で間違っています。
  • getchar関数を呼び出さず、getchar関数へのポインタを処理系定義の方法で整数に変換してnoに格納している
  • ファイル終端を表すデータのマクロEOFではなく、処理系定義の値を持つ複数文字の文字定数が使われている
  • 「noが(おそらく)複数の異なる値のいずれかと等しくない」という条件でのループ、すなわち無限ループになっている
これらのバグを直すと、例えば以下のようになります。(noはint型の変数とします)

コード:

while((no=getchar())!=EOF&&no!='\n');
このコードは、以下の点でfgetsと異なります。
  • fgetsには読み込む長さの制限があるが、このコードには無い
  • fgetsでは読み込んだ文字を全てバッファに保存するが、このコードでは最後の文字(EOFまたは改行)しか保存しない
fgets関数の働きを学ぶには、リファレンスや規格書(に近いドラフト)を読みましょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

おーばー

Re: 配列の配列の動的確保について

#8

投稿記事 by おーばー » 7年前

お二方、ご丁寧にどうもありがとうございました!
今後も拙い文章で,かつ変なプログラムを載せてしまうと思いますがどうぞよろしくお願いしますm(__)m

閉鎖

“C言語何でも質問掲示板” へ戻る