ファイルについて

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

ファイルについて

#1

投稿記事 by グー » 17年前

このプログラムなんですけど、警告、エラーが出まくり。なんで?
ヘッダーとかも別に間違っていないと思うけど・・・・。
なんでだろ?
#include <stdio.h>
#include <stdlib.h>

int main(void) {

	int i;
	int sum;
	int val;
	double avg;
	sum = 0;
	avg = 0;
	FILE *fp;
	if(fp = fopen("test.txt","r") == NULL) {
		printf("file open erroe\n");
		return 1;
	}
	printf("file open\n");

	for(i= 0; "" ; i++) {
		fscanf(fp, "%d\n",&val);
			if(val == 0) {
				break;
			}
			sum = sum + val;
		}
	}
	avg = sum / i;

	printf("合計>>%d,平均>>%d",sum,avg);

	fclose(fp);
	return 0;
}

組木紙織

Re:ファイルについて

#2

投稿記事 by 組木紙織 » 17年前

気になる部分だけコメント入れてあります。
修正はしていないですが、修正すればコンパイルできると思います。
#include <stdio.h>
#include <stdlib.h>

int main(void) {

	int i;
	int sum;
	int val;
	double avg;
	sum = 0;
	avg = 0;
/*宣言位置が違う、先頭で定義していない。*/	
	FILE *fp;
/*優先順位の問題により先に[==]を考えている*/
	if(fp = fopen("test.txt","r") == NULL) {
		printf("file open erroe\n");
		return 1;
	}
	printf("file open\n");

	for(i= 0; "" ; i++) {
		fscanf(fp, "%d\n",&val);
			if(val == 0) {
				break;
			}
			sum = sum + val;
		}
/*括弧が一つ多い*/	
	}
	avg = sum / i;

	printf("合計>>%d,平均>>%d",sum,avg);

	fclose(fp);
	return 0;
}

グー

Re:ファイルについて

#3

投稿記事 by グー » 17年前

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

int main(void) {
	FILE *fp;

	int i;
	int sum;
	int val;
	double avg;
	sum = 0;
	avg = 0;
	
	fp = fopen("test.txt","r");
	if(fp == NULL) {  
		printf("file open erroe\n");
		return 1;
	}
	printf("file open\n");

	for(i= 0;  ; i++) {
		fscanf(fp, "%d\n",&val);
			if(val == 0) {
				break;
			}
			sum = sum + val;
		}
	
	avg = sum / i;

	printf("合計>>%d,平均>>%d",sum,avg);

	fclose(fp);
	return 0;
}
こんな感じにしました。確かにコンパイルはできたのですが、avgに代入した値は使われていないとかで警告
が一つでました。そのまま実行したら、file openとだけでて動かなくなってしまいました。

組木紙織

Re:ファイルについて

#4

投稿記事 by 組木紙織 » 17年前

まず[test.txt]の中身が気になります。最後が0で終わっていますか?

avgは最初に0で初期化してありますが、0で初期化する必要はこの場合ありませんよね?
コンパイラ0で初期化して、その値を使っていないということを警告しています。

最後にforの部分は無限ループとなるので[for(;;)]とするのが一般的だと思います。
その場合にはの宣言は必要なくなります。

これらの点に気をつけてみてください。

グー

Re:ファイルについて

#5

投稿記事 by グー » 17年前

一応成功しました。test.txtの中身は
150
164
153
174
189
185
168
156
152
174
173
169
です。
for()の中の条件式をi < 12としたらできました。でも一々条件式かいていたら面倒ですね。

組木紙織

Re:ファイルについて

#6

投稿記事 by 組木紙織 » 17年前

すみません
訂正です。
はループ以外の部分でも使っていました。
この場合は単純に無限ループだけに使っているわけではないので、問題ないです。
すみませんでした。

グー

Re:ファイルについて

#7

投稿記事 by グー » 17年前

いえいえい。アドバイスありがとうございます。
ところで、for(;;)というのはどういうことなのでしょう?確かに私のテキストにもfor()文は条件式がありませんでした。

組木紙織

Re:ファイルについて

#8

投稿記事 by 組木紙織 » 17年前

面倒でないようにするためには
1:テキストファイルの最後を0にする。
2:ファイルの終わりを確認する手段を入れる。
3:テキストファイルの先頭に要素の数を入れて、ループをその回数だけまわす。

といった手段があります。

組木紙織

Re:ファイルについて

#9

投稿記事 by 組木紙織 » 17年前

簡単に説明すると、永久に続くループを作る手段の方法のひとつとでも覚えてください。
while(1){}も同じような効果があります。
#include <stdio.h>
#include <stdlib.h>

