[英]How would I separate a std::string with more than 1 character I'm looking for?
I'm writing a program that can take in multiple names separated by a space, like "John Paul Andrew"
and turns the names into keys for a std::map.我正在编写一个程序,它可以接收多个由空格分隔的名称,例如
"John Paul Andrew"
,并将名称转换为 std::map 的键。
It works fine with two names, but three names or more separate the string into:它适用于两个名称,但三个或更多名称将字符串分隔为:
Andrew
John
John Paul
Here's how I'm splitting the strings:这是我拆分字符串的方式:
for (int i = 0; i < names.size() - 1; i++) {
std::string::size_type pos = names.find(" ", i);
std::cout << "Position of space: " << pos << std::endl; // For debugging
if (pos != std::string::npos) {
std::string name = names.substr(0, pos);
scoreboard[name] = 0;
} else {
std::string name = names.substr(names.rfind(" ") + 1);
scoreboard[name] = 0;
}
}
Is there a replacement for names.substr(0, pos);
是否有
names.substr(0, pos);
的替代品? I can use to fix the issue?我可以用来解决问题吗?
You have i
as you indexer, which can help you find the word being processed.你有
i
作为你的索引器,它可以帮助你找到正在处理的单词。 So you don't need an old_pos
as I had suggested, since i
already can serve that purpose.所以你不需要我建议的
old_pos
,因为i
已经可以达到这个目的。
#include <iostream>
#include <string>
#include <map>
using std::cout;
using std::map;
using std::string;
static auto make_scoreboard(string names) -> map<string, int> {
auto scoreboard = map<string, int>{};
for (decltype(names.size()) i = 0; i < names.size() - 1; i++) {
auto pos = names.find(" ", i);
cout << "Position of space: " << pos << "\n"; // For debugging
if (pos != string::npos) {
auto name = names.substr(i, pos - i);
scoreboard[name] = 0;
i = pos;
} else {
string name = names.substr(names.rfind(" ") + 1);
scoreboard[name] = 0;
i = names.size();
}
}
return scoreboard;
}
int main() {
auto names = string{"John Paul Andrew"};
auto scoreboard = make_scoreboard(names);
for(auto&& s : scoreboard) {
cout << s.first << "\n";
}
}
You are looping through each character of names
(except the last character,), using the current loop position as the starting position to find()
a space character.您正在遍历
names
的每个字符(最后一个字符除外),使用当前循环 position 作为起始position 来find()
一个空格字符。 That is not the logic you should be using.这不是您应该使用的逻辑。
Let's follow the logic, using your example of "John Paul Andrew"
as the names
to split.让我们按照逻辑,使用您的
"John Paul Andrew"
示例作为要拆分的names
。
On the 1st-5th loop iterations, where i
is 0..4
, names.find(" ", i)
returns 4 each time.在第 1-5 次循环迭代中,
i
为0..4
, names.find(" ", i)
每次返回 4。 You then call names.substr(0, 4)
which returns "John"
.然后你调用
names.substr(0, 4)
返回"John"
。 So you assign 0 to scoreboard["John"]
5 times .因此,您将 0 分配给
scoreboard["John"]
5 次。
On the 6th-10th loop iterations, where i
is 5..9
, names.find(" ", i)
returns 9 each time.在第 6-10 次循环迭代中,
i
为5..9
, names.find(" ", i)
每次返回 9。 You then call names.substr(0, 9)
which returns "John Paul"
.然后,您调用
names.substr(0, 9)
返回"John Paul"
。 So you assign 0 to scoreboard["John Paul"]
5 times .因此,您将 0 分配给
scoreboard["John Paul"]
5 次。
On the 11th-15th loop iterations, where i
is 10..14
, names.find(" ", i)
returns std::string::npos
each time.在第 11-15 次循环迭代中,
i
是10..14
, names.find(" ", i)
每次都返回std::string::npos
。 You then call names.rfind(" ")
which returns 9, and then you call names.substr(9 + 1)
which returns "Andrew"
.然后调用
names.rfind(" ")
返回 9,然后调用names.substr(9 + 1)
返回"Andrew"
。 So you assign 0 to scoreboard["Andrew"]
5 times .因此,您将 0 分配给
scoreboard["Andrew"]
5 次。
See the problem now?现在看到问题了吗?
At the very least, since you are looping through names
one character at a time anyway, you should not be using names.find()
at all, eg:至少,由于您一次遍历一个字符的
names
,因此您根本不应该使用names.find()
,例如:
std::string::size_type start = 0;
for (std::string::size_type i = 0; i < names.size(); ++i) { // <-- no -1 !
if (names[i] == ' ') {
std::cout << "Position of space: " << i << std::endl; // For debugging
if (i > start) {
std::string name = names.substr(start, i - start);
scoreboard[name] = 0;
}
start = i + 1;
}
}
if (start < names.size()) {
std::string name = names.substr(start);
scoreboard[name] = 0;
}
Which, if you really want to use find()
, can be re-written more like this:如果您真的想使用
find()
,可以将其重写为:
std::string::size_type start = names.find_first_not_of(' ');
std::string name;
while (start != std::string::npos)
{
std::string::size_type pos = names.find(' ', start);
if (pos == std::string::npos)
{
name = names.substr(start);
start = pos;
}
else
{
name = names.substr(start, pos - start);
start = names.find_first_not_of(' ', pos + 1);
}
scoreboard[name] = 0;
}
However, there is a must easier way to split a string on spaces (and other whitespace characters):但是,必须有一种更简单的方法可以在空格(和其他空白字符)上拆分字符串:
std::istringstream iss(names);
std::string name;
while (iss >> name)
{
scoreboard[name] = 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.