宿題です(汗)

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

宿題です(汗)

#1

投稿記事 by 羽流布 » 18年前

<問題>
一万個の乱数を格納したファイル(RANDF.DAT)を入力データとし,次の仕様を満たすプログラムを作成せよ.

・最初の2行(特性の記録行)を読み飛ばす.
・1万個の乱数データを順次入力して,各々の値が0-9,10-19,・・・,980-989,990-999の100段階のどこに分類されるかを調べ,各段階の出現回数を数え,出現表(度数分布表)を出力する.
・上の表の各データから,統計量を計算する.

現在、以下の状況で行き詰まってます。
#include <stdio.h>
#include <stdlib.h>

int main(void) {
	FILE *ifp;
	int n[100] = {0}, j, x;
	double a = 0;
	
	if ((ifp = fopen("RANDF.DAT", "r")) == NULL) {
		printf("ファイル RANDF.DAT はオープンできない.\n");
		exit (1);
	}
	printf("段階    出現個数\n");
	for (j = 0; j < 100; j++) {
		printf("%3d-%3d", j * 10, j * 10 + 9);
		ifp += 2;
		while (fscanf(ifp, "%d", &x) != EOF) {
			if (j * 10 <= x && x <= j * 10 + 9) {
				n[j]++;
			}
		}
		printf("%13d\n", n[j]);
	}
	fclose(ifp);
	for (j = 0; j < 100; j++) {
		a += ((n[j] - 100) * (n[j] - 100)) / 100;
	}
	printf("統計量 x^2 = %.1f", a);
	return (0);
}
助言おねがいしますm(_ _)m

Hermit

Re:宿題です(汗)

#2

投稿記事 by Hermit » 18年前

ifp += 2;
普通、ファイルポインタは変えない物ですが。

で、何をやりたいのかさっぱりわからないソースですね。
どこをどう勘違いしているのかも・・・

とりあえず、
100段階のどこに分類されるかを調べ,各段階の出現回数を数え,それの個数だけでも表示できますか?

羽流布

Re:宿題です(汗)

#3

投稿記事 by 羽流布 » 18年前

>普通、ファイルポインタは変えない物ですが。
最初の2行を読み飛ばせると思ってやったのですが出来ませんね……。
と言いますか、ファイル変数の扱いが分かりません。
よって個数を表示できなくて困っております○TZ

Hermit

Re:宿題です(汗)

#4

投稿記事 by Hermit » 18年前

char buff[256]; // 256 はテキトウ、30 くらいでもいいかな
...............
	if ((ifp = fopen("RANDF.DAT", "r")) == NULL) {
		printf("ファイル RANDF.DAT はオープンできない.\n");
		exit (1);
	}
	fgets(buff,sizeof buff,ifp); // 単純に、1行読み捨てているだけ
	fgets(buff,sizeof buff,ifp); // 2行目読み捨て

羽流布

Re:宿題です(汗)

#5

投稿記事 by 羽流布 » 18年前

なんとか出来ました……。
#include <stdio.h>
#include <stdlib.h>

int main(void) {
	FILE *ifp;
	int n[100] = {0}, j, x;
	char buff[256];
	double a = 0;
	
	printf("段階    出現個数\n");
	for (j = 0; j < 100; j++) {
		if ((ifp = fopen("RANDF.DAT", "r")) == NULL) {
			printf("ファイル RANDF.DAT はオープンできない.\n");
			exit (1);
		}
		fgets(buff, sizeof buff, ifp);
		fgets(buff, sizeof buff, ifp);
		printf("%3d-%3d", j * 10, j * 10 + 9);
		while (fscanf(ifp, "%d", &x) != EOF) {
			if (j * 10 <= x && x <= j * 10 + 9) {
				n[j]++;
			}
		}
		fclose(ifp);
		printf("%13d\n", n[j]);
	}
	for (j = 0; j < 100; j++) {
		a += ((n[j] - 100) * (n[j] - 100)) / 100;
	}
	printf("統計量 x^2 = %.1f", a);
	return (0);
}
助言ありがとうございましたm(_ _)m

Hermit

Re:宿題です(汗)

#6

投稿記事 by Hermit » 18年前

多分間違ってます。

