ファイル書き込みの上書きについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
yoko
記事: 24
登録日時: 15年前

ファイル書き込みの上書きについて

#1

投稿記事 by yoko » 10年前

久々の質問です。

ファイル出力において、既存のファイルを上書きしようとすると、エラーが出て上書きされません。
新規ファイルの場合は正しく出力されます。
原因わかりましたら教えてください。
情報の過不足ありましたら、提示いたしますので、返信ください。

環境
c言語
VS2015
win8.1update

以下コードです。

コード:

//bat.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bat.h"

int main(void) {

	FILE *fp_w;

	fp_w=file_make();
	file_write(&fp_w);
	fclose(fp_w);


	return 0;
}

コード:

//file_write.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bat.h"

FILE* file_make() {
	FILE *fp_w,*fp_r;
	char  file_w[N];
	char yn[10] = { 0 };
	errno_t error;

	/*ファイル作成*/
	while (1) {
		int w_flag = 0;
		char file_temp[N];
		while (1) {
			w_flag = 0;
			printf("出力ファイル名を入力してください(拡張子は自動で付きます)\nファイル名:");
			scanf_s("%s", file_temp, 256);
			while (1) {
				printf("ファイル名は%sでいいですか?\n(Y/N)?", file_temp);
				scanf_s("%s", &yn, 2);
				if (yn[0] == 'y' || yn[0] == 'Y') {
					strcpy_s(file_w,_countof(file_w) ,file_temp);
					strcat_s(file_w, _countof(file_w),".bat");
					if (error = fopen_s(&fp_r,file_w, "r") == 0) {
						while (1) {
							printf("ファイルが既に存在します\n上書きしますか?\n(Y/N)?");
							scanf_s("%s", &yn, 2);
							fclose(fp_r);
							if (yn[0] == 'y' || yn[0] == 'Y') {
								w_flag = 1;
								if ( error= fopen_s(&fp_w,file_w, "w+") != 0) {
									printf("ファイルオープンエラーです。\n終了します。\n");
									exit(1);
								}
								break;
							}
							else if (yn[0] == 'n' || yn[0] == 'N') {
								w_flag = -1;
								break;
							}
						}
						fclose(fp_r);

					}
					else {
						w_flag = 1;
						if (error = fopen_s(&fp_w,file_w, "w+") != 0) {
							printf("ファイルオープンエラーです。\n終了します。\n");
							exit(1);
						}
					}
				}
				else if (yn[0] == 'n' || yn[0] == 'N') break;
				if (w_flag == -1) break;
				if (w_flag == 1)break;
			}
			if (w_flag == 1) break;
		}
		if (w_flag == 1) break;
	}
	return fp_w;
}

void file_write(FILE** fp_w) {
	fprintf_s(*fp_w, "@echo off\n\nrem管理者実行確認\nfor /f \"tokens = 3 delims = \\ \" %%i in (\'whoami /groups^|find \"Mandatory\"\') do set LEVEL=%%%%i\n");
	
}

コード:

//bat.h
#define N (256) //ファイル名長さ最大
#define L 30 //設定値文字数最大

extern void file_write(FILE** fp_w);
extern FILE* file_make();
添付ファイルにエラーメッセージの画像を貼ります。
添付ファイル
error.jpg
エラーメッセージ
error.jpg (57.22 KiB) 閲覧数: 5414 回

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

Re: ファイル書き込みの上書きについて

#2

投稿記事 by box » 10年前

個人的な感想です。
file_write.c
の処理内容が仰々しいような感じがします。もっと単純にできるように思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

yoko
記事: 24
登録日時: 15年前

Re: ファイル書き込みの上書きについて

#3

投稿記事 by yoko » 10年前

box さんが書きました:個人的な感想です。
file_write.c
の処理内容が仰々しいような感じがします。もっと単純にできるように思います。
boxさん
おっしゃる通り、簡素化できないかとも思いましたが
今の私の知識ではこれが精いっぱいです。
※YNの処理を正しく行うため試行錯誤した結果です。

最初の質問とは異なりますが、簡素化の方法ヒントのみでかまいませんので、
何かありますでしょうか。

かずま

Re: ファイル書き込みの上書きについて

#4

投稿記事 by かずま » 10年前

yoko さんが書きました:ファイル出力において、既存のファイルを上書きしようとすると、エラーが出て上書きされません。
新規ファイルの場合は正しく出力されます。
原因わかりましたら教えてください。
fclose(fp_r) が while(1) の中で 1回以上、while(1) の後で 1回の
合わせて 2回以上呼ばれています。
fclose(fp_r); を while(1) の前にひとつだけ置くようにしてみてください。

