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

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

ただいまの
回答率

88.23%

ファイルから読み取って配列に入れて表示したい c

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 630

ceb

score 11

前提・実現したいこと

初心者です。C言語で住所録を作りたいです。
①入力した名前・住所・電話番号を配列に入れて、ファイルに書き込む機能と
②ファイルから読み込んで配列に入れて表示する機能を作りたいです。
①書き込む機能はなんとかできたのですが②読み込んで表示が上手くいきません。「全%d件の登録を読み込みます。」だけ表示されて終了してしまいます。
どこを直せばいいかご教授ください。
また、参考のお手本の中ではwrite関数のfprintfのdataの前に&がなかったのですが、入れないと①が②と同様に途中で止まってしまうため入れました。何か問題が起こりますでしょうか。ついでに教えていただけると幸いです。
長いですが、一応全文載せました。初歩的な問題で申し訳ありませんがよろしくお願いいたします。

発生している問題・エラーメッセージ

該当のソースコード

#include <stdio.h>

int n;                   /*グローバル変数 */

/*プロトタイプ宣言 */
void write(void);
void read(void);

int main(void)
{
    char data[3][30];

    int bunki;
    printf("住所録です。名前と住所と電話番号を30件まで記録できます。\n");
    printf("新規登録を行うには0、登録先を読み込むには1、指定された住所を含む登録先を読み込むには2を入力してください\n");

    scanf("%d", &bunki);

    if(bunki == 0)
    {
        write();
    }
    else
    {
        if(bunki == 1)
        {
            read();
        }
        else
        {
            if(bunki == 2)
            {
                printf("作成中\n");
            }
            else
            {
                printf("0,1,2以外が入力されています。やり直してください。\n");
            }

        }

    }

    return 0;
}

/*新規登録を行う関数write */
void write(void)
{
    char data[30][3];

    FILE *fpn;             /*ファイルポインタ mame=名前*/
    FILE *fpa;             /*ファイルポインタ address=住所*/
    FILE *fpp;             /*ファイルポインタ phone=電話番号 */    
    FILE *fpr;             /*ファイルポインタ 登録が何番目かを記録するファイル*/

    fpr = fopen("numberfile.txt", "r");                        /*nの値をファイルから読み込む */
    fscanf(fpr, "%d", &n);
    fclose(fpr);
    if(n >= 29)
        {
            printf("これ以上登録できません\n");
        }
        else
        {
            if(n <= 28)
            {
                printf("%d番目の新規登録を行います。\n", n+1);   /*n+1 0番目始まりは違和感があるので1~30番で表示されるようにした */

                printf("名前を入力してください\n");
                scanf("%s", &data[n][0]);                      /*[n][0]にはn番目の登録の、名前の情報が入る*/
                fpn = fopen("namefile.txt","a");
                fprintf(fpn, "%s\n", &data[n][0]);
                fclose(fpn);

                printf("住所を入力してください\n");
                scanf("%s", &data[n][1]);                     /*[n][1]にはn番目の登録の、住所の情報が入る*/
                fpa = fopen("addressfile.txt","a");
                fprintf(fpa, "%s\n", &data[n][1]);                
                fclose(fpa);

                printf("電話番号を入力してください\n");
                scanf("%s", &data[n][2]);                     /*[n][2]にはn番目の登録の、電話番号の情報が入る*/
                fpp = fopen("phonefile.txt","a");
                fprintf(fpp, "%s\n", &data[n][2]);
                fclose(fpp);

                printf("%d番目の登録が完了しました。\n", n+1);

                n++;

                fpr = fopen("numberfile.txt", "w");            /*nの値を更新してファイルに保存 */
                fprintf(fpr, "%d\n", n);
                fclose(fpr);
            }
        }
}

/*読み込みを行う関数read */
void read(void)
{
    char data[30][3];

    FILE *fpn;
    FILE *fpa;
    FILE *fpp;
    FILE *fpr;

    fpr = fopen("numberfile.txt", "r");                        /*nの値をファイルから読み込む */
    fscanf(fpr, "%d", &n);
    fclose(fpr);

    if(n == 0)
    {
        printf("一件も登録されていません。\n");
    }
    else
    {
        fpn = fopen("namefile.txt","r");
        fpa = fopen("addressfile.txt","r");
        fpp = fopen("phonefile.txt","r");

        int m;
        for(m=0; m<=n; m++)
        {
            fscanf(fpn, "%s", &data[m][0]);
            fscanf(fpa, "%s", &data[m][1]);
            fscanf(fpp, "%s", &data[m][2]);
        }
        fclose(fpn);
        fclose(fpa);
        fclose(fpp);

        printf("全%d件の登録を読み込みます\n", n);

        for(m=0; m<=n; m++)
        {
            printf("名前:%s  住所:%s  電話番号:%s\n", data[m][0], data[m][1], data[m][2]);
        }
    }
}

試したこと

補足情報(FW/ツールのバージョンなど)

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

scanf の "%s" は、char の配列に、入力文字列を読み込む
変換指定子です。十分な大きさの配列を用意してください。
プログラム中の文字列は最後に '\0' が付きます。
char data[3] では、2文字しか入りません。

scanf は、入力を読み込む変数へのポインタを指定しないといけ
ないのですが、変数が配列の場合、配列は自動的に配列の先頭要素
へのポインタに変換されるので & を付ける必要はありません。

次のプログラムについて、よく考えてみてください。

#include <stdio.h>

int main(void)
{
    char name[32];
    printf("name: ");
    scanf("%31s", name);
    printf("  name = '%s'\n", name);

    char names[3][32];
    for (int i = 0; i < 3; i++) {
        printf("names[%d] = ", i);
        scanf("%31s", names[i]);
    }
    for (int i = 0; i < 3; i++)
        printf("  names[%d] = '%s'\n", i, names[i]);
    return 0;
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/06 19:40

    ご回答ありがとうございます!
    配列の要素数の意味をよく理解していませんでした。無事解決することができました。ありがとうございました。

    キャンセル

+1

   fscanf(fpn, "%s", &data[m][0]);

scanf関係は全部ダメです
引数は、配列のアドレスを指定します。現状では文字のアドレスとなってしまっていて、領域外のアクセスになってしまいます。

scanf,fscanfの記述は全部修正しましょう


で、Cのコードを組むなら、VisualStudioとかEclipseとかのデバッグできる環境を整えましょう
任意の行で実行を止め、変数の値を見ることができるようになります。また、1行づつ実行することもできます
そうすれば、あてずっぽでコードを組まなくて済むようになります

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/06 19:48

    ご回答ありがとうございます!
    配列について理解が足りていませんでした。これから復習していきます。お恥ずかしながらデバッグも上手く動かせず困っていたところでした。;;
    無事解決できました。ありがとうございました。

    キャンセル

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

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

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