【发布时间】:2019-10-27 05:33:44
【问题描述】:
所以,当我遇到异常行为时,我正在编写一个用于静态密码分析的程序。
首先,我写了字符计数器,这就是问题出现的地方。
我有文件:
//alphabet.txt
abcdefghijklmnopqrstuvwxyz
当我尝试计算字母频率时,得到了一些有趣的结果! (不要关注第一行,它只是说ifstream是打开的)
D:\Workspaces\EclipseWS\StaticAnalysis\src>g++ main.cpp
D:\Workspaces\EclipseWS\StaticAnalysis\src>a.exe
1!
a 1
b 1
c 1
d 1
e 1
f 1
g 1
h 1
i 1
j 1
k 1
l 1
m 1
n 1
o 1
p 1
q 1
r 1
s 1
t 1
u 1
v 1
w 1
x 1
y 1
z 2
如您所见,程序说“z”在文本中出现了 2 次,但实际上没有。
现在,技术细节。
Operating System: Windows 10 Enterprise LTSC
System Type: 64bit
C++ compiler: MinGW
alphabet.txt File encoding: ANSI
代码,我解析了文件:
#include <fstream>
#include <iostream>
#include <map>
#include <string>
using namespace std;
#define encrypted_fname "D:\\Workspaces\\EclipseWS\\StaticAnalysis\\src\\alphabet.txt"
void printMap(const map<char,int>& m){
for (const auto& p : m){
cout<<p.first<<'\t'<<p.second<<endl;
}
}
int main(){
ifstream ifs(encrypted_fname);
cout << ifs.is_open() << "!\n";
map<char,int> letterCount;
char buffer;
while(ifs){
ifs >> buffer;
letterCount[buffer]+=1;
}
printMap(letterCount);
}
我尝试将文件编码更改为 UTF-8
1!
» 1
¿ 1
ï 1
a 1
b 1
c 1
d 1
e 1
f 1
g 1
h 1
i 1
j 1
k 1
l 1
m 1
n 1
o 1
p 1
q 1
r 1
s 1
t 1
u 1
v 1
w 1
x 1
y 1
z 2
..Unicode 大端\unicode..
1!
þ 1
ÿ 1
28
a 1
b 1
c 1
d 1
e 1
f 1
g 1
h 1
i 1
j 1
k 1
l 1
m 1
n 1
o 1
p 1
q 1
r 1
s 1
t 1
u 1
v 1
w 1
x 1
y 1
z 1
但是正如你所看到的,在每种情况下输出都有点蹩脚!
如果您需要,我可以提供更多信息,请告诉我如何获取。
我的主要问题是:为什么会这样?我的代码有错误吗?如何解决?
【问题讨论】:
-
旁注:
char buffer已签名(对于 127 以上的任何字符为负数)。将其用作数组的索引时要小心。 -
而且我相信
ifstream将打开您的文件以作为 ascii(每个字符 1 个字节)读取,无论您的文件设置为什么编码。只是如果您更改文件编码,那么一些附加信息将(隐式)添加到该文件中,然后当您使用ifstream阅读时,这些信息将显示为“奇怪的字符”。 -
您的问题与以下事实有关,我认为,
while(ifs)在达到EOF字符时为真,但随后ifs >> buffer实际上并没有将其加载到buffer中,这仍然保持其最后一个值(恰好是z)。有关详细信息,请参阅this answer。 -
^^^ iow。将您的 while-condition 更改为
while (ifs >> buffer)并从循环本身中删除ifs >> buffer。 -
@goodvibration "
char bufferis signed" - 这取决于编译器的实现。char可以签名或不签名。
标签: c++ unicode encoding utf-8 ansi