それから

コード:

    if (error = fopen_s(&fp_r,file_w, "r") == 0) {
    if ( error= fopen_s(&fp_w,file_w, "w+") != 0) {
    if (error = fopen_s(&fp_w,file_w, "w+") != 0) {
ですが、

コード:

    if (error = (fopen_s(&fp_r,file_w, "r") == 0)) {
    if ( error= (fopen_s(&fp_w,file_w, "w+") != 0)) {
    if (error = (fopen_s(&fp_w,file_w, "w+") != 0)) {
という意味になりますよ。error には 0 か 1 しか入りません。
本当は次のようにしたかったのでは?

コード:

    if ((error = fopen_s(&fp_r,file_w, "r")) == 0) {
    if ((error = fopen_s(&fp_w,file_w, "w+")) != 0) {
    if ((error = fopen_s(&fp_w,file_w, "w+")) != 0) {
これだと error にエラーコードが入ります。
もっとも今回は error の値は参照していないので、次のように書けば十分でしょう。

コード:

    if (fopen_s(&fp_r,file_w, "r") == 0) {
    if (fopen_s(&fp_w,file_w, "w+") != 0) {
    if (fopen_s(&fp_w,file_w, "w+") != 0) {

yoko
記事: 24
登録日時: 15年前

Re: ファイル書き込みの上書きについて

#5

投稿記事 by yoko » 10年前

かずま さんが書きました: fclose(fp_r) が while(1) の中で 1回以上、while(1) の後で 1回の
合わせて 2回以上呼ばれています。
fclose(fp_r); を while(1) の前にひとつだけ置くようにしてみてください。
返信ありがとうございます。
while(1)の前にのみfcloseを書くことで解決しました。
※while(1)の前がif分のため、対応するelse文の後にもfclose書きました。
ありがとうござました。

とりあえず正常に動きましたので、
簡潔にするのほうは無しにして、解決とさせていただきます。

かずま

Re: ファイル書き込みの上書きについて

#6

投稿記事 by かずま » 10年前

yoko さんが書きました:while(1)の前にのみfcloseを書くことで解決しました。
※while(1)の前がif分のため、対応するelse文の後にもfclose書きました。
while (1) は 4つありますが、
いま問題にしているのは一番内側の while (1) ですよね。その「while文」の前の
「if文」では fopen_s(&fp_r, file_w, "r") を実行しています。
対応する else は、ファイルのオープンにした場合ですから、fclose(fp_r);を
実行してはいけません。
yoko さんが書きました:とりあえず正常に動きましたので、
簡潔にするのほうは無しにして、解決とさせていただきます。
こんなのはどうでしょうか?

コード:

FILE *file_make(void)
{
    FILE *fp;
    char yn[10];  // "y", "Y", "n", "N"
    char base_name[N];  // no extention
    char full_name[N];  // with extention
 
    while (1) {
        printf("出力ファイル名を入力してください(拡張子は自動で付きます)\nファイル名:");
        scanf_s("%s", base_name, N);
        do {
            printf("ファイル名は%sでいいですか?\n(Y/N)?", base_name);
            scanf_s("%s", &yn, 10);
        } while (strchr("yYnN", yn[0]) == NULL);
        if (yn[0] == 'n' || yn[0] == 'N') continue;
        sprintf_s(full_name, N, "%s.bat", base_name);
        if (fopen_s(&fp, full_name, "r") == 0) {
            fclose(fp);
            do {
                printf("ファイルが既に存在します\n上書きしますか?\n(Y/N)?");
                scanf_s("%s", &yn, 10);
            } while (strchr("yYnN", yn[0]) == NULL);
            if (yn[0] == 'n' || yn[0] == 'N') continue;
        }
        break;
    }
    if (fopen_s(&fp, full_name, "w") != 0) {
        printf("ファイルオープンエラーです。\n終了します。\n");
        exit(1);
    }
    return fp;
}

yoko
記事: 24
登録日時: 15年前

Re: ファイル書き込みの上書きについて

#7

投稿記事 by yoko » 10年前

かずまさん

返信ありがとうございます。
strchr関数を初めて知りました。
これを使うほうが完結に書けますね。

かずまさんのを使用させていただきます。

ありがとうございました。

閉鎖

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