std::string 具有将 const char* 子字符串作为输入的 compare() 方法。您不需要使用std::string::substr() 来比较子字符串,例如:
#include <iostream>
#include <map>
#include <string>
#include <vector>
int main() {
std::string str("0=My,1=comma,2=separated,3=string,0=with,3=repeated,7=IDs");
std::vector<std::string> out0;
std::map<std::string, std::string> out;
size_t startPos = 0, delimPos, nameStart, nameEnd, valueStart, valueEnd;
// loop over the string, collecting "key=value" pairs
while (startPos < str.size()){
nameStart = startPos;
delimPos = str.find_first_of("=,", startPos, 2);
if (delimPos == std::string::npos) {
nameEnd = valueStart = valueEnd = str.size();
}
else {
nameEnd = delimPos;
if (str[delimPos] == '=') {
valueStart = nameEnd + 1;
valueEnd = str.find(',', valueStart);
if (valueEnd == std::string::npos) {
valueEnd = str.size();
}
}
else {
valueStart = valueEnd = nameEnd;
}
}
// TODO: if needed, adjust name(Start|End) and value(Start|End) to
// ignore leading/trailing whitespace around the name and value
// substrings...
if (str.compare(nameStart, nameEnd - nameStart, "0", 1) == 0) {
out0.push_back(str.substr(valueStart, valueEnd - valueStart));
} else {
out[str.substr(nameStart, nameEnd - nameStart)] = str.substr(valueStart, valueEnd - valueStart);
}
startPos = valueEnd + 1;
}
// print out the data structures
std::cout << "out0:";
for (auto& entry : out0) {
std::cout << ' ' << entry;
}
std::cout << std::endl;
std::cout << "out:";
for (auto it : out) {
std::cout << ' ' << it->first << '=' << it->second;
}
}
输出:
out0: 我的
输出:1=逗号 2=分隔 3=重复 7=ID
Live Demo
您可以更进一步,完全不使用substr(),方法是根本不在std::vector 和std::map 中存储std::string 值,而是存储std::pair<char*, size_t>:
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <utility>
using StrView = std::pair<const char*, size_t>;
StrView makeStrView(const char *str, size_t size) {
return std::make_pair(str, size);
}
struct compareStrView {
bool operator()(const StrView &lhs, const StrView &rhs) const {
if (lhs.second == rhs.second)
return (std::char_traits<char>::compare(lhs.first, rhs.first, lhs.second) < 0);
return (lhs.second < rhs.second);
}
};
std::ostream& operator<<(std::ostream &os, const StrView &rhs) {
return os.write(rhs.first, rhs.second);
}
int main() {
std::string str("0=My,1=comma,2=separated,3=string,0=with,3=repeated,7=IDs");
std::vector<StrView> out0;
std::map<StrView, StrView, compareStrView> out;
size_t startPos = 0, delimPos, nameStart, nameEnd, valueStart, valueEnd;
// loop over the string, collecting "key=value" pairs
while (startPos < str.size()){
nameStart = startPos;
delimPos = str.find_first_of("=,", startPos, 2);
if (delimPos == std::string::npos) {
nameEnd = valueStart = valueEnd = str.size();
}
else {
nameEnd = delimPos;
if (str[delimPos] == '=') {
valueStart = nameEnd + 1;
valueEnd = str.find(',', valueStart);
if (valueEnd == std::string::npos) {
valueEnd = str.size();
}
}
else {
valueStart = valueEnd = nameEnd;
}
}
// TODO: if needed, adjust nameStart/End and valueStartEnd to
// ignore leading/trailing whitespace around the name and value
// substrings...
if (str.compare(nameStart, nameEnd - nameStart, "0", 1) == 0) {
out0.push_back(makeStrView(&str[valueStart], valueEnd - valueStart));
} else {
out[makeStrView(&str[nameStart], nameEnd - nameStart)] = makeStrView(&str[valueStart], valueEnd - valueStart);
}
startPos = valueEnd + 1;
}
// print out the data structures
std::cout << "out0:";
for (auto& entry : out0) {
std::cout << ' ' << entry;
}
std::cout << std::endl;
std::cout << "out:";
for (auto &it : out) {
std::cout << ' ' << it.first << '=' << it.second;
}
}
输出:
out0: 我的
输出:1=逗号 2=分隔 3=重复 7=ID
Live Demo
在 C++17 中,您可以使用 std::string_view 代替:
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <string_view>
int main() {
std::string str("0=My,1=comma,2=separated,3=string,0=with,3=repeated,7=IDs");
std::string_view sv(str);
std::vector<std::string_view> out0;
std::map<std::string_view, std::string_view> out;
size_t startPos = 0, delimPos, nameStart, nameEnd, valueStart, valueEnd;
// loop over the string, collecting "key=value" pairs
while (startPos < sv.size()){
nameStart = startPos;
delimPos = sv.find_first_of("=,", startPos, 2);
if (delimPos == std::string_view::npos) {
nameEnd = valueStart = valueEnd = sv.size();
}
else {
nameEnd = delimPos;
if (sv[delimPos] == '=') {
valueStart = nameEnd + 1;
valueEnd = sv.find(',', valueStart);
if (valueEnd == std::string_view::npos) {
valueEnd = sv.size();
}
}
else {
valueStart = valueEnd = nameEnd;
}
}
// TODO: if needed, adjust nameStart/End and valueStartEnd to
// ignore leading/trailing whitespace around the name and value
// substrings...
if (sv.compare(nameStart, nameEnd - nameStart, "0", 1) == 0) {
out0.push_back(sv.substr(valueStart, valueEnd - valueStart));
} else {
out[sv.substr(nameStart, nameEnd - nameStart)] = sv.substr(valueStart, valueEnd - valueStart);
}
startPos = valueEnd + 1;
}
// print out the data structures
std::cout << "out0:";
for (auto& entry : out0) {
std::cout << ' ' << entry;
}
std::cout << std::endl;
std::cout << "out:";
for (auto &it : out) {
std::cout << ' ' << it.first << '=' << it.second;
}
}