C言語関係掲示板

過去ログ

No.579.ポインタの配列で"NULL pointer assignment"

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

ポインタ配列
投稿者---SIN(2003/02/26 02:48:41)


こんばんは。質問なんですが、ポインタ配列を使って
以下のようなプログラムをつくったのですが、
表示結果が"NULL pointer assignment"と表示され、
どうにもうまくいきません。いろいろ試したのですが、
どうしても理由がわかりません。どうか教えていただけないでしょうか。
コンパイラはlsic86です。

/*あるファイルを読み込み、二つ以上の連続した空白を
 一つの空白に変換して出力するプログラム */ 

#include<stdio.h>
#include<ctype.h>

#define		MAXSTR		1000
#define		MAXLINE     1000


main()
{
	int  i;
	char inline[MAXSTR];					/* 入力された文字列 */
	char *outline[MAXLINE];					/* 出力する文字列	*/
	char *p;                              
	char **q;
	char *qc;
	
	q=outline;
	while(gets(inline)){  
		qc=*q;
		for(p=inline; *p; ++p){
			if(*p==' '){
				while(*p==' ')
					p++;
				p--;
			}
			*qc=*p;
			qc++;
			*qc=0;
		}
		q++;
		*q=0;
	}
	
	
	for(i=0; *outline[i]; i++)
		printf("%s\n",outline[i]);
}


No.5381

Re:ポインタ配列
投稿者---a"(2003/02/26 04:02:27)


#define MAXSTR 1000
#define MAXLINE 5


void main(void){
    int  i;
    char line[MAXSTR];                    /* 入力された文字列 */
    char outline[MAXLINE][MAXSTR]={0,0,0,0,0};        /* 出力する文字列    */
    char *p;                              
    char *qc;
    
    for(i=0;i<MAXLINE-1 && gets(line);i++){
        qc=outline[i];
        for(p=line; *qc=*p; qc++,p++){
            if(*p==' '){
                while(*p==' ')p++;
                --p;
            }
        }
        *qc=0;
    }
    for(i=0;*outline[i]; i++)
        printf("%s\n",outline[i]);
}


No.5382

Re:ポインタ配列
投稿者---あかま(2003/02/26 04:55:06)


こんな感じでどうじゃろう?いちおうgccでは動いたんですが。
*outline[MAXLINE]に文字列をいれるメモリを確保し忘れている気がします。
ポインタのポインタは頭が混乱しますね><

#include<stdio.h>
#include<ctype.h>

#define		MAXSTR		1000
#define		MAXLINE     1000


main()
{
	int  i;
	char inline[MAXSTR];					/* 入力された文字列 */
	char *outline[MAXLINE];					/* 出力する文字列	*/
	char *p;                              
	char **q;
	char *qc;
	
	q=outline;
	
	while(gets(inline)){
		*q = (char *)malloc(strlen(inline));
		qc=*q;
		
		for(p=inline; *p; ++p){
			if(*p==' '){
				while(*p==' ')
					p++;
				p--;
			}
			*qc=*p;
			qc++;
			
		}
		*qc='\0';
		q++;
		*q=0;
	}
	
	for(i=0; outline[i]; i++){
		printf("%s\n",outline[i]);
		free(outline[i]);
	}
	
	
}


No.5383

Re:ポインタ配列
投稿者---あかま(2003/02/26 05:23:05)


まちがえ。
*q = (char *)malloc(strlen(inline));

*q = (char *)malloc(strlen(inline)+1);


No.5387

Re:ポインタ配列
投稿者---ところで(2003/02/26 07:18:36)


それだと、(1)や(2)のようなことになるかもしれませんよね。
(1) whileループが1度も回らないとき、outlineの不正な参照または不正なfree
(2) MAXLINE行より多い行数のとき、outlineのバッファオーバーラン