羽流布

Re:宿題です(汗)

#7

投稿記事 by 羽流布 » 18年前

え? そうなんですか!?
結果はそれらしいのですが……。
段階  出現個数
  0-  9       96
 10- 19      106
 20- 29      103
 30- 39      101
 40- 49      111
 50- 59      105
 60- 69       97
 70- 79      108
 80- 89       94
 90- 99      108
100-109      103
110-119       96
120-129      112
130-139      108
140-149       95
150-159       86
160-169      100
170-179      100
180-189       95
190-199      109
200-209       89
210-219       92
220-229      115
230-239       97
240-249      119
250-259       95
260-269      113
270-279       94
280-289       94
290-299       93
300-309       89
310-319      112
320-329      115
330-339       97
340-349       72
350-359       80
360-369      114
370-379      101
380-389       70
390-399       95
400-409      111
410-419      105
420-429       90
430-439       92
440-449      109
450-459      105
460-469       97
470-479       83
480-489      112
490-499      104
500-509       99
510-519      102
520-529      127
530-539      102
540-549       93
550-559       93
560-569      109
570-579      118
580-589       89
590-599       94
600-609      106
610-619      104
620-629      100
630-639      103
640-649       83
650-659       90
660-669      104
670-679      108
680-689      117
690-699       96
700-709       97
710-719       97
720-729       95
730-739      118
740-749       97
750-759      108
760-769       92
770-779       98
780-789       85
790-799      103
800-809       98
810-819      100
820-829      109
830-839      104
840-849       98
850-859       87
860-869       80
870-879      113
880-889       88
890-899      125
900-909       85
910-919       96
920-929      106
930-939       93
940-949       96
950-959       94
960-969       99
970-979      105
980-989       97
990-999      113
統計量 x^2 = 77.0

Hermit

Re:宿題です(汗)

#8

投稿記事 by Hermit » 18年前

ああ、結果はいいんですね。
失礼しました。

ただ、その為に、100回ファイルをオープンするのはどうかと思いますが。
if ((ifp = fopen("RANDF.DAT", "r")) == NULL) {
		printf("ファイル RANDF.DAT はオープンできない.\n");
		exit (1);
	}
	fgets(buff,sizeof buff,ifp);
	fgets(buff,sizeof buff,ifp);
	printf("段階    出現個数\n");
	while (fscanf(ifp, "%d", &x) != EOF) {
		n[x/10]++;
	}
	fclose(ifp);
	for (j = 0; j < 100; j++) {
		printf("%3d-%3d%13d\n",j*10,j*10+9,n[j]);
	}

こんな感じでいいような気がします。
(エラー処理はしてませんが)

初心者A

Re:宿題です(汗)

#9

投稿記事 by 初心者A » 18年前

見事なリソースの無駄使いです。

ほぼ均一に分布していると考えた場合、
ファイルからのデータを99%読み飛ばし、
1%ずつ格納する処理を100回繰り返し、
最終的にファイルのデータを100%格納しています。

1回のファイルopenとcloseで処理できますので、
頑張ってみて下さい。

羽流布

Re:宿題です(汗)

#10

投稿記事 by 羽流布 » 18年前

確かにファイルを百回もオープンするのは無駄ですね。
気付きませんでした……。

ありがとうございます!

羽流布

Re:宿題です(汗)

#11

投稿記事 by 羽流布 » 18年前

すいません(汗)
またまた助言お願いします。
下記のプログラムは何か間違っているのでしょうか?
結果は、
ファイルA:2 4 7 8 10 15
ファイルB:3 5 7 9 10 16 18
ファイルC:2 3 4 5 7 7 8 9 10 10 15 16 18
と表示させたいのです。
#include <stdio.h>
#include <stdlib.h>

