std::stringstream convertor("Tom Scott 25");
std::string name;
int age;
convertor >> name >> age;
if(convertor.fail())
{
// it fails of course
}
我想将两个或多个单词提取到一个字符串变量中。到目前为止,我已经读过,似乎不可能。如果是这样,怎么办呢?我希望name
在数字(年龄)之前获取所有字符。
我觉得使用sscanf最舒服,但我显然不能。
我需要的是能够在age
之前提取所有字词。
答案 0 :(得分:3)
这有什么问题?
std::stringstream convertor("Tom Scott 25");
std::string firstname;
std::string surname;
int age;
convertor >> firstname >> surname >> age;
std::string name = firstname + " " + surname;
答案 1 :(得分:3)
到目前为止发布的大多数解决方案都不符合规范 - 所有截至年龄的数据都被视为名称。例如,他们会以“Richard Van De Rothstyne”这样的名字失败。
正如OP所指出的那样,使用scanf,您可以执行以下操作:scanf("%[^0-9] %d", name, &age);
,它会很好地读取它。假设这是面向行的输入,我倾向于这样做:
std::string temp;
std::getline(infile, temp);
// technically "[^0-9]" isn't required to work right...
sscanf(temp.c_str(), "%[^0123456789] %d", name, &age);
不幸的是,iostream并不直接模拟扫描集转换 - getline可以读取分隔符,但是您只能指定一个字符作为分隔符。如果你真的不能使用scanf和company,那么下一站就是手工编写代码(年龄的开头是temp.find_first_of("0123456789");
)或使用RE包(TR1如果你的编译器提供它,否则可能Boost)。
答案 2 :(得分:2)
这有什么问题?
std::stringstream convertor("Tom Scott 25");
std::string first, last;
int age;
convertor >> first >> last >> age
如果你真的想一次性阅读,那么这样的事情就可以了
class Name {
std::string first, last;
public:
std::istream& read(std::istream& in) {
return in >> first >> last;
}
operator std::string() const { return first + " " + last; }
};
std::istream& operator>>(std::istream& in, Name& name) {
return name.read(in);
}
/* ... */
Name name;
int age;
converter >> name >> age;
std::cout << (std::string)name;
你想读N个单词的更通用的例子可以这样运作:
class Reader {
int numWords;
std::vector<std::string> words;
// ...
std::istream& read(std::istream& in) {
std::vector<std::string> tmp;
std::string word;
for (int i = 0; i < numWords; ++i) {
if (!in >> word)
return in;
tmp.push_back(word);
}
// don't overwrite current words until success
words = tmp;
return in;
}
答案 3 :(得分:2)
您可以实施的常规算法:
read word into name
loop
try reading integer
if success then break loop
else
clear error flag
read word and attach to name
答案 4 :(得分:1)
一种方法是使用重载运算符&gt;&gt;
创建一个新类class TwoWordString {
public:
std::string str;
};
istream& operator>>(istream& os; TwoWordString& tws) {
std::string s1, s2;
os >> s1;
os >> s2;
tws.str = s1 + s2;
return os;
}
答案 5 :(得分:0)
这是一种矫枉过正的方式(使用Boost.Spirit)&gt;:D
#include <iostream>
#include <string>
#include <boost/format.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
int main()
{
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace ascii = boost::spirit::ascii;
using ascii::char_; using ascii::digit; using ascii::blank;
using qi::_1; using qi::int_; using phoenix::ref; using phoenix::at_c;
std::string input("Sir Buzz Killington, esq. 25");
std::string name;
int age = 0;
qi::rule<std::string::const_iterator, std::string()> nameRule;
nameRule %= (+(char_ - digit - blank));
std::string::const_iterator begin = input.begin();
std::string::const_iterator end = input.end();
qi::parse(begin, end,
(
nameRule[ref(name) += _1]
>> *( ((+blank) >> nameRule)[ref(name) += ' ']
[ref(name) += at_c<1>(_1)] )
>> *blank
>> int_[ref(age) = _1]
)
);
std::cout << boost::format("Name: %1%\nAge: %2%\n") % name % age;
return 0;
}
输出:
姓名:Sir Buzz Killington,esq。
年龄:25
但是,如果您经常在程序中进行非平凡的输入解析,请考虑使用parsing或regular expressions库。
答案 6 :(得分:0)
这是我刚才做的功课。 但是int或double类型必须放在字符串的前面。因此,您可以阅读不同大小的多个单词。 希望这可以帮助你一点点。
string words;
sin>>day>>month>>year;
sin>>words;
watch = words;
while(sin>>words)
{
watch += " "+words;
}
答案 7 :(得分:0)
这是一个std::regex
(任意数量的名称)的解决方案:
auto extractNameAndAge(std::string const &s) -> std::tuple<std::string, int> {
using namespace std::string_literals;
static auto const r = std::regex{"(.*)\\s+(\\d+)\\s*$"s};
auto match = std::smatch{};
auto const matched = std::regex_search(s, match, r);
if (!matched)
throw std::invalid_argument{"Invalid input string \""s + s +
"\" in extractNameAndAge"s};
return std::make_tuple(match[1], std::stoi(match[2]));
}
测试:
auto main() -> int {
using namespace std::string_literals;
auto lines = std::vector<std::string>{"Jonathan Vincent Voight 76"s,
"Donald McNichol Sutherland 79"s,
"Scarlett Johansson 30"s};
auto name = ""s;
auto age = 0;
for (auto cosnt &line : lines) {
std::tie(name, age) = extractNameAndAge(line);
cout << name << " - " << age << endl;
}
}
输出:
Jonathan Vincent Voight - 76
Donald McNichol Sutherland - 79
Scarlett Johansson - 30