int main(void) {

	int i=0;
	
/*
	永久にループが続くので
	Ctrl + Cなどで止めてください
*/
	for(;;){
	 	printf("%d\n",i);
	}
	return 0;
}

グー

Re:ファイルについて

#10

投稿記事 by グー » 17年前

私の持っているテキストでは、こんなコードになっています。
while(fscanf(fp, "%d",&val) != EOF)の部分がよく分からないですね。
あと、cntが、未定義のシンボルとでてしまいます。なぜでしょう?
#include <stdio.h>

int main(void) {
	FILE *fp;
	int val;
	int sum;
	int cnt;

	if((fp = fopen("test.txt","r")) == NULL) {
		return 1;
	}
	printf("oprn\n");

	cnt = 0;
	while(fscanf(fp, "%d",&val) != EOF) {
		sum = sum + val;
		cont++;
	}
	
	if(cnt > 0) {
		printf("合計>>%d,平均>>%d",sum,sum/cnt);
	}
	fclose(fp);
	return 0;
}

組木紙織

Re:ファイルについて

#11

投稿記事 by 組木紙織 » 17年前

EOFはEnd OF Fileの略です。
ファイルの最後を示すものと考えてください。
>while(fscanf(fp, "%d",&val) != EOF) {
この部分でファイルが終わるまでループをまわし続けるという意味になります。

cntとcontありますが、タイプミスですか?

グー

Re:ファイルについて

#12

投稿記事 by グー » 17年前

タイプミスです。

あと、scanfとsscanfがかいてあるのですが、どの様に違うのでしょう?sscanfを使うメリットとはなにか
あるのでしょか?

組木紙織

Re:ファイルについて

#13

投稿記事 by 組木紙織 » 17年前

簡単に言うと
scanf()はコンソール入力から、sscanf()は文字列から入力元()を取るという違いがあります。

簡単に使い方を示しておきます。
#include <stdio.h>

int main(void) {
	char string[/url] = "125 a";
	int num;
	char ch;
	 
	sscanf(string, "%d %c",&num, &ch);
	
	printf("%d %c\n",num, ch);
	
	return 0;
}
メリットは
scanf()はある一定の条件においてはプログラムが正しくない動きをすることがあり、
それを防ぐためにsscanf()を使うことが多いです。

というような感じです。
このことに関しては色々な場所で議論されているので調べてみたらどうでしょうか?

グー

Re:ファイルについて

#14

投稿記事 by グー » 17年前

#include <stdio.h>

int main(void) {
	FILE *fp;
	int val;
	int sum;
	int cnt;
	char buff[100];

	if((fp = fopen("test.txt","r")) == NULL) {
		return 1;
	}
	printf("oprn\n");

	cnt = 0;
	while(fgets(buff,buff[100],fp)) { 
		sscanf(buff,"%d",&val);
		sum = sum + val;
		cnt++;
	}
	
	if(cnt > 0) {
		printf("合計>>%d,平均>>%d",sum,sum/cnt);
	}
	fclose(fp);
	return 0;
}
これだと、コンパイルはできるのですが実行できないです。なぜか、ループ処理の中の条件式を
書かないと私のは動きませんね。やっぱりVisual stadioとか入れるべきなのかな?

後、fgets()ってファイルの読み込みとなっていますが、書き込みもできますよね?
fgets(第一引数、第二引数、stdin)として、fprintf()をつかってやれば?

組木紙織

Re:ファイルについて

#15

投稿記事 by 組木紙織 » 17年前

私自身はVisual stadioは重いのであまり好きではないのですが、確かにあったほうが便利な部分は多いです。

本題に入りますが、
fget()の引数と、戻り値は何であるか知っていますか?
この場合はコンパイルが出来ても動作は正しく動かないです。

char *fgets(char *文字列, int 数値, FILE *ストリーム)
となっています。
今気をつけるのは二番目の引数の数値の部分と戻り値の部分です。
二番目の引数の意味は文字列に読み込む文字数を与えないといけないです。
上のプログラムでは文字列の100番目の部分にある部分を数値で読み取った場合の値となるので
通常は読み込む文字数をそのまま入れればよいでしょう。

戻り値ですが、この戻り値は文字列へのポインタを返しますので、whileの条件判断の部分に
入れるのは不適当だと思います。


fgets(buff,99,fp);
で入力して、
として終わりの判断はfeof()関数を使ってあげればよいかと思います。

fgets()だけでは書き込みは不可能です。
この関数は文字列の読み込みに使うだけなので、書き込むためには読み込んだ文字列を
別の関数を使って書き込みしないといけなくなります。

その意味ではfget(,,stdin)でコンソールから読み取った文字列をfprintf()でファイルに書き込むことはできますが。

グー

Re:ファイルについて

#16

投稿記事 by グー » 17年前

組木紙織さん詳しい解説ありがとうございます。

なんか訳わからなくなってきてしまいました。私の持っているテキストって・・・一体・・。

グー

Re:ファイルについて

#17

投稿記事 by グー » 17年前

ちょっと混乱したので基礎にもどります。
#include <stdio.h>

int main(void) {
	FILE *fp;
	int i;
	int val;
	int sum;
	
	fp = fopen("test.txt","r");
	if(fp == NULL) {
		return 0;
	}
	printf("OPEN!!\n");

	i = 0;
	sum = 0;
	while(fscanf(fp,"%d",&val) != EOF ){
		sum = sum + val;
		i++;
	}
	
	printf("合計:%d,平均:%d",sum,sum/i);
	
	fclose(fp);
	return 0;
}
これは成功したコードです。合計、平均がしっかりコンソールに出てきました。テキストファイルの中身は、
10
20
30
40
50
60
70
80
90です。
最初の方にwhile()の中身については教えていただいたので理解できました。
ただ、今度は文字列を読み込んでみようとおもうのですが、fscanf()ではダメですよね?
また、fscanf()だと色々と危険性の問題もあるようなので。
例えば、テキストファイルの中身がABCDEFという文字列だった場合です。文字列の場合はfgets()を使うの
でしょうか??

グー

Re:ファイルについて

#18

投稿記事 by グー » 17年前

文字列の読み込みに成功しました。ファイルにはabcdefgと書いておき読み込んだものです。コードは↓
[/pre]
#include <stdio.h>

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

fp = fopen("test1.txt","r");
if(fp == NULL) {
return 1;
}
printf("OPEN!!\n");


for(i = 0; i < 8; i++){
fgets(&ch,20,fp);
}

/*
while(fgets(&ch,20,fp) != EOF){
i++;
}
*/
     printf("%s",ch);
fclose(fp);
retrun 0;
}
[/pre]
for(i = 0; i < 8; i++)のところの条件式なのですが、今は読み込む数が少ないので数えれば分かるのですが、
数え切れないような量を読み込むときはどうしたらいいのでしょう?

