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

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

ただいまの
回答率

88.83%

ループ2回目以降が上手くいきません。ファイルの入出力 strtok_s関数

解決済

回答 2

投稿 編集

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

madanai

score 5

アドレス帳のような機能を作っています。

不具合が起きているのは、profile_edit関数「mail.txtのデータ(元のデータ)をmail2.txtに書き写しながら、変更したい部分に新しい文字列を挿入する」のところです。
今の状態だと「元の文字列が消えずに残っているが表示されない」ので1回目のループはうまくいきます。
2回目以降だと、消えずに残っている文字列が邪魔をしてうまくいきません。1回目のループで、元の文字列を上書きもしくは削除したいです。

使う関数自体変えればいいのでしょうが、知識が浅くどの関数をどう使えばいいのか分からない状態です。(strtok_s関数とCSVファイルを使うとうまくいくのかなと考え程度です)

専門用語等分からないことが多いです。

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

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

int profile_edit ( int , char [ 256 ] );

struct profile {            /* プロフィール構造体 */
    char name [ 256 ];        /* 氏名 */
    char code [ 256 ];        /* 郵便番号 */
    char add [ 256 ];        /* 住所 */
    char tel [ 256 ];        /* 電話番号 */
    char mail [ 256 ];        /* メールアドレス */
};
FILE* fp;
FILE* fp2;

int main ( )
{
    struct profile prof;
    char file_in [ 256 ];
    int num = 0;
    int end = 0;

    printf ( "【アドレス帳】\n" );
    do {
        printf ( "\nアドレスの\n\t[登録]:1\t[編集]:2\n\t[削除]:3\t[参照]:4\t数字を入力:" );
        scanf_s ( "%d" , &num );
        printf ( "\n" );
        if ( num == 1 ) {                                    /* 1の場合 */
            fopen_s ( &fp , "mail.txt" , "w" );
            if ( fp == NULL ) {
                return 0;
            }
            printf ( "氏名     :" );
            scanf_s ( "%s" , prof.name , 255 );
            printf ( "郵便番号   :" );
            scanf_s ( "%s" , prof.code , 255 );
            printf ( "住所     :" );
            scanf_s ( "%s" , prof.add , 255 );
            printf ( "電話番号   :" );
            scanf_s ( "%s" , prof.tel , 255 );
            printf ( "E-mailアドレス:" );
            scanf_s ( "%s" , prof.mail , 255 );
            fputs ( "氏名     :" , fp );
            fputs ( prof.name , fp );
            fputs ( "\n郵便番号   :" , fp );
            fputs ( prof.code , fp );
            fputs ( "\n住所     :" , fp );
            fputs ( prof.add , fp );
            fputs ( "\n電話番号   :" , fp );
            fputs ( prof.tel , fp );
            fputs ( "\nE-mailアドレス:" , fp );
            fputs ( prof.mail , fp );
            fputs ( "\n" , fp );
            fclose ( fp );
        }
        else if ( num == 2 ) {                                /* 2の場合 */
            fopen_s ( &fp2 , "mail2.txt" , "w" );
            if ( fp2 == NULL ) {
                printf ( "編集ができません。\n" );
                break;
            }
            fopen_s ( &fp , "mail.txt" , "r" );
            if ( fp == NULL ) {
                printf ( "連絡先が見つかりません。\n" );
                break;
            }
            int edit = 0;    /* 編集番号を受け取る */
            int a = 0;        /* profile_edit関数の引数を受け取る */
            char newdata [ 256 ];
            printf ( "どの項目を編集しますか?\n\t[氏名]:1\t[郵便番号]:2\n\t[住所]:3\t[電話番号]:4\n\t[E-mailアドレス]:5\t\t数字を入力:" );
            scanf_s ( "%d" , &edit );
            printf ( "\n新しい情報を入力してください。\n\t:" );
            scanf_s ( "%s" , newdata , 255 );

            profile_edit ( edit , newdata );
            if ( a = profile_edit ( edit , newdata ) == 0 ) {
                printf ( "新しい情報に書き換えられました。\n" );
            }
            else {
                printf ( "編集に失敗しました。\n" );
                break;
            }
        }

        else if ( num == 3 ) {                                /* 3の場合 */

            if ( remove ( "mail.txt" ) == 0 ) {
                printf ( "連絡先を削除しました。\n" );
            }
            else {
                printf ( "連絡先の削除に失敗しました。\n" );
            }
        }
        else if ( num == 4 ) {                                /* 4の場合 */
            fopen_s ( &fp , "mail.txt" , "r" );
            if ( fp == NULL ) {
                printf ( "連絡先が見つかりません。\n" );
                do {
                    printf ( "\n続けますか?[はい]:1 [いいえ]:2\t数字を入力:" );
                    scanf_s ( "%d" , &end );
                } while ( ( end != 1 ) && ( end != 2 ) );
                if ( end == 2 ) {
                    return 0;
                }
                else {
                    continue;
                }
            }
            while ( 1 ) {
                fgets ( file_in , 255 , fp );
                if ( feof ( fp ) ) {
                    break;
                }
                printf ( "%s" , file_in );
            }
            fclose ( fp );
        }
        else {
            printf ( "1~4の数字を入力し直してください。\n" );
            continue;
        }

        do {
            printf ( "\n続けますか?[はい]:1 [いいえ]:2\t数字を入力:" );
            scanf_s ( "%d" , &end );
        } while ( ( end != 1 ) && ( end != 2 ) );
        if ( end == 2 ) {
            break;
        }
    } while ( end == 1 );

    return 0;
}

