Поиск строки в файле (построчно), игнорируя размер пробелов между словами - PullRequest
2 голосов
/ 22 декабря 2011

Я новичок в C ++, поэтому, пожалуйста, поймите ...

Я хочу найти строку (иглу) в файле (стоге сена), читая каждую строку отдельно, затем ищаигла в этой линии.Тем не менее, в идеале для более надежного кода я хотел бы иметь возможность просто читать отдельные слова в строке, чтобы при наличии больших (то есть нескольких) пробелов между словами они игнорировались при поиске стрелки.(например, возможно, используя оператор >> ??) То есть строка иглы не должна точно соответствовать размеру пространства между словами в файле.

, например, если у меня есть игла:

"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;)

Заранее спасибо за любую помощь!

Ответы [ 3 ]

1 голос
/ 22 декабря 2011

Это будет работать, хотя я думаю, что есть более короткое решение:

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");
1 голос
/ 22 декабря 2011

Вы можете найти все последовательности символов пробела в строке 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;
}
0 голосов
/ 22 декабря 2011

Чтобы решить вашу проблему, вы должны убрать лишние пробелы с иглы и линии сена.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
      }
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...