また、最初はwhile()文(コメント部分)でやったのですが、コンパイルすらできませんでした。
0を検出するとか色々書いてあったのですが、よく分からなかったですね・・。ただwhile()の方が、
EOFとか使っているので、色々とトラブルは未然に防げるみたいですけど、なかなか理解できないです。

組木紙織

Re:ファイルについて

#19

投稿記事 by 組木紙織 » 17年前

文字列を入れる配列の大きさを十分大きくすればfscanf()でも問題はないです。
ABCDEFの文字列だと要素が7以上あれば問題はないです。(何で7以上か分かりますか?)
また引数の部分を"%s"ではなく"%6s"として取り込む文字数を指定することが出来ます。

fget()の場合は、取り込む文字数を指定しているので配列のサイズを取り込む文字数以上にしておけば
問題はないです。


文字列の場合fscanf()もfget()も取り込む文字数と配列のサイズとの兼ね合いを気をつけておけば
問題はないと思います。

グー

Re:ファイルについて

#20

投稿記事 by グー » 17年前

>>ABCDEFの文字列だと要素が7以上あれば問題はないです。(何で7以上か分かりますか?)
 char型は1バイトでabcdefで6バイト、それで最後の\0も必要だからですか?

後、私が書いたコードのfor()の条件式なのですが、i<1としてもしっかりと読み取れます。これはどういうことでしょう?

 

組木紙織

Re:ファイルについて

#21

投稿記事 by 組木紙織 » 17年前

>char型は1バイトでabcdefで6バイト、それで最後の\0も必要だからですか?
そうです。文字列を扱うときには最後の\0を意識して扱う必要があります。

>後、私が書いたコードのfor()の条件式なのですが、i<1としてもしっかりと読み取れます。これはどういうこ>とでしょう?

テキストファイルの中身を

abcdefghijklmnopqrtsuvwxyz
このようにして次のプログラムを実行してみてください。
で考えてみてください。
ポイントはfget()が何処まで文字を読み取るか?と、fget()は何をバッファに入れるか?ということです。
#include <stdio.h> 

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

fp = fopen("test1.txt","r"); 
if(fp == NULL) { 
return 1; 
} 
printf("OPEN!!\n"); 



