学校の課題2

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

学校の課題2

#1

投稿記事 by 学校でやらされている初心者 » 2年前

学校の課題です。

課題は「構造体を使って生徒番号、名前のイニシャル、身長、体重を表示させよ。ただし、ファイルからデータを読み込むこと。」です。

以下のように途中まで自分でやってみましたが、どのようにファイルからイニシャルだけを取り出して表示や、身長だけを取り出し表示するのかわかりません。

コード:

#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

よろしくお願いいたします。

box
記事: 2002
登録日時: 13年前

Re: 学校の課題2

#2

投稿記事 by box » 2年前

きたないコードですが…

コード:

#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);
    }
}
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

box
記事: 2002
登録日時: 13年前

Re: 学校の課題2

#3

投稿記事 by box » 2年前

さすがに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

#4

投稿記事 by 学校でやらされている初心者 » 2年前

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);
    }

}

box
記事: 2002
登録日時: 13年前

Re: 学校の課題2

#5

投稿記事 by box » 2年前

https://qiita.com/softnakikaiya/items/d ... 913e1038a1
に、fopen_sをfopenのかわりに使うときのやり方がかいてあります。
その他、
fopen_s 使い方
あたりのキーワードでググってみると、いろんなことがわかると思います。

p.s.
fopen_sって、確かマイクロソフト社の処理系の独自関数だったような気が...。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

学校でやらされている初心者

Re: 学校の課題2

#6

投稿記事 by 学校でやらされている初心者 » 2年前

box さんが書きました:
2年前
https://qiita.com/softnakikaiya/items/d ... 913e1038a1
に、fopen_sをfopenのかわりに使うときのやり方がかいてあります。
その他、
fopen_s 使い方
あたりのキーワードでググってみると、いろんなことがわかると思います。
サイトを参考にしてみたところ、エラーはなくなりました。
ありがとうございます。

エラーなく実行できたのですが、実行結果が下のようになってしまいます。

コード:

read file error

解決方法を具体的に教えていただきたいです。

コード:

#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);
    }

}

box
記事: 2002
登録日時: 13年前

Re: 学校の課題2

#7

投稿記事 by box » 2年前

read file error
開発環境によって、読み込み用のファイルの置き場所が異なるようです。
ソースファイルと同じ場所でなければなかったり、
実行ファイルと同じ場所でなければなかったりするみたいです。
読み込みファイルの置き場所を変えてみてください。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

学校でやらされている初心者

Re: 学校の課題2

#8

投稿記事 by 学校でやらされている初心者 » 2年前

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)

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 学校の課題2

#9

投稿記事 by みけCAT » 2年前

学校でやらされている初心者 さんが書きました:
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);
    }
とすると改善するでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

学校でやらされている初心者

Re: 学校の課題2

#10

投稿記事 by 学校でやらされている初心者 » 2年前

この部分が間違っています。
ありがとうございます。
上記のエラーはなくなり、実行結果も表示されるようになりましたが、大体の値がファイルの値と異なってしまいます。

具体的な解決方法を教えていただけると助かります。


実行結果

コード:

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);
    }

}

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 学校の課題2

#11

投稿記事 by みけCAT » 2年前

%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関数の戻り値を無視せず、ちゃんと読み込めたかのチェックをするようにするとさらに良いでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

学校でやらされている初心者

Re: 学校の課題2

#12

投稿記事 by 学校でやらされている初心者 » 2年前

みけCAT さんが書きました:
2年前
まとめると、

コード:

        fscanf_s(fp, "%c", &(bodydata[i].initial));
のかわりに

コード:

        fscanf_s(fp, "%2s", (bodydata[i].initial), (unsigned)sizeof(bodydata[i].initial));
ありがとうございます。勉強になりました。

うまくプログラムが作動しました!
みなさん今回もありがとうございました。

返信

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