奇怪,为什么我这样得不到正确的结果呢?

时间:2021-05-23 20:05:11
程序是这样的:

#include <iostream>
#include <fstream>
#include <string>
#include <cassert>

using namespace std;

int main()
{
//-------读取密码并加密转换
string OriginFileName="原始密码.txt";

ifstream OriginStream(OriginFileName.data(),ios::in);
assert(OriginStream.is_open()); //判断是否读到文件

char inPassword_ch=0; //保存原始的密码字符
char temp_ch;
string outTempPW_str("00000000"); //保存加密后的密码字符串

for(int i=0;i<8;i++)
{
OriginStream>>inPassword_ch; //从文件中读取8个密码字符

switch(i)  //对每个字符进行简单的加密测试
{
case 0:
temp_ch=inPassword_ch+'s';
break;
case 1:
temp_ch=inPassword_ch+'2';
break;
case 2:
temp_ch=inPassword_ch+'n';
break;
case 3:
temp_ch=inPassword_ch+'u';
break;
case 4:
temp_ch=inPassword_ch+'i';
break;
case 5:
temp_ch=inPassword_ch+'e';
break;
case 6:
temp_ch=inPassword_ch+'2';
break;
case 7:
temp_ch=inPassword_ch+'s';
break;
default:
break;
}
outTempPW_str[i]=temp_ch;
}
OriginStream.close(); //关闭与原始密码文件联系


//------输出加密后的密码文件
string outTempFileName="加密后文件.txt";
         ofstream outTempStream(outTempFileName.data(),ios::out);//app
assert(outTempStream.is_open()); //判断是否打开文件
outTempStream<<outTempPW_str<<endl;
outTempStream.close();


//------读取加密后的文件并解密
string inTempFileName=outTempFileName;
ifstream inTempStream(inTempFileName.data(),ios::in);
assert(inTempStream.is_open()); //判断是否读到文件

string outPW_str("00000000"); //保存最后解密的密码串

for(int i2=0;i2<8;i2++)
{
inTempStream>>inPassword_ch; //从文件中读取密文

switch(i2) //解密
{
case 0:
temp_ch=inPassword_ch-'s';
break;
case 1:
temp_ch=inPassword_ch-'2';
break;
case 2:
temp_ch=inPassword_ch-'n';
break;
case 3:
temp_ch=inPassword_ch-'u';
break;
case 4:
temp_ch=inPassword_ch-'i';
break;
case 5:
temp_ch=inPassword_ch-'e';
break;
case 6:
temp_ch=inPassword_ch-'2';
break;
case 7:
temp_ch=inPassword_ch-'s';
break;
default:
break;
}
outPW_str[i2]=temp_ch;
}

inTempStream.close(); //关闭读取文件联系


//-----输出解密后的密码文件
string outFileName="解密后文件.txt";
ofstream outStream(outFileName.data(),ios::out);//app
assert(outStream.is_open()); //判断是否打开文件
outStream<<outPW_str<<endl;
outStream.close();


system("pause");
return 0;
}


----------
我在文件“原始密码.txt”中输入11111111,在“解密后文件.txt”却得不到密码值11111111
不知道为什么呢?难道是输入输出缓冲问题?还是回车符问题呢?
在哪里修改呢?
谢谢!一直没有发现原因,汗。。

23 个解决方案

#1


文件名的原因, 该用英文字母的文件名吧:)

#2


#3


文件名的原因, 该用英文字母的文件名吧:)

--------
我改成:
原始密码.txt  -> Origin.txt
加密后文件.txt ->Temp.txt
解密后文件.txt -> End.txt
也得不出正确得结果

比如Origin.txt里输入为: 00000000
得到得End.txt显示结果和用中文文件名相同,均为8个相同的乱码符

应该不是文件名的原因吧

#4


你在什么编译器下编译运行的?
debug or release?
你确认你打开了Origin.txt吗?

#5


assert(outTempStream.is_open());//判断是否打开文件
在NDEBUG(release)下是不会给你任何信息的:)

#6


确认打开了
VC++6.0
DEbug

