在输入流的开头匹配字符串
Matching a string at the beginning of a inputstream
我实现了一个简单的输入流操纵符,将输入流中的下n个字符与给定字符串匹配。然而,我不确定这是否是最好的方法。有提示吗?
class MatchString {
private:
std::string mString;
public:
MatchString(const std::string &str) {
mString = str;
}
std::istream& operator()(std::istream& is) const {
// Allocate a string buffer, ...
char *buffer = new char[mString.length()];
// ... read next n chars into the buffer ...
is.read(buffer, mString.length());
// ... and compare them with given string.
if(strncmp(buffer, mString.c_str(), mString.length())) {
throw MismatchException(mString);
}
delete[] buffer;
return is;
}
};
inline MatchString match(const std::string &str) {
return MatchString(str);
}
inline std::istream& operator>>(std::istream& is, const MatchString& matchStr) {
return matchStr(is);
}
编辑:可以根据user673679的建议实现使用匹配字符的解决方案:
class MatchString {
...
std::istream& operator()(std::istream& is) const {
// Match the next n chars.
std::for_each(mString.begin(), mString.end(),
[&](const char c) {
if(is.get() != c) {
throw MismatchException(mString);
}
});
return is;
}
};
如果我不想消耗字符,我该如何实现呢?
编辑II:
这里是fjardon提到的另一个解决方案:
class MatchString {
...
std::istream& operator()(std::istream& is) const {
// Match the next n chars.
if(std::mismatch(mString.begin(), mString.end(),
std::istreambuf_iterator<char>(is)).first != mString.end()) {
throw MismatchException(mString);
}
return is;
}
};
编辑III:
终于得到了一个工作函数,如果字符串不匹配,它将恢复消耗:
class MatchString {
...
std::istream& operator()(std::istream& is) const {
// Match the next n chars.
std::streampos oldPos = is.tellg();
if(std::mismatch(mString.begin(), mString.end(),
std::istreambuf_iterator<char>(is)).first != mString.end()) {
is.seekg(oldPos);
throw MismatchException(mString);
}
return is;
}
};
不需要从流中分配和复制整个字符串,您可以一次只检查一个字符,从而完全避免分配缓冲区:
#include <iostream>
#include <sstream>
#include <string>
auto mString = std::string("foobar");
std::istream& match(std::istream& is) {
for (auto c : mString)
if (c != is.get())
throw std::runtime_error("nope");
return is;
}
int main()
{
auto input = "foobarbaz";
auto stream = std::istringstream(input);
match(stream);
std::cout << "done!" << std::endl;
}
您还应该为is.get()(或原始代码中的.read())添加错误检查。
相关文章:
- 在 C++11 中,如何查找并返回以给定字符串开头的字符串向量中的所有项?
- 字符串开头的分隔符
- 如何使字符串出现在编译的二进制可执行文件的开头?
- 如何在 Arduino 字符串的开头添加元素.类似于 JS unshift();
- 为什么使用 QString::right 在字符串开头省略逗号?
- cout 切断 for 循环中的字符串开头
- 如何从字符串开头到第二个分隔符中提取子字符串?
- ZeroMQ (cppzmq) 订阅者,过滤器以相同的字符串开头
- 如何检查 std::vector<std::string> 的元素是否以某个子字符串开头?
- 如何在 qt 中使用 QRegularExpression 匹配字符串开头的空格?
- DeleteFile,以子字符串开头
- 是否有函数/WinAPI 可以判断一个字符串是否以不区分大小写的语言方式以另一个字符串开头?
- 检查一个字符串是否以另一个已知字符串开头
- 如何检查const char*是否以特定字符串开头?(C++)
- 字符串以某个字符串开头
- 如何清除字符串开头的垃圾
- 删除字符串c++开头和结尾的标点符号
- 检查字符串是否以另一个字符串开头:find或compare
- C++ std::map<std::string, int> 获取键以特定字符串开头的值
- c++ getline在字符串开头添加空格