我是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
}
}
}