使用EasyX製作遊戲需要讀寫檔案時遇到編碼問題的解決方法

suang發表於2024-05-25

使用EasyX製作遊戲需要讀寫檔案時遇到編碼問題的解決方法

一、編碼問題

例如我們需要從file.txt中讀取文字,再使用outtextxy()函式向視窗繪製文字。
查詢EasyX的官方文件可知,該函式有兩個過載,分別為:void outtextxy(int x, int y, LPCTSTR str)void outtextxy(int x, int y, TCHAR c)
如果我們的file.txt檔案使用GBK或者GB2312編碼的話,會導致VS編譯器混合utf-8編碼和GBK編碼,導致程式不能正確繪製文字。
編碼問題一直是令人頭痛的問題,這裡給出通用的方法論,希望能夠帶來一些幫助。

二、解決方法

1.重新編碼txt檔案

首先使用vscode開啟file.txt檔案,確保檔案編碼為utf-8。如下圖:

如果不是utf-8編碼,點選選擇編碼,透過編碼重新開啟,選擇utf-8編碼,這時原來的內容會變成亂碼,將原來的內容刪除,重新輸入,儲存即可。具體的操作如下圖:


2.程式碼部分

首先,我們需要用到std::wstring_convert,這個標準庫需要標頭檔案#include<codecvt>,我們定義string str,用static std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;定義我們所需要的從utf-8編碼的字串到寬字串的轉換器。
開啟檔案,讀取檔案內容到str內,使用from_bytes(str)函式即可實現字串的轉換,又由於outtextxy沒有使用wstring的過載,使用wstring的成員函式c_str()即可轉換成wchar_t字串,最終,我們用這樣的程式碼將文字繪製在視窗上outtextxy(10, 10, converter.from_bytes(str).c_str());
效果如圖:

完整程式碼如下:

#include<fstream>
#include<codecvt>
#include<string>
#include<iostream>
#include<graphics.h>

std::string str;

int main()
{
	initgraph(500, 500);

	static std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;

	std::ifstream infile("file.txt");
	if (!infile)
	{
		std::cerr << "無法開啟檔案" << std::endl;
		return 0;
	}
	std::getline(infile, str);
	infile.close();

	while (true)
	{
		outtextxy(10, 10, converter.from_bytes(str).c_str());
	}
}

三、問題延伸

如果我們需要在程式內使用InputBox對話方塊輸入,並將輸入的內容正確儲存在檔案裡,該如何操作呢。
首先檢視InputBox的引數列表bool InputBox(LPTSTR pString, int nMaxCount, LPCTSTR pPrompt = NULL, LPCTSTR pTitle = NULL, LPCTSTR pDefault = NULL, int width = 0, int height = 0, bool bOnlyOK = true);,其中大部分是預設引數,這裡不做解釋,重點是第一個引數,InputBox只接受&wchar_t的引數,因此,假設輸入的字串最大長度為256,我們定義TCHAR buffer[256];陣列來接收輸入,寫下這樣的程式碼來彈出對話方塊InputBox(buffer, 256, _T("請輸入:"), _T("輸入框"), NULL, 0, 0, TRUE);開啟檔案,定義std::string str;,仍然使用我們剛才定義的轉換器,使用to_bytes()函式,即可將輸入的內容轉換為utf-8字串。再進行輸入即可。
完整程式碼如下:

#include<fstream>
#include<codecvt>
#include<string>
#include<iostream>
#include<graphics.h>

int main()
{
	initgraph(500, 500);

	static std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;

	TCHAR buffer[256];
	InputBox(buffer, 256, _T("請輸入:"), _T("輸入框"), NULL, 0, 0, TRUE);

	std::ofstream outfile("file.txt");
	if (!outfile)
	{
		std::cerr << "無法開啟檔案" << std::endl;
		return 0;
	}
	std::string str = converter.to_bytes(buffer);
	outfile << str;
	outfile.close();
}

相關文章