ページ 11

ファイルの読み書き!!

Posted: 2007年3月23日(金) 21:41
by み~
お久しぶりです!!みなさんにアドバイスを沢山頂きようやくファイルのことが分かってきました。本当に感謝
しております!!下のコードでちょっと問題発生です!!アドバイスよろしくお願いします!!
//書き込みコード
#include <stdio.h>
#define NUM 3

int main(void) {
	FILE *fp;
	char no[NUM][10];
	char name[NUM][20];
	char point[NUM][10];
	char buf[NUM][256];
	int i;
	fp = fopen("student.txt","w");
	if(fp == NULL) {
		return 1;
	}
	printf("FILE OPEN\n");
	
	for(i = 0; i < NUM; i++) {
		printf("%d人目",i + 1);
		printf("NO>>>");
		scanf("%s",buf);
		fprintf(fp,"NO>>>%s\n",buf);
		printf("NAME>>>");
		scanf("%s",buf);
		fprintf(fp,"NAME>>>%s\n",buf);
		printf("POINT>>>");
		scanf("%s",buf);
		fprintf(fp,"POINT>>>%s\n",buf);
	}
	printf("書き込み終了\n");

	fclose(fp);
	return 0;
}
//読み込みコード
#include <stdio.h>
#define NUM 3

int main(void){
	FILE *fp;
	int buf[20];
	int i;
	
	fp = fopen("student.txt","r");
	if(fp == NULL) {
		return 1;
	}
	printf("FILE OPEN\n");

	for(i = 0; i < NUM; i++){
		printf("%d人目\n",i + 1);
		fgets(&buf,sizeof(buf),fp);
		printf("%s\n",buf);
		fgets(&buf,sizeof(buf),fp);
		printf("%s\n",buf);
		fgets(&buf,sizeof(buf),fp);
		printf("%s\n",buf);
	}
	fclose(fp);
	return 0;
}
書き込み、読み込み成功しているのですが、読み込みコードをコンパイルするときfgets()の部分で警告
「問題のあるポインタの変換」とでてしまいます。どうしてでしょう?

Re:ファイルの読み書き!!

Posted: 2007年3月23日(金) 22:11
by box
> //書き込みコード
> 	char no[NUM][10];
> 	char name[NUM][20];
> 	char point[NUM][10];

no, name, pointは、定義しただけで使っていません。
よいのでしょうか?

> 		scanf("%s",buf);

2次元配列にしている意味がないように見えます。
buf と書くべきでありましょう。

> //読み込みコード
> 	int buf[20];

char型で書き込んだ内容を、なぜint型で読み込むのでしょうか?

> 		fgets(&buf,sizeof(buf),fp);

第1引数の&は不要です。

Re:ファイルの読み書き!!

Posted: 2007年3月23日(金) 22:52
by み~
boxさんご指摘&アドバイスありがとうございます!!
>no, name, pointは、定義しただけで使っていません

確かに使ってないですね。マズイですね。bufとするべきでしたね。。


>char型で書き込んだ内容を、なぜint型で読み込むのでしょうか?

うっかりしてました・・^^; まだまだ勉強不足ですね。。

Re:ファイルの読み書き!!

Posted: 2007年3月23日(金) 23:19
by むつ
以下のソースは、
 ・入力してすぐ書き込み用データ蓄積、読み込んですぐ表示
 (データ入力・読み込み後のチェックをしていない)
 ・数値も全てcharで扱っている。
この通りなので、あまり良い例ではありませんが、
最低限、お望みの動作はするかと思います。
修正点はかなりありますので、み~さんのソースと見比べてみてください。

※ソースを読みやすくする為に、空白を適所にいれると、ケアレスミスも減りますよ。
/* 書き込み */
#include <stdio.h>
#define NUM 3
int main( void )
{
	FILE *fp;
	char buf[ 256 ];
	int i;
	fp = fopen( "student.txt", "w" );
	if( fp == NULL ) {
		return 1;
	}
	printf( "FILE OPEN\n" );
	
	for( i = 0; i < NUM; i++ ) {
		printf( "%d人目\n", i + 1 );
		printf( "NO>>>" );
		scanf( "%s", &buf );
		fprintf( fp, "%s\n", buf );

		printf( "NAME>>>" );
		scanf( "%s", &buf );
		fprintf( fp, "%s\n", buf );

		printf( "POINT>>>" );
		scanf( "%s", &buf );
		fprintf( fp, "%s\n", buf );
	}
	printf( "書き込み終了\n" );
	fclose( fp );
	return 0;
}

/* 読み込みコード */
#include <stdio.h>
#include <string.h>
#define NUM 3