fgets(&ch[0],20,fp);
printf("%s\n",ch);
fgets(&ch[1],20,fp);
printf("%s\n",ch); 
 


fclose(fp); 
return 0; 
}

box

Re:ファイルについて

#22

投稿記事 by box » 17年前

> 	for(i = 0; i < 8; i++){
> 		fgets(&ch,20,fp);
> 	}

ここのループの、変数 i の意味と、fgets 関数の第1引数の意味を教えてくださいますか?
ファイルポインタ fp から、最大20バイトを、どこへ格納しようとしているのでしょうか?
ch のアドレスでよいのでしょうか?

グー

Re:ファイルについて

#23

投稿記事 by グー » 17年前

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20]
a b c d e f g h i j k l m n o p q r s t u

fgets(&ch[0],20,fp);の第二引数が20だからchar[0]から20個読み取りなさいということでここまで読み込んだ。それで最後に\0が来るから実際に文字を読み込んでいるのは19個。\0もあわせて20個20バイトになる。

fgets(&ch[1],20,fp);はatuvwzとでてきました。よく分からないです。

組木紙織

Re:ファイルについて

#24

投稿記事 by 組木紙織 » 17年前

一番のポイントはfget()は文字列を扱うということです。
一度目のfget()で読み込み文字列
 abcdefghijklmnopqrs

&ch[0]に代入
  ↓ここから代入
 ch[0]   ch[1]   ch[2]    ch[3]   ch[4]   ch[5]  . . .
+++++++++++++++++++++++++++++++++++++++++++++++++
+       +       +       +       +       +       + 
+   a   +   b   +   c   +   d   +   e   +   f   + 
+       +       +       +       +       +       +
+++++++++++++++++++++++++++++++++++++++++++++++++


二度目のfget()で読み込む文字列
tuvwxyz

&ch[1]に代入
      ↓ここから代入
 ch[0]   ch[1]   ch[2]    ch[3]   ch[4]   ch[5]  . . .
+++++++++++++++++++++++++++++++++++++++++++++++++
+       +       +       +       +       +       + 
+   a   +   t   +   u   +   v   +   w   +   x   + 
+       +       +       +       +       +       +
+++++++++++++++++++++++++++++++++++++++++++++++++

グー

Re:ファイルについて

#25

投稿記事 by グー » 17年前

なるほど~。
でも、二回目の読み込みのとき aも出てきてしまったのは?

組木紙織

Re:ファイルについて

#26

投稿記事 by 組木紙織 » 17年前

>printf("%s\n",ch);
は文字列を何処から表示するのでしょうか?
ch[0]? ch[1]?

グー

Re:ファイルについて

#27

投稿記事 by グー » 17年前

う~・・・aからですか?
でも、aは二回も表示させてくないですよね。

組木紙織

Re:ファイルについて

#28

投稿記事 by 組木紙織 » 17年前

そうですね。
通常は上記のような扱い方をしません。
通常は
fget(ch,20,fp);
といったような使い方をします。

グー

Re:ファイルについて

#29

投稿記事 by グー » 17年前

>>通常fget(ch,20,fp); といったような使い方をします

そしたらfor()は意味がないですよね??

グー

Re:ファイルについて

#30

投稿記事 by グー » 17年前

やっぱりなぜaから二回目も出てくるのか分からないです。

>printf("%s\n",ch);
は文字列を何処から表示するのでしょうか?
ch[0]? ch[1]?
がわからないですね?なぜaからなのか。

組木紙織

Re:ファイルについて

#31

投稿記事 by 組木紙織 » 17年前

はい。そのとおりです。
for()なしで問題のプログラムを実行してみましたか?
問題なく動くと思います。

組木紙織

Re:ファイルについて

#32

投稿記事 by 組木紙織 » 17年前

printf("%s",ch);
int i=0;
for(;;){
	if(ch == '\0')break;
	printf("%c",ch);
	i++;
}

と考えたら分かると思います。

グー

Re:ファイルについて

#33

投稿記事 by グー » 17年前

for文使わないでもできました。

グー

Re:ファイルについて

#34

投稿記事 by グー » 17年前

上のコード実行しても何もおきないのですが・・・・。

グー

Re:ファイルについて

#35

投稿記事 by グー » 17年前

コードの実行できました。a~sまでが二回でてきました。

でも良く分からない。。

グー

Re:ファイルについて

#36

投稿記事 by グー » 17年前

実行したコードはこれです。
#include <stdio.h>