例えば、以下のようなチェックを入れるとか。
問題の本質でない、あら探しみたいですみません (^^;
q=outline;
*q=0; /* (1)のため */
while(gets(inline)){
/* ...省略... */
*qc='\0';
q++;
*q=0;
if (q>=&outline[MAXLINE]) /* (2)のため */
break;
}

for(i=0; outline[i]; i++){
printf("%s\n",outline[i]);
free(outline[i]);
}


No.5393

うーん...
投稿者---SIN(2003/02/26 14:46:08)


皆様、ご丁寧にありがとうございます。
メモリ領域の確保が足りなかったのですね。
ですが、私のコンパイラ(lsic86)だと動きませんでした。
(何も表示されない)
適当に文章をコピーしたcファイルをつくり、
それをリダイレクトする形をとっているのですが...


No.5394

Re:うーん...
投稿者---あかま(2003/02/26 16:47:36)


ところでさんフォローサンクスです。
まったく気付いてませんでした><

>何も表示されない
Ctrl+Zでループを止めると直後のprintfが実行されなかったりするみたいです。
こちらに解説があります。
1行どころかまったく出力されない時は…どなたかよろ。

No.5403

Win9x環境でCtrl+ZでEOFになっても出力する
投稿者---ところで(2003/02/27 01:29:45)


>Ctrl+Zでループを止めると直後のprintfが実行されなかったりするみたいです。
>こちらに解説があります。
なるほど。以前私もそのことで困ったことがありました。
勉強になります。

でも、どうしても表示させようとやってみました。
表示するforループの前に改行出力をすると、、、
Ctrl+Zで止めても表示されました。理由は分かりません (^^;。
(Borland C++ Compilerでコンパイル。lsic86は持ってないので)

まあ他環境でも同一出力を期待するなら、この方法は止めたほうがいいです。
fprintf(stderr, "\n");			/* こんな文を挿入 */
for(i=0;*outline[i]; i++) /* a"さんのコードを例に" */
printf("%s\n",outline[i]);

実行結果
(Windows98SE MS-DOSプロンプト)。1行のみ入力しCtrl+Zで抜ける。
_(下線)は (スペース)の意味。
C> program.exe
_____abc___def_g__h_i_←(1ここでReturnキーを押す)
←(ここでCtrl+Zを押す)
_abc_def_g_h_i_

C>
余計な改行を標準エラーに吐くのが嫌なら、EOFで抜けた場合だけ
fprintf(stderr, "\n")するのがいいかもです。
なにか間違ってたら訂正お願いします。


No.5407

どうもありがとうございました。
投稿者---SIN(2003/02/27 18:43:50)


あれからコマンドライン引数(第2引数にファイル名)と
ファイル入出力を使って、他ファイルにアクセスする方法を
考えたのですが、結果はまったく同じでした(1行すら表示されない)。

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


#define		MAXSTR		1000
#define		MAXLINE     1000


main(int argc, char *argv[])
{
	FILE *fp;
	int  i;
	char inline[MAXSTR];					/* 入力された文字列 */
	char *outline[MAXLINE];					/* 出力する文字列	*/
	char *p;                              
	char **q;
	char *qc;
	
	fp=fopen(argv[1],"r");
	
	q=outline;
	*q=0;
	while(fgets(inline, MAXSTR, fp)){  
		*q = (char *)malloc(strlen(inline)+1);
		qc=*q;
		for(p=inline; *p; ++p){
			if(*p==' '){
				while(*p==' ')
					p++;
				p--;
			}
			*qc=*p;
			qc++;
			*qc=0;
		}
		q++;
		*q=0;
	}
	for(i=0; *outline[i]; i++){
		printf("%s\n",outline[i]);
		free(outline[i]);
	}
	fclose(fp);

}

でも他ファイルにアクセスせずにDOS上(WindowsME)で
直接文字列を入力するとうまく出力されました。
これ以上悩んでも仕方ないので、次に進もうと思います。
ご教授してくれた皆様、本当にありがとうございました。