Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ WCHAR*的结尾包含垃圾_C++_Winapi_Unicode - Fatal编程技术网

C++ WCHAR*的结尾包含垃圾

C++ WCHAR*的结尾包含垃圾,c++,winapi,unicode,C++,Winapi,Unicode,我正在一个小项目中工作,在这个项目中我必须管理文件i/O(这是我刚刚开始做的事情)。我使用带有unicode的WIN32 API作为字符集,因此使用宽字符存储所有文件数据,程序中的所有字符串使用std::wstring存储。这是函数中读取和返回字符串的部分: //Get the string from file and return it //(nChars is the amount of characters to read)

我正在一个小项目中工作,在这个项目中我必须管理文件i/O(这是我刚刚开始做的事情)。我使用带有unicode的WIN32 API作为字符集,因此使用宽字符存储所有文件数据,程序中的所有字符串使用std::wstring存储。这是函数中读取和返回字符串的部分:

            //Get the string from file and return it
            //(nChars is the amount of characters to read)
            WCHAR * resultBuffer = new WCHAR[nChars];
            file.read(resultBuffer, nChars); 
            std::wstring result = resultBuffer;
            delete[] resultBuffer;
            return result;
然而,我注意到结果的末尾包含一堆垃圾字符(整个字符串从文件中正确读取,但在末尾附加了垃圾字符)。进一步检查后,我注意到这些字符也出现在resultBuffer分配之后。现在,如果它们写得太多,只是看起来像是附加的,并且它们也被复制到结果中(意味着结果得到的元素比预期的多),这就不会是一个问题,这会导致以后使用它们时出现很多问题。我设法解决了这个问题,添加了一些:

            //Get the string from file and return it
            WCHAR * resultBuffer = new WCHAR[nChars];
            file.read(resultBuffer, nChars);
            std::wstring temp = resultBuffer;
            std::wstring result;
            for (INT i = 0; i < nChars; i++) { //NOTE: This shouldn't be necessary 
                result.push_back(temp.at(i));
            }               
            delete[] resultBuffer;
            return result;

您正在调用
std::wstring
构造函数,该构造函数需要以null结尾的
wchar\u t*
字符串,但您不是以null结尾的缓冲区。再分配+1个wchar并将其设置为0:

WCHAR * resultBuffer = new WCHAR[nChars+1];
file.read(resultBuffer, nChars); 
resultBuffer[nChars] = L'\0'; 
std::wstring result = resultBuffer;
delete[] resultBuffer;
return result;
或者,如果在构造
std::wstring
时指定缓冲区长度,则不需要空终止符:

WCHAR * resultBuffer = new WCHAR[nChars];
file.read(resultBuffer, nChars); 
std::wstring result(resultBuffer, nChars);
delete[] resultBuffer;
return result;
无论哪种方式,您都应该使用
std::vector
来管理内存缓冲区,而不是手动使用
new[]
/
delete[]

std::vector<WCHAR> resultBuffer(nChars+1);
file.read(&resultBuffer[0], nChars); 
resultBuffer[nChars] = L'\0'; 
return std::wstring(resultBuffer.data());

您正在调用
std::wstring
构造函数,该构造函数需要以null结尾的
wchar\u t*
字符串,但您不是以null结尾的缓冲区。再分配+1个wchar并将其设置为0:

WCHAR * resultBuffer = new WCHAR[nChars+1];
file.read(resultBuffer, nChars); 
resultBuffer[nChars] = L'\0'; 
std::wstring result = resultBuffer;
delete[] resultBuffer;
return result;
或者,如果在构造
std::wstring
时指定缓冲区长度,则不需要空终止符:

WCHAR * resultBuffer = new WCHAR[nChars];
file.read(resultBuffer, nChars); 
std::wstring result(resultBuffer, nChars);
delete[] resultBuffer;
return result;
无论哪种方式,您都应该使用
std::vector
来管理内存缓冲区,而不是手动使用
new[]
/
delete[]

std::vector<WCHAR> resultBuffer(nChars+1);
file.read(&resultBuffer[0], nChars); 
resultBuffer[nChars] = L'\0'; 
return std::wstring(resultBuffer.data());

从缓冲区读取n个字符后,创建
std::string
的机制是使用大小构造函数

file.read(resultBuffer, nChars);
std::wstring temp(resultBuffer, nChars);

这与null终止输入略有不同,因为它允许resultBuffer包含L'\0',L'\0'成为新字符串的一部分。如果这不正确,则确保从
文件读取的字节数后数据以null结尾。读取

当从缓冲区读取n个字符时,创建
std::string
的机制是使用大小构造函数

file.read(resultBuffer, nChars);
std::wstring temp(resultBuffer, nChars);

这与null终止输入略有不同,因为它允许resultBuffer包含L'\0',L'\0'成为新字符串的一部分。如果这不正确,则确保从
文件读取的字节数后数据以null结尾。使用C++17读取

,还可以通过将的结果传递到
文件.read()
,立即写入
std::wstring
。在使用C++17之前,可以使用字符串的
运算符[]
取而代之。如果您使用
std::vector
则无需自己设置终止符,它将默认初始化为零。@MarkRansom:是的,这是我不喜欢
std::vector
的一点-如果不初始化新元素,就无法分配其缓冲区。对于原始内存缓冲区,默认初始化可能是浪费时间。除非分别使用
reserve()
push_back()
元素,这对文件I/O不好。我完全同意
std::vector
的不必要开销。但我想这就是他们发明
std::unique_ptr
的原因。使用C++17,您还可以通过将结果传递到
file.read()
,立即将其写入
std::wstring
。在使用C++17之前,您可以使用字符串的
运算符[]
取而代之。如果您使用
std::vector
则无需自己设置终止符,它将默认初始化为零。@MarkRansom:是的,这是我不喜欢
std::vector
的一点-如果不初始化新元素,就无法分配其缓冲区。对于原始内存缓冲区,默认初始化可能是浪费时间。除非分别使用
reserve()
push_back()
元素,这对文件I/O不好。我完全同意
std::vector
的不必要开销。但我想这就是为什么他们发明了
std::unique\u ptr