int main(void) {
	FILE *fa, *fb, *fc;
	int a, b, c;
	
	if ((fa = fopen("f1.dat", "r")) == NULL) {
		printf("ファイル f1.dat はオープンできない.\n");
		exit (1);
	}
	if ((fb = fopen("f2.dat", "r")) == NULL) {
		printf("ファイル f2.dat はオープンできない.\n");
		exit (1);
	}
	fc = fopen("f3.dat", "w");
	for ( ; ; ) {
		if (fscanf(fa, "%d", &a) != EOF) {
			if (fscanf(fb, "%d", &b) != EOF) {
				if (a >= b) {
					fprintf(fc, " %2d", b);
					fprintf(fc, " %2d", a);
				}
				else {
					fprintf(fc, " %2d", a);
					fprintf(fc, " %2d", b);
				}
			}
			else {
				fprintf(fc, " %2d", a);
			}
		}
		else {
			if (fscanf(fb, "%d", &b) != EOF) {
				fprintf(fc, " %2d", b);
			}
			else {
				break;
			}
		}
	}
	fclose(fa);
	fclose(fb);
	fclose(fc);
	printf("ファイルA:");
	if ((fa = fopen("f1.dat", "r")) == NULL) {
		printf("ファイル f1.dat はオープンできない.\n");
		exit (1);
	}
	while (fscanf(fa, "%d", &a) != EOF) {
		printf(" %d", a);
	}
	printf("\n");
	fclose(fa);
	printf("ファイルB:");
	if ((fb = fopen("f2.dat", "r")) == NULL) {
		printf("ファイル f2.dat はオープンできない.\n");
		exit (1);
	}
	while (fscanf(fb, "%d", &b) != EOF) {
		printf(" %d", b);
	}
	printf("\n");
	fclose(fb);
	printf("ファイルC:");
	if ((fc = fopen("f3.dat", "r")) == NULL) {
		printf("ファイル f3.dat はオープンできない.\n");
		exit (1);
	}
	while (fscanf(fc, "%d", &c) != EOF) {
		printf(" %d", c);
	}
	printf("\n");
	fclose(fc);
	return (0);
}
朝10時までなら間に合いますので、助言お願いしますm(_ _)m

フリオ

Re:宿題です(汗)

#12

投稿記事 by フリオ » 18年前

 
 最初の質問ですが、

> 統計量 x^2 = 77.0

これ、間違ってませんか?
#include <stdio.h>

#define MAX 100
#define SKIP 2

int GetData(int *freq)
{
	FILE *fp = fopen("RANDF.DAT", "r");
	int num, i;
	
	if(!fp) return 0;
	for(i = 0; i < SKIP; i += (fgetc(fp) == '\n')) ;
	while(fscanf(fp, "%d ", &num) != EOF) freq[num / 10] ++;
	fclose(fp);
	return 1;
}

double Variance(int *freq, int max)
{
	int i;
	double v = 0;
	
	for(i = 0; i < max; i ++){
		v += (freq - 100) * (freq - 100) / 100.0;
	}
	return v;
}

void Print(double v, int *freq, int max)
{
	int i;
	
	for(i = 0; i < max; i ++){
		printf("%3d ~ %3d\t%5d\n", 10 * i, 10 * i + 9, freq);
	}
	printf("\nVariance : %.1f\n", v);
	return;
}

int main(void)
{ 
	int freq[MAX] = {0,};
	
	if(!GetData(freq)){
		puts("File Open Error");
		return 1;
	}
	Print(Variance(freq, MAX), freq, MAX);
	return 0;
}

 
 
 あとの質問ですが、
これは、何をするプログラムでしょうか。
"ファイルA"、"ファイルB"、"ファイルC"とは何でしょうか。
何故、"間違っている"と判断したのでしょうか。
 

フリオ

Re:宿題です(汗)

#13

投稿記事 by フリオ » 18年前

 
 最初の質問の方、なんか、面倒くさい事してました。
"Print"関数を以下に訂正します。
void Print(int *freq, int max)
{
	int i;
	
	for(i = 0; i < max; i ++){
		printf("%3d ~ %3d\t%5d\n", 10 * i, 10 * i + 9, freq);
	}
	printf("\nVariance : %.1f\n", Variance(freq, MAX));
	return;
}

 

羽流布

Re:宿題です(汗)

#14

投稿記事 by 羽流布 » 18年前

すいません、説明不足でした(汗)                    Aはf1.dat、Bはf2.dat、Cはf3.datです。                AとBの値を比べて小さいほうから順次並べたものがCです。                    現在のプログラムですと、Cへ限りなく書き込んでしまうようなのです。