int main(void) {
	FILE *fp;
	int i;
	char ch[20];
	
	fp = fopen("test1.txt","r");
	if(fp == NULL) {
		return 1;
	}
	printf("OPEN!!\n");
	fgets(ch,20,fp);
	 
	i=0;
	for(;;){
		if(ch == '\0')break;
	printf("%c",ch);
	i++;
}
	printf("%s\n",ch)	;
     	
	fclose(fp);
	return 0;
}

組木紙織

Re:ファイルについて

#37

投稿記事 by 組木紙織 » 17年前

上のコードは考え方だけなのでそのままでは実行出来ないはずです。
一通り形にしてみると次のようになります。
#include <stdio.h> 

int main(void) {

char ch[/url] = "abcde"; 
int i;

/* %sを使った場合*/
printf("%s",ch);

printf("\n");

 /*%sを%cとループで代用した場合*/
i=0;
for(;;){
/*ここを注意深くみてください*/
	if(ch == '\0')break;
	printf("%c",ch);
	i++;
}

return  0; 
}

グー

Re:ファイルについて

#38

投稿記事 by グー » 17年前

なんとか自分なりに理解できました。

後、気になっていたのですが、数字を読み取る時にEOFを使ったじゃないですか。あれって文字列の時は使わなくていいのですか?

むつ

Re:ファイルについて

#39

投稿記事 by むつ » 17年前

ファイルから複数行読み取る際には、ファイルの終端(EOF)がわからないといけないですよね。
次のステップは、複数行の読み取りでしょうかね。

※ch[ここに一行分格納できるだけのサイズ]
※fgets( ch, ここのサイズを決定する, fp );

その後、ここをご覧ください。
http://www.bohyoh.com/CandCPP/C/Library/fgets.html

【 改行文字 】を読み取ったとき、
またはファイルの終わりを検出したときに、文字の読取りは終了し、
【 読み取った改行文字 】も配列に格納する。

このように、chへ取り込まれた改行をなくしたいなら、
'\0'で置き換える作業が必要かと思います。

グー

Re:ファイルについて

#40

投稿記事 by グー » 17年前

むつさんありがとうございます。
今、数値をfgets()で読み取り、数値に変換して計算するということをやっています。
#include <stdio.h>

int main(){
	FILE *fp;
	char ch[20];
	int i;
	int sum = 0;
	int val;

	fp = fopen("test.txt","r");
	if(fp == NULL) {
		return 1;
	}
	printf("ok\n");
	i = 0;
	sum = 0;
	while(fgets(ch,20,fp)){
		sscanf(ch,"%d",&val);
		sum = sum + val;
		i++;
	}
	printf("%d",sum);
	fclose(fp);
	return 0;
}
while(fgets(ch,20,fp))のところが良く分からないですね・・・。
whileってループですよね?条件式とかもないし。どういうことなんでしょう?fgets()の中身は
だいぶ分かってきました。

グー

Re:ファイルについて

#41

投稿記事 by グー » 17年前

ファイルに出力する問題でテキストの練習問題解いているのですが、実行するとエラーになってしまいます。どこがおかしいのでしょうか?scanfで入力させるのは良くないですかね?
#include <stdio.h>

int main(void) {
	FILE *fp;
	char no[10];
	char name[20];
	char point[10];
	int i;

	fp = fopen("student.txt","w");
	if(fp == NULL) {
		printf("エラーです\n");
		return 1;
	}
	printf("FILE OPEN\n");

	for(i = 0; i < 3; i++) {
		printf("%d人目の入力\n");
		scanf("%s",no);
		scanf("%s",name);
		scanf("%s",point);
	}
	for(i =0; i < 3; i++) {
		fprintf(fp,"%s\n",no);
		fprintf(fp,"%s\n",name);
		fprintf(fp,"%s\n",point);
	}
	fclose(fp);
	return 0;
}

バグ

Re:ファイルについて

#42

投稿記事 by バグ » 17年前

scanfの引数はアドレスじゃなかったかと…?
滅多に使わないから、うろ覚えなので、間違ってたらすみません…m(__)m

グー

Re:ファイルについて

#43

投稿記事 by グー » 17年前

今アドレス&を付けて実行したら、入力はできるのですが、入力が終わるとエラーになってしまいます。

miyaza

Re:ファイルについて

#44

投稿記事 by miyaza » 17年前

printf("%d人目の入力\n");の%dにあてはまる変数や値がないからです。

scanf("%s",no);
としていますがこれでは、一人目の人のデータを入力した後、二人目の人のデータを入力したときno[1]の部分から上書きしてしまうことになります。
name
point
も同様です。
3人分のデータを保存するのなら二次元配列にすることをおすすめします。

