Bit-Shift 一个字符串来解码保存文件 C++
Bit-Shift a string to decode save file C++
我有点想解码我的保存文件。我想到了这个。但是从保存文件中将字符移回原位似乎无法正常工作。只有数字似乎恢复正确,但所有其他字符似乎都变成了奇怪的符号。如您所见,我将 savecontent << 1 向左位移,在加载时,我将传入行 >> 1 向右位移。但它没有像我预期的那样工作。位移在字符串上不能正常工作吗?
void erGuiManager::SaveToFile(string filename) {
ofstream ifs;
ifs.open(filename, ios::binary);
if (ifs.is_open())
{
string savecontent = "";
for (int i = 0; i < guiItems.size(); i++) {
if (dynamic_cast<erGuiBasicNode*>(guiItems[i])) {
savecontent.append( dynamic_cast<erGuiBasicNode*>(guiItems[i])->save(true));
}
}
for (int i = 0; i < savecontent.length(); i++) {
savecontent[i] = savecontent[i] << 1;
}
ifs.write(savecontent.c_str(), strlen(savecontent.c_str()));
ifs.close();
}
else {
cout << "Error: Unable to open file " << filename;
}
}
void erGuiManager::LoadFromFile(string filename) {
string line;
string out;
ifstream myfile(filename);
if (myfile.is_open())
{
while (getline(myfile, line))
{
for (int i = 0; i < line.length(); i++) {
line[i] = line[i] >> 1;
}
out.append(PasteNodeFromString(line,true));
}
ConnectBezierLines(out);
myfile.close();
}
}
运算符 >>
执行 arithmetic shift,这意味着所有 >=64 的值的最高位都为 1,这不是您想要的。在 ASCII 中,数字用 48 到 57 之间的值表示,字母从 65 开始,所以这就是字母不起作用的原因。
一个简单的解决方案是将最高位显式设置为零:
line[i] = (line[i] >> 1) & 0x7f;
这仍然意味着您只能使用字符集的下半部分,即值 <127。更好的解决方案是轮换 shift:
line[i] = (line[i] << 1) | (line[i] >> 7)&0x01;
编码和
line[i] = (line[i] >> 1)&0x7f |(line[i]<<7);
积分提升有一个微妙的问题(因为 char
没有 operator<<
,所以它被提升为 int
)和符号扩展。
考虑:
int main() {
char a = 127;
printf("%hhd\n", a);
char b = a << 1;
printf("%hhd\n", b);
char c = b >> 1;
printf("%hhd\n", c);
}
及其输出:
127
-2
-1
如您所见,原始值无法恢复。
修复是在 unsigned
space 中操作,这样就不会发生符号扩展:
int main() {
char a = 127;
printf("%hhd\n", a);
char b = static_cast<unsigned char>(a) << 1;
printf("%hhd\n", b);
char c = static_cast<unsigned char>(b) >> 1;
printf("%hhd\n", c);
}
正确输出:
127
-2
127
在这种特殊情况下,只需要 static_cast<unsigned char>(b) >> 1
即可解决此问题,但是,在执行移位时,应该了解整数提升和符号扩展。
没有投射:
char(254) >> 1 === int(-2) >> 1 === int(-1) === char(-1)
演员阵容:
unsigned char(254) >> 1 === int(254) >> 1 === int(127) === char(127)
我有点想解码我的保存文件。我想到了这个。但是从保存文件中将字符移回原位似乎无法正常工作。只有数字似乎恢复正确,但所有其他字符似乎都变成了奇怪的符号。如您所见,我将 savecontent << 1 向左位移,在加载时,我将传入行 >> 1 向右位移。但它没有像我预期的那样工作。位移在字符串上不能正常工作吗?
void erGuiManager::SaveToFile(string filename) {
ofstream ifs;
ifs.open(filename, ios::binary);
if (ifs.is_open())
{
string savecontent = "";
for (int i = 0; i < guiItems.size(); i++) {
if (dynamic_cast<erGuiBasicNode*>(guiItems[i])) {
savecontent.append( dynamic_cast<erGuiBasicNode*>(guiItems[i])->save(true));
}
}
for (int i = 0; i < savecontent.length(); i++) {
savecontent[i] = savecontent[i] << 1;
}
ifs.write(savecontent.c_str(), strlen(savecontent.c_str()));
ifs.close();
}
else {
cout << "Error: Unable to open file " << filename;
}
}
void erGuiManager::LoadFromFile(string filename) {
string line;
string out;
ifstream myfile(filename);
if (myfile.is_open())
{
while (getline(myfile, line))
{
for (int i = 0; i < line.length(); i++) {
line[i] = line[i] >> 1;
}
out.append(PasteNodeFromString(line,true));
}
ConnectBezierLines(out);
myfile.close();
}
}
运算符 >>
执行 arithmetic shift,这意味着所有 >=64 的值的最高位都为 1,这不是您想要的。在 ASCII 中,数字用 48 到 57 之间的值表示,字母从 65 开始,所以这就是字母不起作用的原因。
一个简单的解决方案是将最高位显式设置为零:
line[i] = (line[i] >> 1) & 0x7f;
这仍然意味着您只能使用字符集的下半部分,即值 <127。更好的解决方案是轮换 shift:
line[i] = (line[i] << 1) | (line[i] >> 7)&0x01;
编码和
line[i] = (line[i] >> 1)&0x7f |(line[i]<<7);
积分提升有一个微妙的问题(因为 char
没有 operator<<
,所以它被提升为 int
)和符号扩展。
考虑:
int main() {
char a = 127;
printf("%hhd\n", a);
char b = a << 1;
printf("%hhd\n", b);
char c = b >> 1;
printf("%hhd\n", c);
}
及其输出:
127
-2
-1
如您所见,原始值无法恢复。
修复是在 unsigned
space 中操作,这样就不会发生符号扩展:
int main() {
char a = 127;
printf("%hhd\n", a);
char b = static_cast<unsigned char>(a) << 1;
printf("%hhd\n", b);
char c = static_cast<unsigned char>(b) >> 1;
printf("%hhd\n", c);
}
正确输出:
127
-2
127
在这种特殊情况下,只需要 static_cast<unsigned char>(b) >> 1
即可解决此问题,但是,在执行移位时,应该了解整数提升和符号扩展。
没有投射:
char(254) >> 1 === int(-2) >> 1 === int(-1) === char(-1)
演员阵容:
unsigned char(254) >> 1 === int(254) >> 1 === int(127) === char(127)