int main( void )
{
	FILE *fp;
	unsigned char buf[ 256 ];
	int i;
	fp = fopen( "student.txt", "r" );
	if( fp == NULL ) {
		return 1;
	}
	printf( "FILE OPEN\n" );

	for( i = 0; i < NUM; i++ ){
		printf( "%d人目\n", i + 1 );

		fgets( buf, sizeof( buf ), fp );
		// fgetsは改行も取ってきてしまうので、改行を\0に置き換え
		// 読み込んだ内容をチェックする時に改行が邪魔をするので
		buf[ strlen( buf ) - 1 ] = '\0';
		// 改行をつけて表示
		printf( "%s\n", buf );

		fgets( buf, sizeof( buf ), fp );
		buf[ strlen( buf ) - 1 ] = '\0';
		printf( "%s\n", buf );

		fgets( buf, sizeof( buf ), fp );
		buf[ strlen( buf ) - 1 ] = '\0';
		printf( "%s\n", buf );
	}
	fclose( fp );
	return 0;
}

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 08:41
by み~
むつさんへ。
わざわざありがとうございます。参考にさせていただきます。

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 09:22
by み~
今度はバイナリファイルに書き込み、ランダムアクセスをするというものです。
バイナリファイルというものは、普通人間が見ても分からないようになっていますよね。だが、私が書き込んだ
ファイルを見ると、このようにファイルのなかに書き込まれていました↓

123 e N a abc e N a m e d O b 10 e N a 456 e N a def e N a m e d O b 20 e N a 789 e N a ghi e N a m e d O b 30 e N a

確かにNOには123,NAMEにはabcとしました。書き込みの時のファイルの拡張子がいけないのでしょうか?普通バイナリテキストの時の拡張子は.txtとはしないのですか?
PS:私の場合ファイルはバイナリエディタなど使っていません。普通のメモ帳に書き込んでいます。

ランダムアクセスのfseek(fp,0,SEEK_SET);は先頭から0バイト目を読み込むというものですよね?そしてfread(&buf,10,1,fp)で10バイト分を1回読み込むということじゃないですか。すると私の場合、123と出てきてしますのですが、これでいいのでしょうか?文字は1バイトだから123abc1045とでると思うのですが。。


NO>>>123 name>>>abc point>>>10
NO>>>456 name>>>def point>>>20
NO>>>789 name>>>ghi point>>>30
とバイナリファイルにはかきこみました。
//書き込みコード
#include <stdio.h>
#define NUM 3

int main(void) {
	FILE *fp;
	char no[NUM][10];
	char name[NUM][20];
	char point[NUM][10];
	char buf[NUM][256];
	int i;
	fp = fopen("student1.txt","wb");
	if(fp == NULL) {
		return 1;
	}
	printf("FILE OPEN\n");
	
	for(i = 0; i < NUM; i++) {
		printf("%d人目",i + 1);
		printf("NO>>>");
		scanf("%s",buf);
		fwrite(&buf,10,1,fp);
		printf("NAME>>>");
		scanf("%s",buf);
		fwrite(&buf,20,1,fp);
		printf("POINT>>>");
		scanf("%s",buf);
		fwrite(&buf,10,1,fp);
	}
	printf("書き込み終了\n");

	fclose(fp);
	return 0;
}
読み込みコード
#include <stdio.h>

int main(void) {
	FILE *fp;
	char buf[20];

	fp = fopen("student1.txt","rb");
	if(fp == NULL){
		return 1;
	}
	printf("FILE OPEN\n");
	
	fseek(fp,0,SEEK_SET);
	fread(&buf,10,1,fp);
	printf("%s",buf);

	fclose(fp);
	return 0;
}

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 11:17
by miyaza
今回の書き込みで
31 31 34 00 CC CC
という感じでバイナリが続いていきます。結局テキストファイルというもの自体がこういったバイナリを文字に変換して表示するものなので。メモ帳で開き続ける限り普通じゃない部分 CC CC なども表示されますが、正常な書き込み部分も表示されます。

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 11:21
by miyaza
そもそも文字コードを書き込んでいるのだからメモ帳で開けるのは当たり前です。これがint型で数値を書き込んでいたらメモ帳では読み取れませんが。

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 11:37
by miyaza
> ランダムアクセスのfseek(fp,0,SEEK_SET);は先頭から0バイト目を読み込むというものですよね?そしてfread
> (&buf,10,1,fp)で10バイト分を1回読み込むということじゃないですか。すると私の場合、123と出てきてします
> のですが、これでいいのでしょうか?文字は1バイトだから123abc1045とでると思うのですが。。

