【发布时间】:2015-08-07 00:08:28
【问题描述】:
我有一个由句子组成的文本语料库,每行一个。语料库是德文的,其中某些部分包含一些奇怪的字符。例如,当从终端使用less 命令查看时,以下是一些行:
w�hlen sie die zahlen aus,indem sie sie anklicken。西肯嫩 jede runde zwei bis zehn zahlen ausw�hlen.
keno xperiment ist eine erweiterte version vom keno lottery spiel.
nachdem sie ihre auswahl getroffen haben, klicken sie auf eine spielen, um die spielrunde zu starten, oder auf f�nf spielen, um mit den ausgew�hlten zahlen f�nf runden hintereinander zu spielen。
under dem hauptspielbereich finden sie eine reihe von buttons mit den zahlen 2 bis 10, au�erdem die zufallsauswahl und ein k�stchen mit der bezeichnung ‘vor jeder runde neue zahlen ausw�hlen’.
(“�”实际上只是带有元音变音的字符。令人惊讶的是,在某些行中,这些字符完美显示)
我想处理以删除包含这些损坏字符的行。代码如下:
#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <pthread.h>
#include <sstream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
using namespace std;
int lengthLowerBound = -1;
int requirePunct = 0;
unordered_map <string, string> specials;
// weird characters
#pragma warning( push)
#pragma warning( disable : 4101 )
bool isOK(char ch) {
if (ch == '�') return false;
return true;
}
#pragma warning( pop )
bool isOK(string &line) {
for (int i = 0; i < line.length(); ++i) {
if (line[i] == '�') return false;
}
return true;
}
// has punctuations
bool hasPunctuations(string &line) {
for (int i = 0; i < line.length(); ++i) {
if (ispunct(line[i])) return true;
}
return false;
}
int main(int argc, char *argv[]) {
if (argc < 5) {
cout << "Usage: ./Filter input1.txt input2.txt output1.txt output2.txt [hasPunctuation | noShorterThan x]" << endl;
exit(1);
}
string inpFile1 = string(argv[1]);
string inpFile2 = string(argv[2]);
string outFile1 = string(argv[3]);
string outFile2 = string(argv[4]);
for (int i = 5; i < argc; ++i) {
if (strcmp(argv[i], "hasPunctuation") == 0) requirePunct = 1;
else if (strcmp(argv[i], "noShorterThan") == 0) lengthLowerBound = atoi(argv[i+1]);
}
// filter
ifstream finp1(inpFile1, ifstream::in);
if (finp1.fail()) {
cout << " Can't open file " << inpFile1 << endl;
exit(1);
}
ifstream finp2(inpFile2, ifstream::in);
if (finp2.fail()) {
cout << " Can't open file " << inpFile2 << endl;
exit(1);
}
ofstream fout1(outFile1, ofstream::out);
if (fout1.fail()) {
cout << " Can't open file " << outFile1 << endl;
exit(1);
}
ofstream fout2(outFile2, ofstream::out);
if (fout2.fail()) {
cout << " Can't open file " << outFile2 << endl;
exit(1);
}
string line1, line2;
int numLines = 0;
cout << "# Start tokenizing" << endl;
while (getline(finp1, line1)) {
getline(finp2, line2);
if (line1.empty() || line2.empty()) continue;
if (!isOK(line1) || !isOK(line2)) continue;
if (lengthLowerBound > 0) {
if (line1.length() < lengthLowerBound || line2.length() < lengthLowerBound) continue;
}
if (requirePunct) {
if (!hasPunctuations(line1) || !hasPunctuations(line2)) continue;
}
fout1 << line1 << endl;
fout2 << line2 << endl;
++numLines;
if (numLines % 1000 == 0) cout << "\r Read " << numLines/1000 << "k lines.";
}
cout << endl;
cout << "# Done" << endl;
fout2.close();
fout1.close();
finp2.close();
finp1.close();
return 0;
}
如果您只是复制上面的代码并按照代码本身的指导使用适当的命令运行它,在给定的句子上,您会看到代码没有做任何事情。我怀疑这是因为比较 ch == '�' 总是错误的。实际上有一个警告。
所以,我的问题是如何做我想做的事?而且它不需要在 C++ 中。 Python、Perl 或 sed 命令,任何东西,都受到高度赞赏。谢谢。
TL;DR:我想处理一个文本文件以删除引用文本中的所有“�”字符。
【问题讨论】:
-
我很确定问题在于您正在像处理 ANSI 一样处理文本,而这些元音变音可能超出 ANSI 范围。阅读joelonsoftware.com/articles/Unicode.html,这是一本很棒的入门书。
-
在您的源代码中嵌入不寻常的字符可能不起作用。相反,您需要以另一种方式检查字符(例如,通过其整数代码或 unicode 代码)。
-
先用十六进制编辑器找到字符的代码点。
标签: c++ text special-characters