miyaza

Re:ファイルについて

#45

投稿記事 by miyaza » 17年前

> printf("%d人目の入力\n");の%dにあてはまる変数や値がないからです。
関係ありませんでした。しかし値は必要だと思います。

グー

Re:ファイルについて

#46

投稿記事 by グー » 17年前

miyazaさんありがとうございます。できました。こういうことですね。
#include <stdio.h>

int main(void) {
	FILE *fp;
	char no[3][10];
	char name[3][20];
	char point[3][10];
	int i;

	fp = fopen("student.txt","w");
	if(fp == NULL) {
		printf("エラーです\n");
		return 1;
	}
	printf("FILE OPEN\n");

	for(i = 0; i < 3; i++) {
		printf("%d人目の入力\n",i + 1);
		scanf("%s",&no);
		scanf("%s",&name);
		scanf("%s",&point);
	}
	for(i =0; i < 3; i++) {
		
		fprintf(fp,"%s\n",no);
		fprintf(fp,"%s\n",name);
		fprintf(fp,"%s\n",point);
	
	}
	fclose(fp);
	return 0;
}

コンソールから入力させるときはscanf()よりもいい方法ないですかね?scanf()はあまりよくないみたいで。

むつ

Re:ファイルについて

#47

投稿記事 by むつ » 17年前

入力した内容を、直接ファイルに格納し、
なおかつ、no[/url]、name[/url]、point[/url]を以後使わないのであれば、
以下のようになると思います。
#include <stdio.h>
int main(void) {
	FILE *fp;
	char no[10];
	char name[20];
	char point[10];
	int i;
	fp = fopen("student.txt","w");
	if(fp == NULL) {
		printf("エラーです\n");
		return 1;
	}
	printf("FILE OPEN\n");
	for(i = 1; i <= 3; i++) {
		printf("%d人目の入力\n", i );
		scanf("%s", &no);
		scanf("%s", &name);
		scanf("%s", &point);
		//
		fprintf(fp,"%s\n",no );
		fprintf(fp,"%s\n",name );
		fprintf(fp,"%s\n",point);
	}
	fclose(fp);
	return 0;
}

miyaza

Re:ファイルについて

#48

投稿記事 by miyaza » 17年前

> コンソールから入力させるときはscanf()よりもいい方法ないですかね?scanf()はあまりよくないみたいで。
fgets()を使ってみたらどうでしょう。

fgets(no,sizeof(no),stdin);

こんな感じで

グー

Re:ファイルについて

#49

投稿記事 by グー » 17年前

fgets()って読み込むときじゃないんですか??
scanf()よりもメリットあるのでしょうか??というより、fgets()でもコンソールから入力させられるなんて!!

miyaza

Re:ファイルについて

#50

投稿記事 by miyaza » 17年前

> fgets()って読み込むときじゃないんですか??
読み込んでますよ。標準入力から、だからfgets()の第三引数をstdinとしています。

グー

Re:ファイルについて

#51

投稿記事 by グー » 17年前

なるほど!確かに読み込んでいますよね。標準入力から。説得力ありますよ。

fgets()で読み込むメリットってなんすかね?質問ばかりですみません。

miyaza

Re:ファイルについて

#52

投稿記事 by miyaza » 17年前

> fgets()で読み込むメリットってなんすかね?質問ばかりですみません。
一行だけ読み取れます。スペースも読み取れる。メリットというかscanf()との違いですが。

逆に聞きますがなんでscanf()よくないんでしょうか?

グー

Re:ファイルについて

#53

投稿記事 by グー » 17年前

一度目はしっかりと読み込めたのですが、2回目3回目読み込むと、数字がめちゃくちゃになっているのですが、どういうことでしょうか?
#include <stdio.h>

int main(void) {
	FILE *fp;
	char no[3][10];
	char name[3][20];
	char point[3][10];
	int i;
	int val;
	int sum;

	fp = fopen("student.txt","r");
	if(fp == NULL) {
		printf("エラーです\n");
		return 1;
	}
	printf("FILE OPEN\n");
/*
	//書き込み用
	for(i = 0; i < 3; i++) {
		printf("%d人目の入力\n",i + 1);
		scanf("%s",&no);
		scanf("%s",&name);
		scanf("%s",&point);
	}
	for(i =0; i < 3; i++) {
		
		fprintf(fp,"%s\n",no);
		fprintf(fp,"%s\n",name);
		fprintf(fp,"%s\n",point);
	
	}
*/
	//読み込み用
	sum = 0;
	for(i = 0; i < 3; i++) {
		fgets(no,10,fp);
		fgets(name,20,fp);
		fgets(point,10,fp);
		//sscanf(point,"%d",&val);
		//sum = sum + val;
		
	}
	for(i = 0; i < 3; i++) {
	printf("%s\n",no[i]);
	printf("%s\n",name[i]);
	printf("%d\n",&point[i]);
	}
	printf("合計%d",sum);
	fclose(fp);
	return 0;
}

