【问题标题】:Boost: How to locate the position of the iterator inside a huge text file?Boost:如何在一个巨大的文本文件中定位迭代器的位置?
【发布时间】:2011-03-15 18:35:37
【问题描述】:

我正在一个程序中工作,该程序使用 boost::regex 来匹配一个巨大的文本文件(大于 200 MB)中的一些模式。匹配工作正常,但要构建输出文件,我需要按照在文本中找到的顺序对匹配(只有 2 个,但在所有文本上)进行排序。 好吧,在调试模式下,在 cout 过程中,我可以在迭代器 it1 内部看到一个 m_base 属性,该属性显示了循环的每一步都增加的地址,我认为这个 m_base 地址是文本中匹配模式的地址,但我无法证明它,也找不到访问此属性以存储地址的方法。 不知道有没有什么办法可以检索到文本中每个匹配模式的地址,但是我确实需要获取这些信息。

#define FILENAME "File.txt"
int main() { 

    int length;     
    char * cMainBuf;
    ifstream is;
    is.open (FILENAME, ios::binary );

    is.seekg(0, ios::end);
    length = is.tellg();
    is.seekg (0, ios::beg);

    cMainBuf = new char[length+1];
    memset(cMainBuf, '\0',length+1);

    is.read(cMainBuf,length);
    is.close();
    string str=cMainBuf;
    regex reg("^(\\d{1,3}\\s[A-F]{99})");
    regex rReg(reg);
    int const sub_matches[] = { 1 };
    boost::sregex_token_iterator it1(str.begin() ,str.end() ,rReg ,sub_matches ), it2; 
    while(it1!=it2) 
    { 
        cout<<"#"<<sz++<<"- "<< *(it1++) << endl;
    }
    return 0;
}

@sln 你好, 我会回答你的问题: 1. 我删除了所有不属于这个问题的代码,所以一些库仍然存在; 2.同1; 3. 因为该文件实际上不是一个简单的文本文件,它可以有任何符号,可能会影响阅读过程,我以前也意识到过; 4. 测试期间需要零缓冲区,因为我不能在缓冲区中存储超过 1MB 的空间; 5.迭代器不允许使用char*来设置文件的开头和结尾,所以需要将其改为字符串; 6. 传入的RegEx不会被声明为静态的,这只是一个草稿来显示问题和anchor的行为来寻找行开始,而不仅仅是字符串开始; 7. sub_matches 是测试的一部分,用于查看包含 2 个或更多组的正则表达式的迭代器在哪里; 8. sz 只是一个计数器; 9. 不能从 const std::_String_const_iterator<_elem> 转换为 long。

实际上所有代码都可以正常工作,我可以识别文本中的任何模式,但我真正需要知道的是每个匹配模式的内存地址(在这种情况下,是每次迭代的迭代器的地址)。我可以意识到 m_base 有这个地址,但是直到此刻我才能检索到这个地址。 我会继续分析,如果我找到任何解决这个问题的方法,我会在这里发布。

【问题讨论】:

    标签: regex boost text iterator


    【解决方案1】:

    编辑 @Tchesko,我正在删除我原来的答案。我已经加载了 boost::regex 并使用 regex_search() 进行了尝试。它不是你正在做的 itr1 方法,但我认为它归结为只是从 boost::smatch 类中获取结果,这实际上是 boost::match_results()。

    它有成员函数来获取匹配和子匹配的位置和长度。所以,它真的是你需要找到你的大字符串的偏移量。无法访问 m_base 的原因是它是一个私有成员变量。

    使用方法 position() 和 length()。请参阅下面的示例...我运行、调试和测试。我又恢复了使用 VS-2005 的速度。但是,boost 似乎有点古怪。如果我要使用它,我希望它做 Unicode,而不是意味着我必须编译 ICU。我正在使用的 boost 二进制文件是 1.44 下载的。最新的是 1.46.1,所以在我用 ICU 评估它的可行性后,我可能会用 vc++ 8 构建它。

    嘿,让我知道结果如何。祝你好运!

    #include <boost/regex.hpp> 
    #include <locale> 
    #include <iostream> 
    
    using namespace std;
    
    int main() 
    { 
      std::locale::global(std::locale("German")); 
      std::string s = "  Boris  Schäling   "; 
      boost::regex expr("(\\w+)\\s*(\\w+)"); 
      boost::smatch what; 
      if (boost::regex_search(s, what, expr)) 
      { 
          // These are from boost::match_results() class ..
          int Smpos0 = what.position();
          int Smlen0 = what.length();
          int Smpos1 = what.position(1);
          int Smlen1 = what.length(1);
          int Smpos2 = what.position(2);
          int Smlen2 = what.length(2);
    
          printf ("Match Results\n--------------\n");
          printf ("match  start/end  = %d - %d,  length = %d\n", Smpos0, Smpos0 + Smlen0,  Smlen0);
          std::cout << "  '" << what[0] << "'\n" << std::endl; 
          printf ("group1 start/end  = %d - %d,  length = %d\n", Smpos1, Smpos1 + Smlen1, Smlen1);
          std::cout << "  '" << what[1] << "'\n" << std::endl; 
          printf ("group2 start/end  = %d - %d,  length = %d\n", Smpos2, Smpos2 + Smlen2, Smlen2);
          std::cout << "  '" << what[2] << "'\n" << std::endl;
    
    /*
        This is the hard way, still m_base is a private member variable.
        Without m_base, you can't get the root address of the buffer.
    
        long Match_start = (long)(what[0].first._Myptr);
        long Match_end   = (long)(what[0].second._Myptr);
        long Grp1_start  = (long)(what[1].first._Myptr);
        long Grp1_end    = (long)(what[1].second._Myptr);
    */
      } 
    } 
    
    /* Output:
    Match Results
    --------------
    match  start/end  = 2 - 17,  length = 15
      'Boris  Schäling'
    
    group1 start/end  = 2 - 7,  length = 5
      'Boris'
    
    group2 start/end  = 9 - 17,  length = 8
      'Schäling'
    */
    

    【讨论】:

    • 我在我的问题中添加了一些与您的建议相关的 cmets(在代码 sn-p 下方编辑)。
    • 好消息,我终于可以使用 &(*it1->first) 来识别缓冲区中的地址,现在它工作正常了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-04
    • 2014-10-29
    • 2019-12-27
    相关资源
    最近更新 更多