首页 > 解决方案 > 如何使用 string::find 从字符串中的字符中找到位置?

问题描述

我需要字符串中字符的位置。字符串包含:

"username":"secret", "password":"also secret", "id":"secret too", "token":"secret"

我需要标记中粗体引号的位置: "token": " secret "。我已经尝试过来自http://www.cplusplus.com/reference/string/string/find的代码, 但一切都没有奏效。谁能帮我?这是我尝试过的,但它只给出0:

#include <iostream>
#include <string>

int main() {
    std::string buffer("\"username\":\"secret\", \"password\":\"also secret\", \"id\":\"secret too\", \"token\":\"secret\"");
    size_t found = buffer.find('"');
    if (found == std::string::npos)std::cout << "something went wrong\n";
    if (found != std::string::npos)
        std::cout << "first " << '"' << " found at: " << found << '\n';
    for (int j = 0; j <= 17; ++j) {
        found = buffer.find('"');
        found + 1, 6;
        if (found != std::string::npos)
            std::cout << "second " << '"' << " found at : " << found << '\n';
    }
    return 0;

标签: c++

解决方案


有很多可能的解决方案。所以,很难回答。

基本上需要做的是,逐个位置地遍历字符串,然后检查字符是否是搜索到的字符,然后对结果做一些事情。

第一个简单的实现可以是:

#include <iostream>
#include <string>

const std::string buffer("\"username\":\"secret\", \"password\":\"also secret\", \"id\":\"secret too\", \"token\":\"secret\"");

int main() {

    for (size_t position{}, counter{}; position < buffer.length(); ++position) {

        if (buffer[position] == '\"') {
            ++counter;
            std::cout << "Character \" number " << counter << " found at position " << position << '\n';
        }
    }
    return 0;
}

但是,您的问题是关于std::string.find(). 在您的实现中,您总是在std::string. 因此,您将始终在位置 0 处找到相同的 "。

解决方案:找到第一个匹配项后,使用结果pos(加一)作为std::string.find()函数的第二个参数。然后您将在第一个找到 " 之后开始搜索,从而找到下一个。所有这些都可以在正常的循环中完成for

请参阅下面的下一个简单示例:

#include <iostream>
#include <string>

const std::string buffer("\"username\":\"secret\", \"password\":\"also secret\", \"id\":\"secret too\", \"token\":\"secret\"");

int main() {

    for (size_t position{}, counter{}; std::string::npos != (position = buffer.find("\"", position)); ++position, ++counter) {

        std::cout << "Character \" number " << counter << " found at position " << position << '\n';
    }
    return 0;
}

还有更多的解决方案,这取决于你真正想做的事情。您可以使用简单的正则表达式提取所有关键字和数据。

像这样的东西:

#include <iostream>
#include <string>
#include <regex>
#include <vector>

const std::regex re{ R"(\"([ a-zA-Z0-9]+)\")" };

const std::string buffer("\"username\":\"secret\", \"password\":\"also secret\", \"id\":\"secret too\", \"token\":\"secret\"");

int main() {
    std::vector part(std::sregex_token_iterator(buffer.begin(), buffer.end(), re, 1), {});
    std::cout << part[7] << '\n';
    return 0;
}

或者,您可以将所有内容拆分为标记和值。像这样:

#include <iostream>
#include <string>
#include <regex>
#include <vector>
#include <map>
#include <iomanip>

const std::regex re1{ "," };
const std::regex re2{ R"(\"([^\"]+)\")" };

const std::string buffer("\"username\":\"secret\", \"password\":\"also secret\", \"id\":\"secret too\", \"token\":\"secret\"");

int main() {
    std::vector<std::string> block(std::sregex_token_iterator(buffer.begin(), buffer.end(), re1, -1), {});
    std::map<std::string, std::string> entry{};
    for (const auto& b : block) {
        std::vector blockPart(std::sregex_token_iterator(b.begin(), b.end(), re2, 1), {});
        entry[blockPart[0]] = blockPart[1];
    }

    for (const auto& [token, value] : entry)
        std::cout << std::setw(20) << token << " --> " << value << '\n';

    return 0;
}

但是如果你有一个复杂的给定格式,比如 JSON,那么有很多特殊情况,唯一有意义的方法就是使用现有的库。


推荐阅读