むつ

Re:ファイルについて

#54

投稿記事 by むつ » 17年前

今、入力した内容を直接ファイルに書き込んでいるので
書き込みの方で、for文を2つに分ける必要がありません。

以下に示したように、1つのfor文で処理してはいかがでしょう。

また、書き込みの方で、入力内容は一時的に格納するだけですので、
no[/url]、name[/url]、point[/url]に格納する必要は無いですよ。

もう1つchar buf[ 256 ];というのを用意して、
以下のようにしてみてください。
for( i = 1; i < 3; i++ ) {
	printf( "%d人目の入力\n",i );
	scanf( "%s", &buf );
	fprintf( fp, "%s\n", buf );
	scanf( "%s", &buf );
	fprintf( fp, "%s\n", buf );
	scanf( "%s", &buf );
	fprintf( fp, "%s\n", buf );
}
そして、読み込み側ですが、fclose()によって、ファイルの書き込みが実行されます。
fclose()する前に、fpからfget()しても、入力した内容は取得できないのではないでしょうか。

ファイルが変更された後の、最新情報を取得したいのであれば、
書き込み側のfpをfclose()した後に続いて、読み込み用にfopen()してください。

miyaza

Re:ファイルについて

#55

投稿記事 by miyaza » 17年前

> 一度目はしっかりと読み込めたのですが、2回目3回目読み込むと、数字がめちゃくちゃになっているのですが、どういうことでしょうか?

printf("%d\n",&point);
これではアドレスを渡していることになります。
printf("%s\n",point);
とすればだいじょうぶです。

グー

Re:ファイルについて

#56

投稿記事 by グー » 17年前

miyazaさんへ
>逆に聞きますがなんでscanf()よくないんでしょうか?
 私はまだまだ初心者なので分かりませんが、あまり使わないほうがいいみたいです。理由はよくわからないの です。。

むつさんへ
たしかにそのやり方のほうがいいかもしれませんね!手間が省けますからね。

グー

Re:ファイルについて

#57

投稿記事 by グー » 17年前

miyazaさんありがとうございます。できました。

グー

Re:ファイルについて

#58

投稿記事 by グー » 17年前

pointを文字列として読み込んだあとに数値に変換して合計を求めたいのですが、何か方法ありますかね?
なかなかうまくいかなくて困ってます。

miyaza

Re:ファイルについて

#59

投稿記事 by miyaza » 17年前

先ほどグーさんが書かれたソースの下の部分コメントアウトをはずしたら問題なくできましたが。

//sscanf(point,"%d",&val);
//sum = sum + val;

グー

Re:ファイルについて

#60

投稿記事 by グー » 17年前

そうですか。できましたか。なぜかわたしのはできない。もう一度試してみます!

グー

Re:ファイルについて

#61

投稿記事 by グー » 17年前

合計がやっぱり違う・・・・

box

Re:ファイルについて

#62

投稿記事 by box » 17年前

> 合計がやっぱり違う・・・・

案に相違してうまくいかない場合は、
とにかくそのソースを提示するのが得策でありましょう。

「このソースを書いてみたのですが、合計がやっぱり違います」
という風にすれば、本来は不要な発言のキャッチボールをしなくてすみます。

バグ

Re:ファイルについて

#63

投稿記事 by バグ » 17年前

合計が違うのであれば、『計算部分』か『データの代入部分』のどちらかに間違いがあるのでしょう。

グー

Re:ファイルについて

#64

投稿記事 by グー » 17年前

#include <stdio.h>

int main(void) {
	FILE *fp;
	char no[3][10];
	char name[3][20];
	char point[3][10];
	char buf[256];
	int i;
	int val;
	int sum;

	fp = fopen("student.txt","r");
	if(fp == NULL) {
		printf("エラーです\n");
		return 1;
	}
	printf("FILE OPEN\n");

	

	
	sum = 0;
	for(i = 0; i < 3; i++) {
		fgets(no,10,fp);
		fgets(name,20,fp);
		fgets(point,10,fp);
		scanf(point,"%d",&val);
		sum = sum + val;
		
	}
	for(i = 0; i < 3; i++) {
	printf("%s\n",no);
	printf("%s\n",name);
	printf("%s\n",point);
	}

	printf("合計%d",sum);
	fclose(fp);
	return 0;
}