谢谢

#7


在我的VC6下没问题

#8


晕,楼上的确定肯定以及一定吗,有做过什么设置吗?
直接全部拷贝这些编译运行的?

#9


把后面的outStream<<outPW_str<<endl;   
改成:
for(int j=0;j<8;j++)
      outStream<<outPW_str[j]<<endl;
就好了。和文件名字没有关系

#10


mark

#11


把后面的outStream<<outPW_str<<endl;   
改成:
for(int j=0;j<8;j++)
      outStream<<outPW_str[j]<<endl;
就好了。和文件名字没有关系

---
应该也不是这个问题,因为改了之后结果仍然不对。。。:(
你的这样改后就正常了?

#12


我改了之后就对了,一定要注意程序的文件路径,别写错了!

#13


mark

#14


程序的文件路径?
我的几个txt文件都是放在同一个工程文件下的,应该没有问题啊吧
即使把txt文件放在debug目录下,然后运行debug里的exe文件,结果也是不对的
解密后的前几个字符很奇怪,后面的几个却正常

#15


字符取值逾界:
    switch(i2) //解密
      {
      case 0:
        temp_ch=inPassword_ch-'s'+256;
        break;
      case 1:
        temp_ch=inPassword_ch-'2'+256;
        break;
      case 2:
        temp_ch=inPassword_ch-'n'+256;
        break;
      case 3:
        temp_ch=inPassword_ch-'u'+256;
        break;
      case 4:
        temp_ch=inPassword_ch-'i'+256;
        break;
      case 5:
        temp_ch=inPassword_ch-'e'+256;
        break;
      case 6:
        temp_ch=inPassword_ch-'2'+256;
        break;
      case 7:
        temp_ch=inPassword_ch-'s'+256;
        break;
      }
    outPW_str[i2]=temp_ch;
如是即可。

#16


另外,你使用outTempStream<<outTempPW_str<<endl;方式保存加密文件是不安全的,如果加密后的字符存在与256(即字符0)相等的情况,就会出现文件截断现象,建议使用二进制流方式保存密文。

#17


回FreeFice(庄鱼) :

即使加了“+256“也还是不行,
比如文件Origin.txt内容是:11111111
则加密后文件.txt的内容为:r0焨歟cs
而解密后的文件.txt内容为一个实心方块
奇怪,为什么呢?

另外发现即使加解密过程不加减字符,即如下:
加密:
{
case 0:
temp_ch=inPassword_ch;//+'s';
break;
case 1:
temp_ch=inPassword_ch;//+'2';
break;
case 2:
temp_ch=inPassword_ch;//+'n';
break;
case 3:
temp_ch=inPassword_ch;//+'u';
break;
case 4:
temp_ch=inPassword_ch;//+'i';
break;
case 5:
temp_ch=inPassword_ch;//+'e';
break;
case 6:
temp_ch=inPassword_ch;//+'2';
break;
case 7:
temp_ch=inPassword_ch;//+'s';
break;
default:
break;
}
outTempPW_str[i]=temp_ch;

解密:
{
      case 0:
        temp_ch=inPassword_ch;//-'s'+256;
        break;
      case 1:
        temp_ch=inPassword_ch;//-'2'+256;
        break;
      case 2:
        temp_ch=inPassword_ch;//-'n'+256;
        break;
      case 3:
        temp_ch=inPassword_ch;//-'u'+256;
        break;
      case 4:
        temp_ch=inPassword_ch;//-'i'+256;
        break;
      case 5:
        temp_ch=inPassword_ch;//-'e'+256;
        break;
      case 6:
        temp_ch=inPassword_ch;//-'2'+256;
        break;
      case 7:
        temp_ch=inPassword_ch;//-'s'+256;
        break;
      }
    outPW_str[i2]=temp_ch;

结果却是这样的:

Origin.txt内容是:11111111
则加密后文件.txt的内容为一个实心方块
而解密后的文件.txt内容为四个实心方块
奇怪,为什么呢?

#18


查查你的文件是不是Unicode编码, 若是, 用wordpad另存为
非Unicode的文本文档再试试?

检查你的测试文件是否Unicode编码方法: 用wordpad(写字板)打开文件, 然后点"文件|另存为",
如果在"保存类型"框中显示为"Unicode文本文档", 则该文件是Unicode.

#19


如lightnut() 所说。
UNICODE的字符型变量相当于两个字节长度(而不是ANSI字符型变量的一个字节长度),也就是单字节与双字节的区别。我尝试将原程序代码做如下修改:

char inPassword_ch=0;//保存原始的密码字符
char temp_ch;
string outTempPW_str("00000000");//保存加密后的密码字符串

->转换成

wchar_t inPassword_ch=0;//保存原始的密码字符
wchar_t temp_ch;
wchar_t outTempPW_str[]=L"00000000";

string outPW_str("00000000");//保存最后解密的密码串
->转换成
wchar_t outPW_str[]=L"00000000";

就是用宽字符的wchar_t取代单字节的char,其他部分代码保持不变。但读取用Unicode编码创建的Origin.txt文档(内容为11111111)时,得到的结果却为:
加密后文件.txt:0012FEB8 
解密后文件.txt:0012FD64
//貌似地址

不正确。此时读取的字符已经放到wchar_t字节里了,却还是不正确。请教这是为什么呢?

#20


看这个:
http://www.codeproject.com/vcpp/stl/upgradingstlappstounicode.asp

#21


这个是上面文章的翻译:
http://dozb.bokee.com/1655050.html

#22


应该不在程序上了,你换成2进制格式看看。如果还有问题,可以考虑换个编译器或者调整一下编译参数

#23


ok.感谢各位的热情回复,结贴

#1


文件名的原因, 该用英文字母的文件名吧:)

