我问了一个类似的问题,但遗漏了一个重要细节。我正在对一组字符(cstring)进行一些文本处理。输入数组被复制到输出数组,除了某些字符被改变(例如a-> b)。这是通过使用switch语句完成的。我想要的是如果在一行中找到两个或多个特定字符,其中只有一个被复制到新数组(所以我不希望连续两个空格)。
这是我到目前为止所做的工作,但没有跳过某些字符中的两个或更多字符,这是有效的:
char cleanName[ent->d_namlen];
for(int i = 0; i < ent->d_namlen; i++)
{
switch(ent->d_name[i])
{
case 'a' :
cleanName[i] = 'b';//replace a's with b's (just an example)
break;
case ' ' ://fall through
case '-' :
case '–' :
case '—' :
cleanName[i] = '_';//replace spaces and dashes with spaces
break;
....//more case statments
default:
cleanName[i] = ent->d_name[i];
}
}
例如,如果一行中的两个字符被下划线替换,我该怎么做?我是否只会执行switch
声明if(ent->d_name[i] != previous || (ent->d_name[i] != '-' && ent->d_name[i] != '_' && ent->d_name[i] != ' ')
这可能更像是一个算法问题,而不是特定于实现的问题。
输入示例:abbc - d-e
输出:bbbc_d_e
(为简单起见,假设'a'映射到'b'但实际上不仅仅是这个)
答案 0 :(得分:2)
嗯,对于这类文本处理算法,我会使用状态机。
答案 1 :(得分:2)
最简单的方法是在现有转换后使用std::unique
自定义谓词:
cleanName.erase(std::unique(std::begin(cleanName), std::end(cleanName),
[](char c, char d) { return c == '_' && d == '_'; }), std::end(cleanName));
对于char
数组:
length = std::unique(cleanName, &cleanName[length],
[](char c, char d) { return c == '_' && d == '_'; }) - cleanName;
cleanName[length] = '\0';
答案 2 :(得分:0)
需要注意的一点是,对于索引的工作方式,您需要意识到cleanName的长度不一定与输入数组的长度相同。因此,您需要使用索引i。
答案 3 :(得分:0)
我的建议是将最后找到的字符保存在临时变量中。这样,如果出现,您可以忽略相同的字符。有两种方法可以做到这一点:
在切换之后添加while语句,其消耗的每个字符等于找到的最后一个字符。如果cstring有很多重复的字符,这很有用:
char cleanName[ent->d_namlen];
char parent;
for(int i = 0; i < ent->d_namlen; i++)
{
switch(ent->d_name[i])
{
case 'a' :
cleanName[i] = 'b';//replace a's with b's (just an example)
parent = ent->d_name[i];
break;
case ' ' ://fall through
case '-' :
case '–' :
case '—' :
cleanName[i] = '_';//replace spaces and dashes with spaces
parent = ent->d_name[i];
break;
....//more case statments
default:
cleanName[i] = ent->d_name[i];
}
while((parent == ent->d_name[i++]) && ent->d_name[i++] != NULL)
i++;
}
这里唯一的问题是,如果你有一系列不同的交错空格和破折号,它可能无法识别它并保留各种&#34; _&#34;。一种解决方案是保留父母的集合而不是单个字符。
另一种方法是在每次迭代中将当前字符与下一个字符进行比较。你保持&#34;父母&#34;变量,在每个开关的情况下,你将当前字符与父字符进行比较,如果它们相同,则不要将它添加到cleanName cstring。
答案 4 :(得分:0)
以下是unique_copy
算法和transform_iterator
from Boost的想法:
#include <boost/iterator/transform_iterator.hpp>
#include <iterator>
#include <iostream>
#include <string>
#include <algorithm>
char transform(char c)
{
switch(c) {
case 'a' :
return 'b';
case ' ' :
case '-' :
case '–' :
case '—' :
return '_';
default:
return c;
}
}
int main()
{
std::string in = "abbc--d-e";
std::string out;
std::unique_copy(
boost::make_transform_iterator(in.begin(), transform),
boost::make_transform_iterator(in.end(), transform),
std::back_inserter(out),
[](char c1, char c2){ return c1 == '_' && c2 == '_'; });
std::cout << out; // bbbc_d_e
}