【问题标题】:String search/ indexing in a file using C++使用 C++ 在文件中进行字符串搜索/索引
【发布时间】:2013-10-10 03:22:18
【问题描述】:

我正在使用以下代码来搜索文件并提供数据和相关的行号。但是这个代码在几十万行的情况下是否足够快?我的电脑确实冻结了几秒钟。我需要搜索整数对并在逗号后返回其 RHS 值(一些统计数据),但使用以下代码我可以返回整行。

  1. 使用split 函数解析返回的数据并获取我的 RHS 值是否是一个好主意

  1. 根据 LHS 参数直接获取 RHS 值。 (好吧,我无法做到这一点)

任何人都可以帮助我实现上述两个中的任何一个吗?

这是我的代码:

#include <string>
#include <iostream>
#include <fstream>

    int main()
    {
        std::ifstream file( "index_hyper.txt" ) ;
        std::string search_str = "401" ;
        std::string line ;
        int line_number = 0 ;
        while( std::getline( file, line ) )
        {
            ++line_number ;
            if( line.find(search_str) != std::string::npos )
                std::cout << "line " << line_number << ": " << line << '\n' ;
        }
    }

这是我index_hyper.txt文件的内容:

18,22
20,37
151,61
200,62
156,63
158,64
159,65
153,66
156,67
152,68
154,69
155,56
156,14
157,13
160,122
161,1333
400,455
401,779
402,74
406,71

【问题讨论】:

  • 什么是 RHS 和 LHS ?什么输入你想要什么输出?
  • 此文件的代码冻结了您的计算机?我对此感到惊讶。确定不是病毒检查器?
  • RHS 是右手边,LHS 是 ...
  • @user2754070 啊,没那么大,是其他原因造成的。见this
  • 1.7MB? grep 会非常快地解析该文件,无需编写程序来执行此操作

标签: c++ string search


【解决方案1】:

您可以使用以下代码完成上述代码的工作:

grep -n "^401," index_hyper.txt

如果您只想输出 RHS,您可以:

grep  "^401," index_hyper.txt | sed "s/[^,]*,//"

如果您在没有 sed、grep、bash 等的 Windows 平台上,那么您可以通过安装 cygwin 轻松访问 unix 工具。

【讨论】:

  • 这和C++有什么关系?
  • @P0W,不是。它与问题规范有关。
  • 为什么不简单地sed -n 's:/^401,//p' index_hyper.txt?这可能至少和他能写的任何东西一样快。但据推测,在现实生活中,他想检测语法错误,并在这种情况下向标准错误输出消息。 (否则,既然已经有了这么简单的解决方案,为什么还要担心 C++?)
  • @JamesKanze,感谢您的简化。为什么选择 C++?好吧,这个问题并没有说明为什么是 C++。如果没有给出原因,假设没有原因是合理的。 “如果你只有一把锤子,那么一切看起来都像钉子。”
  • @AdamBurry :-)。是的。由于他提到了他的“PC”,因此很可能他正在运行 Windows。在这种情况下,他可能除了 C++ 之外没有太多其他东西。 (我承认,即使有错误检查等,如果我不能用 shell 工具完成它,我会敲掉一个 Python 脚本。为这么小的东西启动编译器是没有意义的。)
【解决方案2】:

作为一般规则,不要开始将字符串分解为 较小的部分(子字符串),直到您需要为止。然后开始 准确指定想要的内容:您说的是 RHS 和 LHS,并且 谈论“根据 LHS 参数获取 RHS 值”。所以:你想要吗 第一个字段完全匹配,子字符串匹配 第一个字段,还是整行的子字符串匹配?

无论如何:一旦你有line 的线路,你就可以轻松地 将其分为两个字段:

std::string::const_iterator pivot = std::find( line.cbegin(), line.cend(), ',' );

然后你做什么取决于你的标准是什么:

if ( pivot - line.cbegin() == search_str.size() &&
        std::equal( line.cbegin(), pivot, search_str.begin() ) ) {
    //  Exact match on first field...
    std::cout << std::string( std::next( pivot ), line.cend() );
}

if ( std::search( line.cbegin(), pivot, search_str.begin(), search_str.end() ) != pivot ) {
    //  Matches substring in first field...
    std::cout << std::string( std::next( pivot ), line.cend() );
}

if ( std::search( line.cbegin(), line.cend(), search_str.begin(), search_str.end() ) != line.cend() ) {
    //  Matches substring in complete line...
    std::cout << std::string( std::next( pivot ), line.end() ); }
}

当然,您需要进行一些额外的错误检查。什么 例如,如果行中没有逗号(例如pivot == line.end()),您应该怎么做?或者在 线。 (你的例子看起来像数字。应该 "401" 匹配 只有"401",还是"+401"?)

在继续之前,您应该非常仔细地指定 对于所有可能的输入,代码应该做什么。 (为了 最可能的输入,当然,答案可能是: 将带有行号的错误消息输出到std::cerr 和 继续。在这种情况下一定要返回EXIT_FAILURE。)

【讨论】:

  • 太棒了! James 将其一个值作为输入,并将其关联的 RHS 作为输出,还有一件事是任何/所有输入值都是唯一的。你能把它放在我的代码中吗,即使我包含algorithm.h,我也会遇到很多错误
  • 什么样的错误?除了一个明显的错字,我遇到的唯一问题是编译器无法实例化std::equals,因为pivotconst_iterator,但line.begin() 是非常量。您可以通过多种方式纠正此问题:在 C++11 中,要么使 pivot auto(因此它将是一个非常量迭代器),要么在 line 的任何地方使用 cbegin()cend(),一次你已经读过了。在 C++11 之前,最简单的方法是将 pivot 声明为非常量迭代器(或者由于您将多次使用 line.begin(),您可以将其保存在 const_iterator 中,然后使用它.
  • 我已经编辑回答以反映必要的修复,以便它编译和工作(对我来说)。
  • 谢谢!我在 Linux Env​​ 上并使用 NetBeans IDE,我认为 std::next 已包含在 iterator.h 中,我已将其包含在内,但仍然 - unable to resolve identifier 'next'
  • 我有 2 个错误:Error-1: main.cpp:25: error: no matching function for call to ‘equal(__gnu_cxx::__normal_iterator&lt;char*, std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;, __gnu_cxx::__normal_iterator&lt;const char*, std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;&amp;, __gnu_cxx::__normal_iterator&lt;char*, std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;)’ Error-2: main.cpp:28: error: ‘next’ is not a member of ‘std’
猜你喜欢
  • 2021-04-15
  • 2011-01-12
  • 2011-01-31
  • 2021-11-14
  • 2020-09-27
  • 1970-01-01
  • 2010-12-10
  • 1970-01-01
  • 2013-08-09
相关资源
最近更新 更多