#2


#3


文件名的原因, 该用英文字母的文件名吧:)

--------
我改成:
原始密码.txt  -> Origin.txt
加密后文件.txt ->Temp.txt
解密后文件.txt -> End.txt
也得不出正确得结果

比如Origin.txt里输入为: 00000000
得到得End.txt显示结果和用中文文件名相同,均为8个相同的乱码符

应该不是文件名的原因吧

#4


你在什么编译器下编译运行的?
debug or release?
你确认你打开了Origin.txt吗?

#5


assert(outTempStream.is_open());//判断是否打开文件
在NDEBUG(release)下是不会给你任何信息的:)

#6


确认打开了
VC++6.0
DEbug

谢谢

#7


在我的VC6下没问题

#8


晕,楼上的确定肯定以及一定吗,有做过什么设置吗?
直接全部拷贝这些编译运行的?

#9


把后面的outStream<<outPW_str<<endl;   
改成:
for(int j=0;j<8;j++)
      outStream<<outPW_str[j]<<endl;
就好了。和文件名字没有关系

#10


mark

#11


把后面的outStream<<outPW_str<<endl;   
改成:
for(int j=0;j<8;j++)
      outStream<<outPW_str[j]<<endl;
就好了。和文件名字没有关系

---
应该也不是这个问题,因为改了之后结果仍然不对。。。:(
你的这样改后就正常了?

#12


我改了之后就对了,一定要注意程序的文件路径,别写错了!

#13


mark

#14


程序的文件路径?
我的几个txt文件都是放在同一个工程文件下的,应该没有问题啊吧
即使把txt文件放在debug目录下,然后运行debug里的exe文件,结果也是不对的
解密后的前几个字符很奇怪,后面的几个却正常

#15


字符取值逾界:
    switch(i2) //解密
      {
      case 0:
        temp_ch=inPassword_ch-'s'+256;
        break;
      case 1:
        temp_ch=inPassword_ch-'2'+256;
        break;
      case 2:
        temp_ch=inPassword_ch-'n'+256;
        break;
      case 3:
        temp_ch=inPassword_ch-'u'+256;
        break;
      case 4:
        temp_ch=inPassword_ch-'i'+256;
        break;
      case 5:
        temp_ch=inPassword_ch-'e'+256;
        break;
      case 6:
        temp_ch=inPassword_ch-'2'+256;
        break;
      case 7:
        temp_ch=inPassword_ch-'s'+256;
        break;
      }
    outPW_str[i2]=temp_ch;
如是即可。

#16


另外,你使用outTempStream<<outTempPW_str<<endl;方式保存加密文件是不安全的,如果加密后的字符存在与256(即字符0)相等的情况,就会出现文件截断现象,建议使用二进制流方式保存密文。

#17


回FreeFice(庄鱼) :

即使加了“+256“也还是不行,
比如文件Origin.txt内容是:11111111
则加密后文件.txt的内容为:r0焨歟cs
而解密后的文件.txt内容为一个实心方块
奇怪,为什么呢?

另外发现即使加解密过程不加减字符,即如下:
加密:
{
case 0:
temp_ch=inPassword_ch;//+'s';
break;
case 1:
temp_ch=inPassword_ch;//+'2';
break;
case 2:
temp_ch=inPassword_ch;//+'n';
break;
case 3:
temp_ch=inPassword_ch;//+'u';
break;
case 4:
temp_ch=inPassword_ch;//+'i';
break;
case 5:
temp_ch=inPassword_ch;//+'e';
break;
case 6:
temp_ch=inPassword_ch;//+'2';
break;
case 7:
temp_ch=inPassword_ch;//+'s';
break;
default:
break;
}
outTempPW_str[i]=temp_ch;

解密:
{
      case 0:
        temp_ch=inPassword_ch;//-'s'+256;
        break;
      case 1:
        temp_ch=inPassword_ch;//-'2'+256;
        break;
      case 2:
        temp_ch=inPassword_ch;//-'n'+256;
        break;
      case 3:
        temp_ch=inPassword_ch;//-'u'+256;
        break;
      case 4:
        temp_ch=inPassword_ch;//-'i'+256;
        break;
      case 5:
        temp_ch=inPassword_ch;//-'e'+256;
        break;
      case 6:
        temp_ch=inPassword_ch;//-'2'+256;
        break;
      case 7:
        temp_ch=inPassword_ch;//-'s'+256;
        break;
      }
    outPW_str[i2]=temp_ch;

结果却是这样的:

Origin.txt内容是:11111111
则加密后文件.txt的内容为一个实心方块
而解密后的文件.txt内容为四个实心方块
奇怪,为什么呢?

#18


查查你的文件是不是Unicode编码, 若是, 用wordpad另存为
非Unicode的文本文档再试试?

检查你的测试文件是否Unicode编码方法: 用wordpad(写字板)打开文件, 然后点"文件|另存为",
如果在"保存类型"框中显示为"Unicode文本文档", 则该文件是Unicode.

#19


如lightnut() 所说。
UNICODE的字符型变量相当于两个字节长度(而不是ANSI字符型变量的一个字节长度),也就是单字节与双字节的区别。我尝试将原程序代码做如下修改:

char inPassword_ch=0;//保存原始的密码字符
char temp_ch;
string outTempPW_str("00000000");//保存加密后的密码字符串

->转换成

wchar_t inPassword_ch=0;//保存原始的密码字符
wchar_t temp_ch;
wchar_t outTempPW_str[]=L"00000000";

string outPW_str("00000000");//保存最后解密的密码串
->转换成
wchar_t outPW_str[]=L"00000000";

就是用宽字符的wchar_t取代单字节的char,其他部分代码保持不变。但读取用Unicode编码创建的Origin.txt文档(内容为11111111)时,得到的结果却为:
加密后文件.txt:0012FEB8 
解密后文件.txt:0012FD64
//貌似地址

不正确。此时读取的字符已经放到wchar_t字节里了,却还是不正确。请教这是为什么呢?

#20


看这个:
http://www.codeproject.com/vcpp/stl/upgradingstlappstounicode.asp

#21


这个是上面文章的翻译:
http://dozb.bokee.com/1655050.html

#22


应该不在程序上了,你换成2进制格式看看。如果还有问题,可以考虑换个编译器或者调整一下编译参数

#23


ok.感谢各位的热情回复,结贴