質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

ファイル入出力とプロフ

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 689

nisuko

score 33

#define _CRT_SECURE_NO_WARNINGS 1

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


typedef struct profile{
    char name[20];
    char age[10];
    char sex[10];
}Pro;

int main(){

    int i;
    char filename[256];
    FILE *fp;


    puts("プロフィールを設定します。\n"
         "以下の項目を入力してください。");
    printf("何人分作りますか?>>>");
    scanf("%d", &i);

    for (int h = 0; h != i ; h++){
        printf("%d人目のプロフィールを作ります。"
            "以下の項目を入力してください。\n", h + 1 );

        Pro hito;
        getchar();
        puts("ファイル名を入力してください。");
        fgets(filename, sizeof(filename), stdin);
        filename[strlen(filename) - 1] = '\0';
        strcat(filename, ".txt");
        fp = fopen(filename, "w");

        puts("名前を入力してください。");
        fgets(hito.name, sizeof(hito.name), stdin);
                hito.name[strlen(hito.name) - 1] = '\0';
        fprintf(fp,"名前は%s\n", hito.name);

        puts("年齢を入力してください。");
        fgets(hito.age, sizeof(hito.age), stdin);
                hito.age[strlen(hito.age) - 1] = '\0';
        fprintf(fp,"年齢は%s\n", hito.age);

        puts("性別を入力してください。");
        fgets(hito.sex, sizeof(hito.sex), stdin);
                hito.sex[strlen(hito.sex) - 1] = '\0';
        fprintf(fp,"性別は%s\n", hito.sex);

        fclose(fp);
    }
    return EXIT_SUCCESS;
}

このプログラムを走らせると、人数を1人に設定すると、.txtが作られ何もできずに終わり、2~にすると入力した人数-1人分のファイルを生成しようとし、名前が入力されたものだけ作られます。
また、ファイルは作られますが、ファイルの中に書き込む所はできません。puts→fscanfの処理が飛ばされます。

そして初心者なので一部、入門書に書かれてるファイルを生成するコードをコピーしています。
ファイル名を入力してください→fgets、strcatなどの処理のところです。

このコードをどうすれば人数分のファイル生成ができ、中身を書き込むことができますか?

説明が下手なのでもしかしたら意図が通じてない所もあるかもしれません。
それと、もともとコード自体を誰かに見せるつもりはなかったので、変数の名前はあまり気にしないでほしいです。すみません。

追記
コードを編集しました。
ここが間違ってる、ここはこうすると良いなどがあれば教えてください。
実行してみた感じでは思った通りに動いてくれました

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

こんにちは。

fscanf(fp, ...)はfpが示すファイルからデータを読み込みます。書き出しではないです。
fgets()で標準入力から文字列を読み込み、fpus()でfpへ出力すれば良いと思います。

また、fp=fopen()に成功したらfclose(fp);する必要が有ります。(開いたら閉じる。鉄則です。)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/01/16 21:21

    確認ありがとうございます。
    1行空くのは確かに気になっていたので、処理を追加しました。
    こうでいいのですよね?動作は一応考え通りに動いてくれていますし、、。

    バッファオーバーフローって取ってあった分のメモリからあふれるってやつですよね?
    改善するにはunsigned int だったり配列でとる分を増やすだけでよいのでしょうか?
    効果的な処理手法があるのでしょうか?

    キャンセル

  • 2016/01/16 21:45

    それで良いと思います。

    > バッファオーバーフローって取ってあった分のメモリからあふれるってやつですよね?

    その通りです。

    > 改善するにはunsigned int だったり配列でとる分を増やすだけでよいのでしょうか?

    増やすだけですと、それを超えて入力されるとやはりバッファオーバーフローしてしまいます。

    > 効果的な処理手法があるのでしょうか?

    方法は色々あります。今回のケースの場合は、メモリ以上の長さの入力があったら残りを'\n'まで読み捨てると良いと思います。

    あ、nisukoさんのプログラムはバッファオーバーフローは起きないですね。
    長過ぎる名前等を入力すると、動作が可笑しくなるだけです。(どうなるかは実際にやってみるのが良いです。19文字の名前や20文字以上の名前など。)
    「長過ぎる入力+配慮不足≒バッファオーバーフロー」なので短絡的に書いてしまいました。ごめんなさい。

    キャンセル

  • 2016/01/17 09:19

    ありがとうございます。
    やってみると、名前で溢れた分は年齢へ、それも溢れると性別へ、という動作しました。
    どのように対処するかまで教えていただきありがとうございます。

    キャンセル

+1

fscanf(fp, "%s", hito.namae);

は、fpでオープンしたファイルから読み込むということですが、やりたいことと違いますよね?
また、どこでもファイルに書いている箇所がありません。どこで書いているつもりですか?
プログラムを音読してみてはどうでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/01/16 20:17 編集

    説明を見る限りやりたいことと違います。
    音読しました。わからないので3回やりましたがわかりません。
    大体35か36行目辺りでfopenでファイルを生成("w"で、なければ生成する、と聞きました。)しており、そのしたのfscanfで、そのファイルに情報を書いてるつもりでした。
    どうすればよいでしょうか?fscanfは入力関数じゃないのですか?

    追記
    コード編集しました。確認をお願いします。

    キャンセル

+1

for 内の fp = fopen(filename, "w"); で出力ファイルを人数分オープンしていますが、このfpのクローズは for の外(48行目)でしていますよね。
クローズもfor内で毎回、人数分する必要があります。

また、"名前を入力してください" の箇所も fscanf で fp を指定しているのも変と思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/01/16 20:19 編集

    fcloseは毎回必要なのですね、確かに言われてみて、よく考えてみると毎回閉じなきゃおかしいですね。ありがとうございます。

    fscanfを、独学なのですが、本で習った時には
    fscanf(fp,"%s",name)
    と書かれていたので必要だと思ったのですが、、
    一度リファレンスを確認してみます、確認する癖をつけるようにします。

    追記
    コード編集しました。確認をお願いします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る