1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【C→C++あるある】勝手にfopenとかfcloseとかしてくれるヘルパー

Last updated at Posted at 2021-05-21

概要

 超絶、今更記事。でも意外と入門サイトとかには書いてない気がするw
 あると、ラムダ式とデストラクタの役割が理解出来て良い。

 現代プログラミングでは当たり前の内容なんですが、C++やっていると知らないと辛いときがたまにあります。
 C言語でしか書かれていないコード、C++使っている癖にこのような視点で変更されていないコードも世の中に結構出回っているので、たま~に役立ちます。

 std::ifstreamなんかはこの記事のような対策が打たれている(と思われる)ので、このようなことを考える必要はないです。

 **「はじめて学ぶC++11入門」**って感じです。

コード

こんなコード数年ぶりに書きましたわ


#include <iostream>

int main()
{
	FILE* fpr;
	wchar_t buffer[256];

	if( _wfopen_s(&fpr, L"C:\\Test.txt", L"r") == 0) {
		fwscanf_s(fp, L"%s", &buffer, 256);
		wprintf(L"%s", buffer);
		fclose(fpr);
		return 0;
	} else {
		wprintf(L"Error");
		return 1;
	}
}

問題点

  • fcloseは、_wfopen_sが成功したときしか実行されなくて、成功時と失敗時の表記揺れが怖い

  • fcloseと書くことを忘れそう

解決方法

  • fopen, fcloseの対になっている部分は、helperクラスを定義しておき、コンストラクタでfopen、デストラクタでfcloseを実行するように処理をする

  • ラムダ式(std::function)を使って、具体的な処理は移譲する


#include <functional>
#include <iostream>

class IoHelper {
private:
	FILE* fpr;
	errno_t error;
public:
	IoHelper(std::wstring path, std::function<void(FILE*, errno_t)> func) {
		error = _wfopen_s(&fpr, path.c_str(), L"r");
		func(fpr, error);
	}
	virtual ~IoHelper() {
		if(error == 0 ) {
			fclose(fpr);
		}
	}
};

int main()
{
	{
		// このように定義すると、IoHelperが存在するローカルスコープの中では、
		// fcloseされないが、ローカルスコープから抜けると自動的にfcloseされる。
		IoHelper helper(L"C:\\Test.txt", [] (FILE* fp, errno_t error) {
			if( error == 0 ) {
				wchar_t buffer[256];
				fwscanf_s(fp, L"%s", &buffer, 256);
				wprintf(L"%s", buffer);
			} else {
				wprintf(L"Error");
			}
		});
	}

	{
		// ここではもうfcloseされている
	}

	return 0;
}

補足

 std::ifstream, std::mutexなどは、このような仕組みと似た設計となっています。
 わざわざ意図的にcloseやunlockをしなくても使えるのが良い。

1
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?