unsigned int fname_length = 0;
//fname length equals 30
file.read((char*)&fname_length,sizeof(unsigned int));
//fname contains random data as you would expect
char *fname = new char[fname_length];
//fname contains all the data 30 bytes long as you would expect, plus 18 bytes of random data on the end (intellisense display)
file.read((char*)fname,fname_length);
//m_material_file (std:string) contains all 48 characters
m_material_file = fname;
// count = 48
int count = m_material_file.length();
现在尝试这种方式时,intellisense在将char数组设置为all'后仍显示18个字节的数据,并得到完全相同的结果。即使没有文件读取
char name[30];
for(int i = 0; i < 30; ++i)
{
name[i] = ' ';
}
file.read((char*)fname,30);
m_material_file = name;
int count = m_material_file.length();
任何想法在这里出错了,它可能是完全显而易见的但是我很难过!
感谢
答案 0 :(得分:3)
听起来像文件中的字符串不是以空值终止的,并且intellisense假定它是。或者,当您将字符串(30)的长度写入文件时,您没有在该计数中包含空字符。尝试添加:
fname[fname_length] = '\0';
在file.read()之后。哦,是的,你还需要分配一个额外的角色:
char * fname = new char[fname_length + 1];
答案 1 :(得分:1)
我猜intellisense试图将char*
解释为C字符串,并且正在寻找'\0'
字节。
答案 2 :(得分:1)
fname
是char*
,因此调试器显示和m_material_file = fname
都会期望它以'\ 0'终止。你从来没有明确地这样做,但只是发生了无论数据如何跟随内存缓冲区在某一点都有一个零字节,所以你得到的字符串比你更长,而不是崩溃(这可能是某种情况)。期望的。
答案 3 :(得分:1)
使用
m_material_file.assign(fname, fname + fname_length);
不需要零终止符。此外,更喜欢std::vector
到原始数组。
答案 4 :(得分:1)
std::string::operator=(char const*)
期望由'\0'
终止的字节序列。您可以使用以下任何方法解决此问题:
fname
并明确添加'\0'
,其他人建议或 m_material_file.assign(&fname[0], &fname[fname_length]);
代替或 file.get(ch)
和m_material_file.push_back(ch)
就个人而言,我会使用最后一个选项,因为它完全取消了显式分配的缓冲区。显式new
少一个是泄漏记忆的可能性减少一个。以下代码片段应该可以完成这项工作:
std::string read_name(std::istream& is) {
unsigned int name_length;
std::string file_name;
if (is.read((char*)&name_length, sizeof(name_length))) {
for (unsigned int i=0; i<name_length; ++i) {
char ch;
if (is.get(ch)) {
file_name.push_back(ch);
} else {
break;
}
}
}
return file_name;
}
您可能不希望使用sizeof(unsigned int)
来确定要写入二进制文件的字节数。读/写的字节数取决于编译器和平台。如果您有最大长度,则使用它来确定要写出的特定字节大小。如果长度保证少于255个字节,则只为该长度写入一个字节。那么你的代码将不依赖于内部类型的字节大小。