在文件中搜索字符串(逐行),忽略单词之间空白的大小



我是c++的初学者,所以请理解…

我想在文件(haystack)中搜索字符串(指针),方法是分别读取每行,然后在该行中搜索指针。然而,理想情况下,对于更健壮的代码,我希望能够只读取一行中的单个单词,这样,如果单词之间有较大的(即多个)空白,则在搜索指针时忽略它们。(例如可能使用>>操作符??)也就是说,指针字符串不必完全匹配文件中单词之间的空间大小。

例如,如果我有一个针:

"The quick brown fox jumps over the lazy dog" 

在文件中,这可能被写为(在特定的行上):

... "The quick brown      fox jumps over the        lazy dog" ...

是否有有效的方法来做到这一点?

目前我包括必要数量的空格在我的针串,但我想改进代码,如果可能的话。

我的代码目前看起来像下面这样(在一个类的方法中):

double var1, var2;
char skip[5];
std::fstream haystack ("filename");
std::string needle = "This is a string, and var1    =";
std::string line;
int pos;
bool found = false;
// Search for needle
while ( !found && getline (haystack,line) ) {
  pos = line.find(needle);  // find position of needle in current line
  if (pos != std::string::npos) { // current line contains needle
      std::stringstream lineStream(line);
      lineStream.seekg (pos + needle.length());
      lineStream >> var1;
      lineStream >> skip;
      lineStream >> var2;
      found = true;
  }
}

(为了清楚起见,在找到字符串(指针)之后,我想要存储该行的下一个单词,或者在某些情况下存储下一个单词,然后跳过一个单词并存储下一个单词,例如:

带文件:

... ...
... This is a string, and var1    = 111 and 777 ...
... ...

我想提取var1 = 111; var2 = 777;)

提前感谢您的帮助!

这将工作,虽然我认为有一个更短的解决方案:

std::size_t myfind(std::string ins, std::string str) {
  for(std::string::iterator it = ins.begin(), mi = str.begin(); it != ins.end(); ++it) {
    if(*it == *mi) {
      ++mi;
      if (mi == str.end())
        return std::distance(ins.begin(),it);
    }
    else {
      if(*it == ' ')
        continue;
      mi = str.begin();
    }
  }
  return std::string::npos;
}
// use:
myfind("foo The quick brown      fox jumps over the        lazy dog bar", "The quick brown fox");

您可以找到line字符串中的所有空白字符序列,并用单个空白替换它们。这样,您就可以替换needle中的多个空格,并且您的搜索算法的其余部分将继续工作不变。

下面是一个使用STL删除重复项的方法:

#include <iostream>
#include <algorithm>
#include <string>
#include <iterator>
using namespace std;
struct DupSpaceDetector {
    bool wasSpace;
    DupSpaceDetector() : wasSpace(0) {}
    bool operator()(int c) {
        if (c == ' ') {
            if (wasSpace) {
                return 1;
            } else {
                wasSpace = 1;
                return 0;
            }
        } else {
            wasSpace = 0;
            return 0;
        }
    }
};
int main() {
    string source("The quick brown      fox jumps over the        lazy dog");
    string destination;
    DupSpaceDetector detector;
    remove_copy_if(
        source.begin()
    ,   source.end()
    ,   back_inserter(destination)
    ,   detector
    );
    cerr << destination << endl;
    return 0;
}

要解决这个问题,您应该从针和干草堆线中去掉额外的空间。std::unique被定义为执行此操作。通常情况下,它是在对范围排序后使用的,但在这种情况下,我们真正想做的是删除重复的空格。

struct dup_space
{
   bool operator()( char lhs, char rhs )
   {
      return std::isspace( lhs ) && std::isspace( rhs );
   }
};
void despacer( const std::string& in, std::string& out )
{
   out.reserve( in.size() );
   std::unique_copy( in.begin(), in.end(),
         std::back_insert_iterator( out ),
         dup_space()
      );
}

你应该这样使用:

void find( const std::string& needle, std::istream haystack )
{
   std::string real_needle;
   despacer( needle, real_needle );
   std::string line;
   std::string real_line;
   while( haystack.good() )
   {
      line.clear();
      std::getline( haystack, line );
      real_line.clear();
      despacer( line, real_line );
      auto ret = real_line.find( real_needle );
      if( ret != std::string::npos )
      {
         // found it
         // do something creative
      }
   }
}

最新更新