在字符串中搜索通配符年份 C++

Search a string for a wildcard year C++

我正在遍历一个文本文件,将每个段落读入一个字符串。我想处理任何包含年份的段落,但如果没有找到年份,那么我想继续遍历文件。当找到年份时,我想知道找到该年份的索引。

为简单起见,我试图避免任何提升或正则表达式代码。为简单起见,我还假设唯一感兴趣的年份是 1900 年代和 2000 年代。我尝试了以下代码,但由于某种原因通配符不起作用。是因为通配符对数字不起作用吗?

string sParagraph = "Aramal et al. (2011), Title";
int iIndex;

if (sParagraph.find("19??")!=string::npos)
    iIndex = sParagraph.find("19??");
else if (sParagraph.find("20??")!=string::npos)
    iIndex = sParagraph.find("20??");
else
    continue;

编辑:我刚刚重读了这个问题,发现这个答案可能太无关紧要了。对不起,如果是的话。

几天前我在找类似的东西。我的方法可能非常(非常非常)低效:我遍历整个字符串并使用 'atoi()' 来查看每组四个字符是否是一年。

for (int i = 0; i < txt.length() - 3; i++)
{
    string t = txt.substr(i, 4); //Take a group of four characters.

    int year = atoi((char*)t.c_str());

    if (year > 1800 && year < 3000)
    {
        break;
    }
    else year = 0;
}

最后,'year' 为零或实际年份。

如果不使用正则表达式或增强代码,您可能会使您的代码更具可读性,但不会更简单。

一个"simple"单遍伪算法:

map<int, std::vector<int>> years;
String par = " ... "

//inefficient but didn't want to have to add more complicated code
//in the while loop. Just want to solution to be clear
int par_index = par.find_first_of("19"); 
if(par_index == string::npos) 
    par_index = par.find_first_of("20");
if(par_index == string::npos)
    //skip //No years in this paragraph

while(par_index < par.size()) {
    string year(par, par_index, 4);
    int year = atoi(year.c_str());  //or use C++11 stoi
    if(2100 < year && year >= 1900)
        years.at(year).push_back(par_index);
    par_index += 4;
}

这将创建一个映射,其中键是年份,值是一个整数向量,表示年份登陆的索引。

所以你当然可以这样做。但它不会更简单,它会更复杂。

无论如何,这可能是您最好的非正则表达式解决方案。它使用 string::iterator 而不是位置:

string sParagraph = "Aramal et al. (2011), Title";
auto iIndex = adjacent_find(sParagraph.begin(), sParagraph.end(), [](char i, char j){return i == '1' && j == '9' || i == '2' && j == '0'; });
const auto end = next(sParagraph.end(), -3);

while (iIndex < end && (isdigit(static_cast<int>(*next(iIndex, 2))) == false || isdigit(static_cast<int>(*next(iIndex, 3))) == false)){
    iIndex = adjacent_find(next(iIndex, 4), sParagraph.end(), [](char i, char j){return i == '1' && j == '9' || i == '2' && j == '0'; });
}

要使用它,您需要检查是否已迭代到 end:

if(iIndex < end){
    continue;
}

为了比较,可以用regex_search判断年份是否存在:

string sParagraph = "Aramal et al. (2011), Title";
smatch iIndex;

if (!regex_search(sParagraph, iIndex, regex("(?:19|20)\d{2}"))){
    continue;
}

一个 smatch 包含更多的信息和一个位置,但是如果你想要年初的索引,你可以这样做:iIndex.position()

不熟悉 C++11 特性的人常犯的错误是:"I don't understand how to use this stuff, it must be more complicated than what I already know." 然后回到他们已经知道的地方。不要犯那个错误,使用 regex_search.