这主要是:
std::ofstream rainbow_file("rainbow.bin", std::ios::binary);
rainbow_file.write((const char*) p.pass, password::PASSWORD_SIZE);
rainbow_file.write((const char*) h.hash_, hash::HASH_SIZE);
其中:
class hash
{
public:
static const size_t HASH_SIZE = 32;
uint8_t hash_[HASH_SIZE];
...
}
// similar for pass
我在Notepad ++中打开rainbow.bin文件,我看到我的传递为传球(字符A-Z,@,!,a-z,0-9)和哈希的二进制垃圾。我以后做的时候:
std::ifstream rainbow_file("rainbow.bin", std::ios::binary);
rainbow_file.read((char*) p.pass, password::PASSWORD_SIZE);
rainbow_file.read((char*) h.hash_, hash::HASH_SIZE);
我把回传作为二进制垃圾回来了。我尝试了很多东西(比如打开两个流 - 一个不是二进制模式 - 并使用seekg分别移动文件指针,尝试各种演员等)但是对于我的生活,我无法让它工作。而且我很好奇为什么。而且很沮丧。我在npp中重复一遍,我看到了所有的事情。
编辑:这些是不同的控制流,流正确关闭()
Edit2 :有效!仍然可以看到下面的答案以及更多C ++方式的评论
答案 0 :(得分:1)
std::ifstream rainbow_file("rainbow.bin", std::ios::binary); /* OK */
rainbow_file.read((char*) p.pass, password::PASSWORD_SIZE); /* KO */
rainbow_file.read((char*) h.hash_, hash::HASH_SIZE);
应替换为:
rainbow_file.read ( reinterpret_cast < char*> (&(p.pass)), password::PASSWORD_SIZE * sizeof(uint_8t));
rainbow_file.read ( reinterpret_cast < char*> (&(h.hash_)), hash::HASH_SIZE * sizeof(uint_8t));
这样你就不会假设sizeof(uint_8t)== sizeof(char)。
在C ++中,h.hash_是一个类型为uint_8t(&amp;)[hash :: HASH_SIZE]的数组,而不是一个指针......你可以通过让你的编译器检查转换来轻松解决问题,但不幸的是,你'使用了C样式演员,未经检查。
永远不要在C ++程序中使用C样式的铸造方法!!!
但实际上你可以在纯C ++中完成它,没有错误:
std::ifstream rainbow_file("rainbow.bin", std::ios::binary);
rainbow_file >> p.pass >> h.hash_;
答案 1 :(得分:1)
如果在您的文件中使用非ascii char(似乎是二进制文件),则必须使用std :: noskipws流操纵器。您还可以显式指定要加载的每个字段的宽度,从而生成代码rainbow_file >> std::noskipws >> std::setw ( password::PASSWORD_SIZE ) >> p.pass >> std::noskipws >> std::setw ( hash::HASH_SIZE ) >> h.hash_;
。
@Nicol Bolas我没有假设uint_8t的类型大小,但指针的大小!转换指针本质上是不安全的,我们对类型的真实内存布局了解多少?没有。这是投射非派生类型指针不安全的唯一原因。我使用reinterpret_cast来告知其他开发人员以及我知道我正在做什么的编译器,重新解释转换的工作方式与日常使用中的静态转换相同。我可以看到每个人都看到了这个伎俩,所以我做得很好!
最后我必须重复p.pas
和h.hash_
不是C ++中的指针!!!!!!它是POD,C风格的演员无法告诉你,C ++风格确实......