// 関数名 : profile_edit
//テキストファイルの1部を書き換える関数
int profile_edit ( int row , char str [ 256 ] )        
{
    int ch = 0;
    int nr = 0;
    int nc = 0;

    while ( ( ch = fgetc ( fp ) ) != EOF ) {
        fputc ( ch , fp2 );
        if ( ch == '\n' ) {
            nr++;
        }
        if ( nr == row - 1 ) {
            nc++;
        }
        if ( nc == 17 ) {
            fputs ( str , fp2 );
            fputc ( '\n' , fp2 );
            fputc ( '\0' , fp2 );

            nr++;
            nc++;
        }
    }
    fclose ( fp );
    fclose ( fp2 );

    fopen_s ( &fp2 , "mail2.txt" , "r" );
    if ( fp2 == NULL ) {
        return -1;
    }
    fopen_s ( &fp , "mail.txt" , "w" );
    if ( fp == NULL ) {
        return -1;
    }
    while ( ( ch = fgetc ( fp2 ) ) != EOF ) {
        fputc ( ch , fp );
    }
    fclose ( fp );
    fclose ( fp2 );

    return 0;
}

Visuai studio

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • y_waiwai

    2020/07/30 21:58

    提示のコードにはどういう不具合があって、それをどうしたいんでしょうか。
    そこらへん詳しく説明しましょう。

    いきなりコード出されても読む気にもなりません

    キャンセル

  • madanai

    2020/07/31 09:27

    失礼しました。
    不具合が起きているのは、profile_edit関数「mail.txtのデータ(元のデータ)をmail2.txtに書き写しながら、変更したい部分に新しい文字列を挿入する」のところです。
    今の状態だと「元の文字列が消えずに残っているが表示されない」ので1回目のループはうまくいきます。
    2回目以降だと、消えずに残っている文字列が邪魔をしてうまくいきません。1回目のループで、元の文字列を上書きもしくは削除したいのです。

    使う関数自体変えればいいのでしょうが、知識が浅くどの関数をどう使えばいいのか分からない状態です。(strtok_s関数とscvファイルを使うとうまくいくのかなと考え程度です)

    キャンセル

  • y_waiwai

    2020/07/31 09:30

    それを質問に追記しましょう。
    修正依頼に書いてても読まれません

    キャンセル

回答 2

check解決した方法

0

fopen_s ( &fp2 , "mail2.txt" , "r" );
    if ( fp2 == NULL ) {
        return -1;
    }
    fopen_s ( &fp , "mail.txt" , "w" );
    if ( fp == NULL ) {
        return -1;
    }
    while ( 1 ) {
        fgets ( file_in , 255 , fp2 );
        if ( feof ( fp2 ) ) {
            break;
        }
        fputs ( file_in , fp );    
}
fclose ( fp );
fclose ( fp2 );

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

1回目の編集で、mail.txtから目的の項目を変更してmail2.txtを作ってそのまま(作りっぱなし)ですよね?
これでは2回目の編集は何も変わっていないmail.txtから読み上げてmail2.txtを作り直すので1回目の編集内容が元に戻ってしまいます。
編集が終わって、ファイルをクローズしたら、

  1. mail.txtを削除する。
  2. mail2.txtをmail.txtにリネームする。
    が必要です。

strtok_sとCSVを使用したい理由は、想像ですがアドレス帳(mail.txt)の各項目をカンマ区切りで格納して、編集の際カンマで区切ったトークンとして項目を扱いたいのかな?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/31 09:30

    mail2.txtはデータを一時保管しているだけで、最後にmail.txtにすべて上書きしています。

    不具合が起きているのは、profile_edit関数「mail.txtのデータ(元のデータ)をmail2.txtに書き写しながら、変更したい部分に新しい文字列を挿入する」のところです。
    新しい文字列を元の文字列に上書き、もしくは新しい文字列を挿入した後に元の文字列を削除したいです。
    そのためには、データ(文字列)ごとに配列に格納するのがいいと思い、strtok_sで区切りCSVファイルを作成するのが手っ取り早いかな、と思ったのです。知識はありません。。

    キャンセル

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

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

関連した質問

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