最初の書き込み部分でNOを10バイト書き込んでいるからです。

だから頭から10バイトがNOでそこから20バイトが文字という感じです。10バイトの部分は書き込んだデータと残りがあり読み込んだときに正常な部分しか表示されないため123と表示されます。
だから、123abc1045と表示されたらその方が異常です。

31 31 34 00 CC CC CC CC CC CC

こんなかんじでNOが10バイト分書き込まれています。そして 31 31 34 の部分が123をあらわして 00 が終端を表しているのでここまでしか表示されません。

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 12:01
by み~
miyazaさん解説ありがとうございます。

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 13:38
by 組木紙織
バイナリーで読み込んでを16進数で表示するプログラムです。
参考までにどうぞ。
#include<stdio.h>
#include<stdlib.h>

int main(int argc, char *argv[/url])
{
 FILE *fp, *fp2;
 unsigned char ch ,out[2];
 int num;
 	if(argc != 2){
		printf("error! program end ");
   		return EXIT_SUCCESS;
	}
	fp = fopen(argv[1],"rb");
	if(fp == NULL){
		printf("Don't open file\n");
		return EXIT_SUCCESS;
	}else{
	 	printf("file open\n");
	}
	
//処理の中心
	while(!feof(fp)){
		for(num =0;num<0xf;num++){
			fread(&ch ,sizeof(ch) ,1, fp);
			if(feof(fp)) break;
			printf("%2x ",ch);
		}
		printf("\n");
	}	
	fclose(fp);
 	return EXIT_SUCCESS;
}

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 16:47
by miyaza
> 31 31 34 00 CC CC CC CC CC CC
>こんな感じでNOが10バイト分書き込まれています。そして 31 31 34 の部分が123をあらわして 00 が終端を表してい>るのでここまでしか表示されません。

間違えました

訂正

31 32 33 00 CC CC CC CC CC CC
こんな感じでNOが10バイト分書き込まれています。そして 31 32 33 の部分が123をあらわして 00 が終端を表しているのでここまでしか表示されません。

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 16:53
by み~
組木紙織さんありがとうございます。
//書き込みコード
#include <stdio.h>
#define NUM 3

int main(void) {
	FILE *fp;
	char no[NUM][10];
	char name[NUM][20];
	char point[NUM][10];
	char buf[NUM][256];
	int i;
	fp = fopen("student.txt","w");
	if(fp == NULL) {
		return 1;
	}
	printf("FILE OPEN\n");
	
	for(i = 0; i < NUM; i++) {
		printf("%d人目",i + 1);
		printf("NO>>>");
		scanf("%s",buf);
		fprintf(fp,"NO>>>%s\n",buf);
		printf("NAME>>>");
		scanf("%s",buf);
		fprintf(fp,"NAME>>>%s\n",buf);
		printf("POINT>>>");
		scanf("%s",buf);
		fprintf(fp,"POINT>>>%s\n",buf);
	}
	printf("書き込み終了\n");

	fclose(fp);
	return 0;
}
ファイルにコンソールから入力させる方法ってscanf(),fgets()以外になにかありませんかね??
getschar()だと結構面倒だけど実際は使われてるもんなのでしょうか?私のコードでgetschar()で入力
させていくとしたらどうですかね?すごく面倒なことになりそうなんですけど・・・・。

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 17:08
by miyaza
getcahr()を使うのであれば、while()で改行文字が入力されるまで、ループさせるような感じでいいと思います。

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 17:18
by み~
>getcahr()を使うのであれば、while()で改行文字が入力されるまで、ループさせるような感じでいいと思います。


でも私のコードだとかなり面倒ですよね?一人一人のデータをforでループさせて、さらにwhileでもループさせせるわけですよね??

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 17:22
by miyaza
> でも私のコードだとかなり面倒ですよね?一人一人のデータをforでループさせて、さらにwhileでもループさせせる> わけですよね??
そうですね。
しかしgetchar()は一文字しか読み取れないのでループ文で読み込むしかないと思います。

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 17:26
by み~
すると、わざわざgetcharなんて使わなくてもいいですよね?

getcharを使う場合ってどういう場合なのですか?一文字だけって・・・。

Re:ファイルの読み書き!!

Posted: 2007年3月24日(土) 20:02
by miyaza
一文字だけ入力したいとき。
入力処理をより厳密にしたいときなどに使えると思います。

一文字だけというのをいかした使い方をすればいいと思います。

Re:ファイルの読み書き!!

Posted: 2007年3月25日(日) 08:18
by み~
miyazaさんへ
いつもいつも分かりやすい解説ありがとうございます!!