使用std::istringstream
它很容易阅读由空格分隔的单词。但要解析以下行,我需要将字符/
视为空格。
f 104/387/104 495/574/495 497/573/497
如何读取由斜杠或空格分隔的值?
使用std::istringstream
它很容易阅读由空格分隔的单词。但要解析以下行,我需要将字符/
视为空格。
f 104/387/104 495/574/495 497/573/497
如何读取由斜杠或空格分隔的值?
一种方法是定义一个分类/
为空白的 ctype facet:
class my_ctype : public std::ctype<char> {
public:
mask const *get_table() {
static std::vector<std::ctype<char>::mask>
table(classic_table(), classic_table()+table_size);
table['/'] = (mask)space;
return &table[0];
}
my_ctype(size_t refs=0) : std::ctype<char>(get_table(), false, refs) { }
};
从那里,使用该 ctype facet 为流注入语言环境,然后读取单词:
int main() {
std::string input("f 104/387/104 495/574/495 497/573/497");
std::istringstream s(input);
s.imbue(std::locale(std::locale(), new my_ctype));
std::copy(std::istream_iterator<std::string>(s),
std::istream_iterator<std::string>(),
std::ostream_iterator<std::string>(std::cout, "\n"));
}
如果 boost 可用,那么boost::split()
将是一个可能的解决方案。填充std::string
usingstd::getline()
然后拆分行:
#include <iostream>
#include <vector>
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>
int main()
{
std::vector<std::string> tokens;
std::string line("f 104/387/104 495/574/495 497/573/497");
boost::split(tokens, line, boost::is_any_of("/ "));
for (auto& token: tokens) std::cout << token << "\n";
return 0;
}
输出:
F 104 387 104 495 574 495 497 573 497
如果您知道何时用斜杠或空格分割,您可以使用std::getline
std::istringstream is("f 104/387/104 495/574/495 497/573/497");
std::string f, i, j, k;
std::getline(is, f, ' ');
std::getline(is, i, '/');
std::getline(is, j, '/');
std::getline(is, k, ' ');
或者,您可以使用格式化输入并手动丢弃斜杠
std::string f;
int i, j, k;
char slash;
is >> f >> i >> slash >> j >> slash >> k;
我确信这根本不是最好的方法,但我正在编写《Programming Principles and Practice Using C++ 2nd Ed》一书中的练习。Bjarne Stroustrup和我想出了一个可能对你有用的解决方案。我四处搜寻,看看其他人是怎么做的(这就是我找到这个帖子的方式),但我真的什么也没找到。
首先,这是书中的练习:
编写一个函数 vector<string> split(const string& s, const string& w) 从参数 s 返回一个由空格分隔的子字符串的向量,其中空格定义为“普通空格”加上 w 中的字符。
这是我想出的解决方案,似乎效果很好。我试着评论它以使其更清楚。只想提一下我对 C++ 还很陌生(这就是我阅读这本书的原因),所以不要对我太苛刻。:)
// split a string into its whitespace-separated substrings and store
// each string in a vector<string>. Whitespace can be defined in argument
// w as a string (e.g. ".;,?-'")
vector<string> split(const string& s, const string& w)
{
string temp{ s };
// go through each char in temp (or s)
for (char& ch : temp) {
// check if any characters in temp (s) are whitespace defined in w
for (char white : w) {
if (ch == white)
ch = ' '; // if so, replace them with a space char ('')
}
}
vector<string> substrings;
stringstream ss{ temp };
for (string buffer; ss >> buffer;) {
substrings.push_back(buffer);
}
return substrings;
}
然后你可以做这样的事情来使用它:
cout << "Enter a string and substrings will be printed on new lines:\n";
string str;
getline(cin, str);
vector<string> substrings = split(str, ".;,?-'");
cout << "\nSubstrings:\n";
for (string s : substrings)
cout << s << '\n';
我知道您不想拆分字符串,但这只是您如何将其他字符视为空格的示例。基本上,我只是用 ' ' 替换这些字符,所以它们确实变成了空格。将其与流一起使用时,效果很好。for 循环可能是您案例的相关代码。