Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I compare a section of a string without copying?

Tags:

c++

string

c++11

I have a long string that I'm iterating through, and at each iteration I compare a section of the string to a constant and store some parts of the string. In my actual code, this code runs millions of times and is the main bottleneck. I think it's due to the excessive use of 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 pos = str.find(',');

    // loop over the string, collecting "key=value" pairs
    while (pos < str.size() - 1) {
        if (str.substr(pos + 1, 2) == "0=") {
            auto newPos = str.find(',', pos + 3);
            out0.push_back(str.substr(pos + 3, newPos - pos - 3);
            pos = newPos;
        } else {
            size_t eqPos = str.find('=', pos + 1);
            auto newPos = str.find(',', eqPos + 1);
            out[str.substr(pos + 1, eqPos - pos - 1)] = str.substr(eqPos + 1, newPos - eqPos - 1);
        }
    }

    // print out the data structures (this doesn't happen in my actual code)
    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;
    }
}

Here are my questions:

  • How can I perform comparisons on the string without performing a copy and without writing the comparison for each character, e.g. str[pos + 1] == '0' && str[pos + 2] == '=' && ...?
  • How can I store references to substrings, instead of making copies every time I add to out0 and out?

This may be a great case for the use of char *, but I've never used it before.

Edit:

Unfortunately, I've only got C++11; otherwise, std::string_view is the best answer. Is there a way to accomplish the storage of references without std::string_view?

like image 669
Kyle Avatar asked Dec 14 '22 10:12

Kyle


1 Answers

If you have C++17, you can use string_view thus: (untested code):

string_view sv{str.data() + pos, 2};
if (sv == "0=") ...

No copies. Or even (all in one go):

if (string_view{str.data() + pos, 2} == "0=") ...

If you don't have string_view, you can use char_traits:

if (std::char_traits<char>::compare(str.data() + pos, "0=", 2) == 0) ...
like image 142
Marshall Clow Avatar answered Jan 10 '23 08:01

Marshall Clow