ページ 1 / 1
学校の課題2
Posted: 2021年7月10日(土) 02:01
by 学校でやらされている初心者
学校の課題です。
課題は「構造体を使って生徒番号、名前のイニシャル、身長、体重を表示させよ。ただし、ファイルからデータを読み込むこと。」です。
以下のように途中まで自分でやってみましたが、どのようにファイルからイニシャルだけを取り出して表示や、身長だけを取り出し表示するのかわかりません。
コード:
#include <stdio.h>
struct anthrop {
int id;
char initial[3];
double height;
double weight;
};
int main(void) {
struct anthrop bodydata[10];
FILE* fp;
int num;
fp = fopen("bodydata.dat", "r");
fscanf(fp,"id:%f,name:")
}
また使用するファイルは以下の通りです。
コード:
3
101
RH
168.5
58.8
102
SN
174.2
65.3
103
SM
176.4
62.5
よろしくお願いいたします。
Re: 学校の課題2
Posted: 2021年7月10日(土) 03:02
by box
きたないコードですが…
コード:
#include <stdio.h>
#include <stdlib.h>
typedef struct anthrop {
int id;
char initial[3];
double height;
double weight;
} anthrop;
int main(void) {
anthrop bodydata[10];
FILE* fp;
int num, i;
fp = fopen("bodydata.dat", "r");
if (!fp) {
fprintf(stderr, "read file error!\n");
exit(1);
}
fscanf(fp, "%d", &num);
for (i = 0; i < num; i++) {
fscanf(fp, "%d", &(bodydata[i].id));
fscanf(fp, "%s", bodydata[i].initial);
fscanf(fp, "%lf", &(bodydata[i].height));
fscanf(fp, "%lf", &(bodydata[i].weight));
}
fclose(fp);
for (i = 0; i < num ; i++) {
printf("%d人目\n", i + 1);
printf("id:%d\n", bodydata[i].id);
printf("initial:%s\n", bodydata[i].initial);
printf("height:%f\n", bodydata[i].height);
printf("weight:%f\n", bodydata[i].weight);
}
}
Re: 学校の課題2
Posted: 2021年7月10日(土) 20:33
by box
さすがにmain()に何でもかんでもやらせるのはちょっとアレなので...
コード:
#include <stdio.h>
#include <stdlib.h>
typedef struct anthrop {
int id;
char initial[3];
double height;
double weight;
} anthrop;
void openFile(FILE **fp)
{
*fp = fopen("bodydata.dat", "r");
if (!*fp) {
fprintf(stderr, "read file error!\n");
exit(1);
}
}
int inputData(anthrop *d)
{
FILE *fp;
int n, i;
openFile(&fp);
fscanf(fp, "%d", &n);
for (i = 0; i < n; i++) {
fscanf(fp, "%d", &(d[i].id));
fscanf(fp, "%s", d[i].initial);
fscanf(fp, "%lf", &(d[i].height));
fscanf(fp, "%lf", &(d[i].weight));
}
fclose(fp);
return n;
}
void outputData(anthrop *d, int n)
{
int i;
for (i = 0; i < n ; i++) {
printf("%d人目\n", i + 1);
printf("id:%d\n", d[i].id);
printf("initial:%s\n", d[i].initial);
printf("height:%f\n", d[i].height);
printf("weight:%f\n", d[i].weight);
}
}
int main(void) {
anthrop bodydata[10];
outputData(bodydata, inputData(bodydata));
}
Re: 学校の課題2
Posted: 2021年7月11日(日) 14:37
by 学校でやらされている初心者
box さんが書きました: ↑2年前
きたないコードですが…
ありがとうございます。
main関数のみのほうでやってみたのですがエラーが出てしまいました。
(どちらも17行目のfp=fopen_sのところです。)
コードC2198 "fopen_s:呼び出しに対する引数が少なすぎます。
コードE0165 関数呼び出しの引数が少なすぎます。
具体的な対処法を教えていただけると助かります。
コード:
#include <stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
typedef struct anthrop {
int id;
char initial[3];
double height;
double weight;
} anthrop;
int main(void) {
anthrop bodydata[10];
FILE* fp;
int num, i;
fp = fopen_s("bodydata.dat", "r");
if (!fp) {
fprintf(stderr, "read file error!\n");
exit(1);
}
fscanf_s(fp, "%d", &num);
for (i = 0; i < num; i++) {
fscanf_s(fp, "%d", &(bodydata[i].id));
fscanf_s(fp, "%s", bodydata[i].initial);
fscanf_s(fp, "%lf", &(bodydata[i].height));
fscanf_s(fp, "%lf", &(bodydata[i].weight));
}
fclose(fp);
for (i = 0; i < num; i++) {
printf("%d人目\n", i + 1);
printf("id:%d\n", bodydata[i].id);
printf("initial:%s\n", bodydata[i].initial);
printf("height:%f\n", bodydata[i].height);
printf("weight:%f\n", bodydata[i].weight);
}
}
Re: 学校の課題2
Posted: 2021年7月11日(日) 18:43
by box
https://qiita.com/softnakikaiya/items/d ... 913e1038a1
に、fopen_sをfopenのかわりに使うときのやり方がかいてあります。
その他、
fopen_s 使い方
あたりのキーワードでググってみると、いろんなことがわかると思います。
p.s.
fopen_sって、確かマイクロソフト社の処理系の独自関数だったような気が...。
Re: 学校の課題2
Posted: 2021年7月13日(火) 01:28
by 学校でやらされている初心者
サイトを参考にしてみたところ、エラーはなくなりました。
ありがとうございます。
エラーなく実行できたのですが、実行結果が下のようになってしまいます。
解決方法を具体的に教えていただきたいです。
コード:
#include <stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
typedef struct anthrop {
int id;
char initial[3];
double height;
double weight;
} anthrop;
int main(void) {
anthrop bodydata[10];
FILE* fp;
int num, i;
fp = fopen_s(&fp,"bodydata.dat", "r");
if (fp != 0) {
fprintf(stderr, "read file error\n");
exit(1);
}
fscanf_s(fp, "%d", &num);
for (i = 0; i < num; i++) {
fscanf_s(fp, "%d", &(bodydata[i].id));
fscanf_s(fp, "%s", bodydata[i].initial);
fscanf_s(fp, "%lf", &(bodydata[i].height));
fscanf_s(fp, "%lf", &(bodydata[i].weight));
}
fclose(fp);
for (i = 0; i < num; i++) {
printf("%d人目\n", i + 1);
printf("id:%d\n", bodydata[i].id);
printf("initial:%s\n", bodydata[i].initial);
printf("height:%f\n", bodydata[i].height);
printf("weight:%f\n", bodydata[i].weight);
}
}
Re: 学校の課題2
Posted: 2021年7月13日(火) 03:20
by box
read file error
開発環境によって、読み込み用のファイルの置き場所が異なるようです。
ソースファイルと同じ場所でなければなかったり、
実行ファイルと同じ場所でなければなかったりするみたいです。
読み込みファイルの置き場所を変えてみてください。
Re: 学校の課題2
Posted: 2021年7月14日(水) 12:52
by 学校でやらされている初心者
box さんが書きました: ↑2年前
読み込みファイルの置き場所を変えてみてください。
ありがとうございます。
ファイルの場所を変えてみたところ、上記のエラーはなくなりましたが、下記のようにエラーが出てしまいます。
具体的な対処方法を教えていただけると助かります。
コード:
Debug Assertion Failed!
Program:...neDrive F1X¥Visual Studio #
¥~~~.exe
File: minkernel crts\ucrt\src\appcrt\stdio input.cpp Line: 32
Expression: stream != nullptr
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
Re: 学校の課題2
Posted: 2021年7月14日(水) 19:17
by みけCAT
学校でやらされている初心者 さんが書きました: ↑2年前
コード:
fp = fopen_s(&fp,"bodydata.dat", "r");
if (fp != 0) {
fprintf(stderr, "read file error\n");
exit(1);
}
この部分が間違っています。
fopen_s関数は、正常終了した場合は0、失敗した場合はエラーコードを返します。
この返り値をfpに代入してしまうと、せっかく書き込んでくれたファイルポインタを消すことになってしまいます。
コード:
if (fopen_s(&fp,"bodydata.dat", "r") != 0) {
fprintf(stderr, "read file error\n");
exit(1);
}
とすると改善するでしょう。
Re: 学校の課題2
Posted: 2021年7月14日(水) 21:42
by 学校でやらされている初心者
この部分が間違っています。
ありがとうございます。
上記のエラーはなくなり、実行結果も表示されるようになりましたが、大体の値がファイルの値と異なってしまいます。
具体的な解決方法を教えていただけると助かります。
実行結果
コード:
1人目
id:101
initial:
フフフフフフフフフフフフフフフフフフフフフフフRフフフフフフフフフフフフフフフフフフフフフフフHフフフ
height:-92559631349317830736831783200707727132248687965119994463780864.000000
weight:-92559631349317830736831783200707727132248687965119994463780864.000000
2人目
id:-858993460
initial:RフフフフフフフフフフフフフフフフフフフフフフフHフフフ
height:-92559631349317830736831783200707727132248687965119994463780864.000000
weight:-92559631349317830736831783200707727132248687965119994463780864.000000
3人目
id:-858993460
initial:Hフフフ
height:168.500000
weight:58.800000
ファイルの値
コード:
3
101
RH
168.5
58.8
102
SN
174.2
65.3
103
SM
176.4
62.5
プログラム
コード:
#include <stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
typedef struct anthrop {
int id;
char initial[3];
double height;
double weight;
} anthrop;
int main(void) {
anthrop bodydata[10];
FILE* fp;
int num, i;
if (fopen_s(&fp, "bodydata.dat", "r") != 0) {
fprintf(stderr, "read file error\n");
exit(1);
}
fscanf_s(fp, "%d", &num);
for (i = 0; i < num; i++) {
fscanf_s(fp, "%d", &(bodydata[i].id));
fscanf_s(fp, "%c", &(bodydata[i].initial));
fscanf_s(fp, "%lf", &(bodydata[i].height));
fscanf_s(fp, "%lf", &(bodydata[i].weight));
}
fclose(fp);
for (i = 0; i < num; i++) {
printf("%d人目\n", i + 1);
printf("id:%d\n", bodydata[i].id);
printf("initial:%s\n", bodydata[i].initial);
printf("height:%f\n", bodydata[i].height);
printf("weight:%f\n", bodydata[i].weight);
}
}
Re: 学校の課題2
Posted: 2021年7月14日(水) 23:34
by みけCAT
%c 指定子は、1文字(もしくは文字数を指定した場合、指定された数の文字)を読み込むためのものです。
文字列を読み込むには、%s 指定子を使うといいでしょう。
また、
fscanf_関数で文字(%c)や文字列(%s)を読み込む際は、読み込み先の後にunsigned型で読み込み先のバッファサイズを指定しないといけません。
バッファオーバーフローを防ぐため、%s 指定子を使う際は読み込む最大バイト数を指定するべきです。
最大バイト数は、終端のナル文字の分を除くためバッファサイズ-1までにするべきです。
さらに、式中の配列は(sizeof演算子や単項&演算子に渡す場合などの例外を除いて)先頭要素へのポインタに変換されます。
%c指定子や%s指定子はchar*型のデータを要求するのに対し、&演算子を使ってしまうと違う型のデータを渡すことになってしまいます。
従って、&演算子を外すべきです。
まとめると、
コード:
fscanf_s(fp, "%c", &(bodydata[i].initial));
のかわりに
コード:
fscanf_s(fp, "%2s", (bodydata[i].initial), (unsigned)sizeof(bodydata[i].initial));
とすると良いでしょう。
それぞれのfscanf_s関数の戻り値を無視せず、ちゃんと読み込めたかのチェックをするようにするとさらに良いでしょう。
Re: 学校の課題2
Posted: 2021年7月15日(木) 01:16
by 学校でやらされている初心者
みけCAT さんが書きました: ↑2年前
まとめると、
コード:
fscanf_s(fp, "%c", &(bodydata[i].initial));
のかわりに
コード:
fscanf_s(fp, "%2s", (bodydata[i].initial), (unsigned)sizeof(bodydata[i].initial));
ありがとうございます。勉強になりました。
うまくプログラムが作動しました!
みなさん今回もありがとうございました。