ページ 1 / 1
配列の配列の動的確保について
Posted: 2016年8月06日(土) 03:43
by おーばー
コード:
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
と出力されてほしいです
Re: 配列の配列の動的確保について
Posted: 2016年8月06日(土) 06:57
by box
こんな感じでしょうか。入力時、いきなりエンターキーを押すとそこで入力を終わるようにしています。
コード:
#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;
}
Re: 配列の配列の動的確保について
Posted: 2016年8月06日(土) 09:05
by みけCAT
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;
}
Re: 配列の配列の動的確保について
Posted: 2016年8月08日(月) 13:29
by おーばー
boxさんの18行目のfgets関数はwhile((no=getchar)!='EOF'||no!='\n');を短く書いたという認識でいいのでしょうか?
意味の分からないことを言ってしまっていたのならすみません...
自分の中ではfgets関数は指定されたストリームから指定した文字列を入れる場所に入れていく,という機能だと思っています.
Re: 配列の配列の動的確保について
Posted: 2016年8月08日(月) 13:33
by おーばー
"みけCAT"さん別のトピックでの助言,大変助かっています
今回もプログラムの問題点を指摘してくださって勉強になります!
オフトピック
少し本題と外れますが.. 改行後に前の行にカーソル移動をさせることは可能ですか?
Re: 配列の配列の動的確保について
Posted: 2016年8月08日(月) 21:30
by box
おーばー さんが書きました:boxさんの18行目のfgets関数はwhile((no=getchar)!='EOF'||no!='\n');を短く書いたという認識でいいのでしょうか?
fgets() のリファレンスを見ていただくのがいちばん確実だと思います。
私ごときがヘタな回答をしてしまってどなたかから突っ込みが入るのがこわいですから。
Re: 配列の配列の動的確保について
Posted: 2016年8月08日(月) 21:47
by みけCAT
おーばー さんが書きました: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関数の働きを学ぶには、リファレンスや規格書(に近いドラフト)を読みましょう。
Re: 配列の配列の動的確保について
Posted: 2016年8月08日(月) 23:30
by おーばー
お二方、ご丁寧にどうもありがとうございました!
今後も拙い文章で,かつ変なプログラムを載せてしまうと思いますがどうぞよろしくお願いしますm(__)m