初心者A

Re:宿題です(汗)

#15

投稿記事 by 初心者A » 18年前

最初のネタの続きです。

今のままでは不正データで誤動作するのと、
区切文字の汎用性がないので、
フリオさんご提示のロジックを少々アレンジしてみました。

尚、必然性のない書き換えは関心しないですね。>羽流布さん
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAX 100
#define SKIP 2
#define	NUM_MIN	"0"
#define	NUM_MAX	"999"

int GetData(int *freq, char **errmsg)
{
	FILE *fp = fopen("RANDF.DAT", "r");
	int num, i, ch;
	char buff[sizeof(NUM_MAX)] = "";
	const int num_min = atoi(NUM_MIN);
	const int num_max = atoi(NUM_MAX);

	if(!fp){
		*errmsg = "File Open Error";
		return 0;
	}
	for(i = 0; ch = fgetc(fp),i < SKIP && ch != EOF; i += (ch == '\n')) ;
	if(ch == EOF){
		fclose(fp);
		*errmsg = "Header Nothing Error";
		return 0;
	}
	for(num = 0;;){
		ch = fgetc(fp);
		if(ch <= ' ' || ch == ','){
			buff[num] = '\0';
			if(*buff){
				num = atoi(buff);
				if(num < num_min || num > num_max){
					fclose(fp);
					*errmsg = "Data Value Error";
					return 0;
				}
				freq[num / 10] ++;
			}
			if(ch == EOF) break;
			num = 0;
			continue;
		}
		if(!isdigit(ch)){
			fclose(fp);
			*errmsg = "Data Not Digit Error";
			return 0;
		}
		buff[num++] = (char)ch;
		if(num >= sizeof(buff)){
			fclose(fp);
			*errmsg = "Data Length Error";
			return 0;
		}
	}
	fclose(fp);
	return 1;
}

double Variance(int *freq, int max)
{
	int i;
	double v = 0;

	for(i = 0; i < max; i ++){
		v += (freq - 100) * (freq - 100) / 100.0;
	}
	return v;
}

void Print(double v, int *freq, int max)
{
	int i;

	for(i = 0; i < max; i ++){
		printf("%3d ~ %3d\t%5d\n", 10 * i, 10 * i + 9, freq);
	}
	printf("\nVariance : %.1f\n", v);
	return;
}

int main(void)
{ 
	int freq[MAX] = {0,};
	char *errmsg;

	if(!GetData(freq, &errmsg)){
		puts(errmsg);
		return 1;
	}
	Print(Variance(freq, MAX), freq, MAX);
	return 0;
}

フリオ

Re:宿題です(汗)

#16

投稿記事 by フリオ » 18年前

 
 あとの質問に関して、
 こちらで試したところ、"Cへ限りなく書き込んでしまう"ことはありませんが、
データが交互でない場合、例えば、

ファイルA : 1 2 3 7 8 9
ファイルB : 4 5 6 10 11 12

だとうまくいきません。

一応、私が考えたものを書いておきますが、
もっとすっきりした方法があるかも。
#include <stdio.h>

int main(void)
{
	FILE *fpa = fopen("f1.dat", "r"),
		*fpb = fopen("f2.dat", "r");
	int v_a, v_b, flag_a, flag_b;
	
	if(!(fpa && fpb)){
		puts("File Open Error");
		return 1;
	}
	flag_a = fscanf(fpa, "%d ", &v_a);
	flag_b = fscanf(fpb, "%d ", &v_b);
	while(flag_a != EOF && flag_b != EOF){
		if(v_a > v_b){
			printf("%d ", v_b);
			flag_b = fscanf(fpb, "%d ", &v_b);
		}
		else{
			printf("%d ", v_a);
			flag_a = fscanf(fpa, "%d ", &v_a);
		}
	}
	while(flag_a != EOF){
		printf("%d ", v_a);
		flag_a = fscanf(fpa, "%d ", &v_a);
	}
	while(flag_b != EOF){
		printf("%d ", v_b);
		flag_b = fscanf(fpb, "%d ", &v_b);
	}
	fclose(fpa);
	fclose(fpb);
	return 0;
}
 

羽流布

