C++读取文本文件:保留连字符与撇号过滤非字母字符
解决方案:保留指定符号的单词过滤
没问题,我来帮你搞定这个单词预处理的问题!你已经完成了转小写的步骤,接下来只需要添加一个过滤逻辑,保留字母、连字符(-)和撇号('),移除其他所有非目标字符就行。
核心思路
我们可以用C++标准库的std::erase + std::remove_if组合(这是处理容器元素移除的惯用手法),配合一个自定义的判断条件来筛选需要保留的字符。判断逻辑很简单:一个字符需要被保留,当且仅当它是字母,或者是连字符,或者是撇号。
修改后的完整代码
#include <algorithm> #include <cctype> #include <locale> // 用于std::isalpha的locale支持 void WordStats::ReadTxtFile() { std::ifstream ifile(Filename); if(!ifile) { std::cerr << "Error Opening file " << Filename << std::endl; exit(1); } for (std::string word; ifile >> word; ) { // 第一步:转小写 std::transform(word.begin(), word.end(), word.begin(), ::tolower); // 第二步:过滤非目标字符(保留字母、-、') word.erase( std::remove_if(word.begin(), word.end(), [](unsigned char c) { // 保留条件:是字母,或者是'-',或者是''' return !(std::isalpha(c, std::locale()) || c == '-' || c == '\''); } ), word.end() ); // 可选:如果处理后单词为空,跳过(比如原单词全是符号的情况) if (word.empty()) { continue; } // 后续逻辑不变 WordMap &Words = (Dictionary.count(word) ? KnownWords : UnknownWords); Words[word].push_back(ifile.tellg()); } std::cout << KnownWords.size() << " known words read." << std::endl; std::cout << UnknownWords.size() << " unknown words read." << std::endl; }
细节说明
- 字符判断的安全性:用
unsigned char转换后再传给std::isalpha,避免因char是有符号类型时,某些字符值(比如0x80以上)导致未定义行为。 - Locale支持:如果你的文本包含非英文的字母(比如法语、德语的特殊字母),
std::isalpha(c, std::locale())会比单纯的std::isalpha(c)更准确,它会遵循当前系统的语言环境来判断字母。如果只处理英文文本,也可以换成std::isalpha(c)。 - 空单词处理:添加了
if (word.empty()) continue;的判断,避免把处理后变成空字符串的“单词”加入到统计中,比如原单词是"!!??",过滤后为空,这种情况应该跳过。
这样处理后,你的单词预处理逻辑就完整啦!
内容的提问来源于stack exchange,提问作者muzzi
相关产品推荐
相关产品推荐

