ページ 1 / 1
宿題です(汗)
Posted: 2007年7月16日(月) 17:49
by 羽流布
<問題>
一万個の乱数を格納したファイル(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
Re:宿題です(汗)
Posted: 2007年7月16日(月) 20:56
by Hermit
ifp += 2;
普通、ファイルポインタは変えない物ですが。
で、何をやりたいのかさっぱりわからないソースですね。
どこをどう勘違いしているのかも・・・
とりあえず、
100段階のどこに分類されるかを調べ,各段階の出現回数を数え,それの個数だけでも表示できますか?
Re:宿題です(汗)
Posted: 2007年7月16日(月) 21:47
by 羽流布
>普通、ファイルポインタは変えない物ですが。
最初の2行を読み飛ばせると思ってやったのですが出来ませんね……。
と言いますか、ファイル変数の扱いが分かりません。
よって個数を表示できなくて困っております○TZ
Re:宿題です(汗)
Posted: 2007年7月16日(月) 22:09
by Hermit
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:宿題です(汗)
Posted: 2007年7月16日(月) 22:21
by 羽流布
なんとか出来ました……。
#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
Re:宿題です(汗)
Posted: 2007年7月16日(月) 22:50
by Hermit
多分間違ってます。
Re:宿題です(汗)
Posted: 2007年7月16日(月) 23:33
by 羽流布
え? そうなんですか!?
結果はそれらしいのですが……。
段階 出現個数
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
Re:宿題です(汗)
Posted: 2007年7月16日(月) 23:49
by Hermit
ああ、結果はいいんですね。
失礼しました。
ただ、その為に、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]);
}
こんな感じでいいような気がします。
(エラー処理はしてませんが)
Re:宿題です(汗)
Posted: 2007年7月16日(月) 23:54
by 初心者A
見事なリソースの無駄使いです。
ほぼ均一に分布していると考えた場合、
ファイルからのデータを99%読み飛ばし、
1%ずつ格納する処理を100回繰り返し、
最終的にファイルのデータを100%格納しています。
1回のファイルopenとcloseで処理できますので、
頑張ってみて下さい。
Re:宿題です(汗)
Posted: 2007年7月16日(月) 23:58
by 羽流布
確かにファイルを百回もオープンするのは無駄ですね。
気付きませんでした……。
ありがとうございます!
Re:宿題です(汗)
Posted: 2007年7月17日(火) 00:19
by 羽流布
すいません(汗)
またまた助言お願いします。
下記のプログラムは何か間違っているのでしょうか?
結果は、
ファイル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:宿題です(汗)
Posted: 2007年7月17日(火) 01:31
by フリオ
最初の質問ですが、
> 統計量 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:宿題です(汗)
Posted: 2007年7月17日(火) 01:41
by フリオ
最初の質問の方、なんか、面倒くさい事してました。
"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:宿題です(汗)
Posted: 2007年7月17日(火) 01:56
by 羽流布
すいません、説明不足でした(汗) Aはf1.dat、Bはf2.dat、Cはf3.datです。 AとBの値を比べて小さいほうから順次並べたものがCです。 現在のプログラムですと、Cへ限りなく書き込んでしまうようなのです。
Re:宿題です(汗)
Posted: 2007年7月17日(火) 05:11
by 初心者A
最初のネタの続きです。
今のままでは不正データで誤動作するのと、
区切文字の汎用性がないので、
フリオさんご提示のロジックを少々アレンジしてみました。
尚、必然性のない書き換えは関心しないですね。>羽流布さん
#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:宿題です(汗)
Posted: 2007年7月17日(火) 06:09
by フリオ
あとの質問に関して、
こちらで試したところ、"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:宿題です(汗)
Posted: 2007年7月17日(火) 09:01
by 羽流布
すいません、2行を飛ばす必要があったようです。
でも、あとは何とかなりそうです。
助言ありがとうございましたm(_ _)m
構造体をchar型の変数へ格納
Posted: 2007年8月27日(月) 00:17
by Chii☆
いつもお世話になってぃます!!
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を使用しています!!
宜しくお願ぃします。
Re:構造体をchar型の変数へ格納
Posted: 2007年8月27日(月) 01:33
by Blue
示されたコードはコンパイルがまったく通らないようですが。。。
(イメージならイメージですと明記しておいたほうが良いでしょう)
数値なのか文字列として格納したいのかどちらなんでしょうか?
空白を消してから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見たいに一気に格納は無理でしょう)
Re:構造体をchar型の変数へ格納
Posted: 2007年8月27日(月) 10:56
by Chii☆
Blueさん解答ありがとうござます!!
>示されたコードはコンパイルがまったく通らないようですが。。。
>(イメージならイメージですと明記しておいたほうが良いでしょう)
申し訳ありません。イメージでした・・
>数値なのか文字列として格納したいのかどちらなんでしょうか?
>空白を消してからmemcpyすればとりあえず(終端文字を含まない)文字列としては
>格納できますが。
>もっとも数値に最終的に変換する場合でも終端文字は必要になりますが。
数値ではなくて文字列として格納したいです・・
説明不足で申し訳ありませんでした!!!
よろしくお願ぃします!!!
Re:構造体をchar型の変数へ格納
Posted: 2007年8月27日(月) 11:18
by Blue
終端文字を含まないといけないので、
(なくてもできるけど、普通の文字列と同等には扱えない。
→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;
}
Re:構造体をchar型の変数へ格納
Posted: 2007年8月27日(月) 14:28
by Chii☆
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
・
・
・
と記述しなくていいので簡単に書くことができると思うのですが、
なかなか良い方法が思い浮かびません・・
私が今書いたソースと全く違うものでもいいので、ご教授願います。
質問の仕方が悪くて申し訳ありませんでした!!
Re:構造体をchar型の変数へ格納
Posted: 2007年8月27日(月) 14:37
by Blue
#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;
}
Re:構造体をchar型の変数へ格納
Posted: 2007年9月01日(土) 23:02
by Chii☆
お礼の返事送れて申し訳ありません!!
おけげ様で無事プログラムが完成できました☆
丁寧な解説、ありがとうございました!!
とても感謝致します。
また何かありましたらよろしくお願いします!!
それでは短いですがお礼とさせて頂きます。