テキストファイルを文字列で読み込み、pointだけ数値に変換してpointの合計を出力しようとしたものです。

miyaza

Re:ファイルについて

#65

投稿記事 by miyaza » 17年前

scanf(point,"%d",&val);
ではなく
sscanf(point,"%d",&val);
としてください
sが一個たりませんでしたね。

管理人

Re:ファイルについて

#66

投稿記事 by 管理人 » 17年前

似たような名前でも1文字でも名前が違えば関数の仕様がかわるので注意してください。
詳しい仕様が分かりやすい書いてあるサイトとしてこの辺がお勧めです。

sscanf
http://www9.plala.or.jp/sgwr-t/lib/sscanf.html

scanf
http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-3

グー

Re:ファイルについて

#67

投稿記事 by グー » 17年前

miyazaさん了解です!
管理人さんありがとうございます!<!--12-->

グー

Re:ファイルについて

#68

投稿記事 by グー » 17年前

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

int main(void) {
	FILE *fp;
	char no[NUM][10];
	char name[NUM][20];
	char point[NUM][10];
	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",&no);
		fprintf(fp,"NO:%s\n",no);
		printf("NAME>>>");
		scanf("%s",&name);
		fprintf(fp,"%s\n",name);
		printf("POINT>>>");
		scanf("%s",point);
		fprintf(fp,"%s\n",point);
	}

	fclose(fp);
	return 0;
}
//書き込みコード

#include <stdio.h>
#define NUM 2

int main(void) {
	FILE *fp;
	char no[NUM][10];
	char name[NUM][20];
	char point[NUM][10];
	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",&no);
		fprintf(fp,"NO:%s\n",no);
		printf("NAME>>>");
		scanf("%s",&name);
		fprintf(fp,"%s\n",name);
		printf("POINT>>>");
		scanf("%s",point);
		fprintf(fp,"%s\n",point);
	}

	fclose(fp);
	return 0;
}

もっとこうしたほうがのでは?と思うところご指摘下さい

グー

Re:ファイルについて

#69

投稿記事 by グー » 17年前

#include <stdio.h>
#define NUM 2

int main(void) {
	FILE *fp;
	char no[NUM][10];
	char name[NUM][20];
	char point[NUM][10];
	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",&no);
		fprintf(fp,"NO:%s\n",no);
		printf("NAME>>>");
		scanf("%s",&name);
		fprintf(fp,"%s\n",name);
		printf("POINT>>>");
		scanf("%s",point);
		fprintf(fp,"%s\n",point);
		
	}

	fclose(fp);
	return 0;
}
#include <stdio.h>
#define NUM 2

int main(void) {
	FILE *fp;
	char no[NUM][10];
	char name[NUM][20];
	char point[NUM][10];
	int i;
	int val;
	int sum;
	
	fp = fopen("student.txt","r");
	if(fp == NULL) {
		return 1;
	}

	printf("FILE OPEN\n");
	sum = 0;

	for(i = 0; i < NUM; i++) {
		printf("%d人目\n",i + 1);
		fgets(no,10,fp);
		printf("%s\n",no);
		fgets(name,20,fp);
		printf("%s\n",name);
		fgets(point,10,fp);
		printf("%s\n",point);
		sscanf(point,"%d",&val);
		sum = sum + val;

	}
	printf("合計>>%d",sum);

	fclose(fp);
	return 0;
}

sscanf(point,"%d",&val);のvalの前に&がある理由って?

fgets(point,10,fp);
printf("%s\n",point);
sscanf(point,"%d",&val);
一度、pointに読み込んだものが格納されて、printfのpointで出力されているのは分かるのですが、sscanf
では、どのような処理がされているのでしょうか?&valで読み込んだものが、pointに格納され、sum = sum + valがされるのでしょうか?

miyaza

Re:ファイルについて

#70

投稿記事 by miyaza » 17年前

> sscanf(point,"%d",&val);のvalの前に&がある理由って?
valのアドレスを渡しているからです。

sscanf()は指定された文字列から指定された書式フォーマットにしたがって変換されたデータを指定されたアドレスに格納します。

sscanf(point,"%d",&val);
今回pointの中にはfgets(point,10,fp);で取り込んだ文字列が入っています。その中から整数を変数valに格納しています。
つまり文字列の中から数値を取り出しています。

グー

Re:ファイルについて

#71

投稿記事 by グー » 17年前

miyazaさんへ
ありがとうございます。

閉鎖

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