Re:宿題です(汗)

#17

投稿記事 by 羽流布 » 18年前

すいません、2行を飛ばす必要があったようです。
でも、あとは何とかなりそうです。

助言ありがとうございましたm(_ _)m

Chii☆

構造体をchar型の変数へ格納

#18

投稿記事 by Chii☆ » 18年前

いつもお世話になってぃます!!
Chii☆と申します!!!

質問お願いします☆
typedef struct a
{
	a[2];
	b[3];
	c[3];
	d[7];
	e[5];
	f[4];
	g[3];
}a;

void main()
{
	a st_a;
	char str[/url] = {2374858373848 3848 28482848 2};
}
構造体をchar型の変数へ格納(空白は飛ばして数字のみ格納)したぃのですが、

a[2]・・・23
b[3]・・・748
c[3]・・・583
  ・
  ・
  ・

というような具合に代入して行きたいのですが、
一つ一つ、

memcpy()などで

memcpy(st_a.a,・・・
memcpy(st_a.b,・・・
memcpy(st_a.c,・・・
  ・
  ・
  ・

というように代入していくと効率が悪いので、
効率良く代入していきたぃのですが、なかなかできません・・

どなたか、ご教授お願いします!!!

VC++ 6.0を使用しています!!

宜しくお願ぃします。

Blue

Re:構造体をchar型の変数へ格納

#19

投稿記事 by Blue » 18年前

示されたコードはコンパイルがまったく通らないようですが。。。
(イメージならイメージですと明記しておいたほうが良いでしょう)

数値なのか文字列として格納したいのかどちらなんでしょうか?
空白を消してからmemcpyすればとりあえず(終端文字を含まない)文字列としては
格納できますが。

もっとも数値に最終的に変換する場合でも終端文字は必要になりますが。


(数値を入れるとして)
>効率良く代入
memcpyではなく空白を消してsscanfぐらいでしょうか。
前メンバを書き出す必要はありますが。

MFCのCStringを使ってもいいなら
#include <afx.h>

struct Hoge
{
    int a, b, c, d, e, f, g;
};

int main()
{
    Hoge h;
    char str[/url] = "2374858373848 3848 28482848 2";
    CString buff(str);

    buff.Replace(" ", "");

    sscanf(buff, "%2d%3d%3d%7d%5d%4d%3d", &h.a, &h.b, &h.c, &h.d, &h.e, &h.f, &h.g);

    printf("%s\n", buff);
    printf("h.a = %d\n", h.a);
    printf("h.b = %d\n", h.b);
    printf("h.c = %d\n", h.c);
    printf("h.d = %d\n", h.d);
    printf("h.e = %d\n", h.e);
    printf("h.f = %d\n", h.f);
    printf("h.g = %d\n", h.g);

    return 0;
}
てな感じで。
(memcpy見たいに一気に格納は無理でしょう)

Chii☆

Re:構造体をchar型の変数へ格納

#20

投稿記事 by Chii☆ » 18年前

Blueさん解答ありがとうござます!!


>示されたコードはコンパイルがまったく通らないようですが。。。
>(イメージならイメージですと明記しておいたほうが良いでしょう)

申し訳ありません。イメージでした・・


>数値なのか文字列として格納したいのかどちらなんでしょうか?
>空白を消してからmemcpyすればとりあえず(終端文字を含まない)文字列としては
>格納できますが。

>もっとも数値に最終的に変換する場合でも終端文字は必要になりますが。


数値ではなくて文字列として格納したいです・・


説明不足で申し訳ありませんでした!!!

よろしくお願ぃします!!!

Blue

Re:構造体をchar型の変数へ格納

#21

投稿記事 by Blue » 18年前

終端文字を含まないといけないので、
(なくてもできるけど、普通の文字列と同等には扱えない。
→printf("%s", a.h);とかatoi(a.h)とか出来ない)
>char str[/url] = "2374858373848 3848 28482848 2";
というバイナリの適所に'\0'を入れないとmemcpyで一気には無理でしょう。

それか、sscanfを使って
#include <afx.h>

struct Hoge
{
    char a[2 + 1];
    char b[3 + 1];
    char c[3 + 1];
    char d[7 + 1];
    char e[5 + 1];
    char f[4 + 1];
    char g[3 + 1];
};

int main()
{
    Hoge h;
    char str[/url] = "2374858373848 3848 28482848 2";
    CString buff(str);

    buff.Replace(" ", "");

    sscanf(buff, "%2s%3s%3s%7s%5s%4s%3s", h.a, h.b, h.c, h.d, h.e, h.f, h.g);

    printf("%s\n", buff);
    printf("h.a = %s\n", h.a);
    printf("h.b = %s\n", h.b);
    printf("h.c = %s\n", h.c);
    printf("h.d = %s\n", h.d);
    printf("h.e = %s\n", h.e);
    printf("h.f = %s\n", h.f);
    printf("h.g = %s\n", h.g);

    return 0;
}

Chii☆

Re:構造体をchar型の変数へ格納

#22

投稿記事 by Chii☆ » 18年前

Bleuさん
解答ありがとうござぃます。

>終端文字を含まないといけないので、
>(なくてもできるけど、普通の文字列と同等には扱えない。
>→printf("%s", a.h);とかatoi(a.h)とか出来ない)
>>char str[/url] = "2374858373848 3848 28482848 2";
>というバイナリの適所に'\0'を入れないとmemcpyで一気には無理でしょう。

では、一つ一つに終端文字を入れる必要があるようですね。


すいません、私の質問の仕方が悪かったみたぃで・・

質問の意味としては、構造体に格納する際に、

st_a.a
st_a.b
st_a.c

などをいちいち書いていたら日が暮れてしまうので、

下のソースのような(コンパイルはしておらず、あくまでイメージです!!)
typedef struct a
{
	a[2];
	b[3];
	c[3];
	d[7];
	e[5];
	f[4];
	g[3];
}a;

void main()
{
	a st_a;
	char str[/url] = {2374858373848 3848 28482848 2};
        int num [/url] = {2,3,3,7,5,4,3}//格配列の要素数をループなどで回す時に使用
          
        int n=0;
     for(int i=0; int =<7 ;i++)
        {
            memcpy((a+Loop+n), (str+num+n), num[i+1]);
            printf(格納した文字列を表示)
        }
}


memcpy((&stBase+Loop+Num), (ss+Loop+Num), Loop[i+1]);

&stBase+Loop+Num

ように書くことができれば、

st_a.a
st_a.b
st_a.c
 ・
 ・
 ・

と記述しなくていいので簡単に書くことができると思うのですが、
なかなか良い方法が思い浮かびません・・

私が今書いたソースと全く違うものでもいいので、ご教授願います。

質問の仕方が悪くて申し訳ありませんでした!!

Blue

Re:構造体をchar型の変数へ格納

#23

投稿記事 by Blue » 18年前

#include <afx.h>

struct Hoge
{
    char a[2 + 1];
    char b[3 + 1];
    char c[3 + 1];
    char d[7 + 1];
    char e[5 + 1];
    char f[4 + 1];
    char g[3 + 1];
};

int main()
{
    Hoge h;
    char str[/url] = "2374858373848 3848 28482848 2";
    CString buff(str);

    buff.Replace(" ", "");

    const int sizes[/url] = 
    {
        sizeof(h.a) - 1,
        sizeof(h.b) - 1,
        sizeof(h.c) - 1,
        sizeof(h.d) - 1,
        sizeof(h.e) - 1,
        sizeof(h.f) - 1,
        sizeof(h.g) - 1
    };
    const char* p = buff;
    char* target = (char*)&h;
    for (int i = 0; i < sizeof(sizes) / sizeof(sizes[0]); ++i)
    {
        memcpy(target, p, sizes);
        target[sizes] = '\0';

        printf("%s\n", target);

        p += sizes;
        target += sizes;
    }
    
    return 0;
}

Chii☆

Re:構造体をchar型の変数へ格納

#24

投稿記事 by Chii☆ » 18年前

お礼の返事送れて申し訳ありません!!

おけげ様で無事プログラムが完成できました☆
丁寧な解説、ありがとうございました!!
とても感謝致します。

また何かありましたらよろしくお願いします!!

それでは短いですがお礼とさせて頂きます。

閉鎖

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