【问题标题】:Printing all substrings between/after occurrence of a character in C++在 C++ 中出现字符之间/之后打印所有子字符串
【发布时间】:2020-03-23 20:48:10
【问题描述】:

我试图在某个字符出现之间或之后获取所有子字符串。 特别是搜索查询网址(获取选项),例如,如果我有:

std::string url = "https://www.google.com/search?q=i+need+help&rlz=1C1CHBF_enUS851US851&oq=i+need+help&aqs=chrome.0.69i59j0l3j69i60l2.4646j0j7&sourceid=chrome&ie=UTF-8"

我需要在“&”字符之间和之后(最后一次出现)输出字符串 所以输出将是:

rlz=1C1CHBF_enUS851US851 
oq=i+need+help
aqs=chrome.0.69i59j0l3j69i60l2.4646j0j7
sourceid=chrome 
ie=UTF-8

我了解如何使用一个字符串来执行此操作,但我一直在尝试将其实现为循环。这必须通过几个不同长度和选项数量的 url 来完成。

到目前为止,我只能在第一次和第二次出现字符之间抓取一个子字符串,但我需要在任何给定的 url 中抓取所有子字符串。

int a = url.find("&") + 1;
int b = url.find("&", url.find("&") + 1);
int c = (b - a);
std::string option = url.substr(a, c);

【问题讨论】:

标签: c++ string split


【解决方案1】:

例如,您可以只使用普通的 for 循环

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>

int main() 
{
    std::string url = "https://www.google.com/search?q=i+need+help"
                      "&rlz=1C1CHBF_enUS851US851"
                      "&oq=i+need+help"
                      "&aqs=chrome.0.69i59j0l3j69i60l2.4646j0j7"
                      "&sourceid=chrome&ie=UTF-8";

    char c = '&';

    size_t n = std::count_if( std::begin( url ), std::end( url ),
                              [=]( const auto &item )
                              {
                                 return item == c;
                              } );

    std::vector<std::string> v;
    v.reserve( n );

    for ( auto pos = url.find( c, 0 );  pos != std::string::npos; )
    {
        auto next = url.find( c, ++pos );

        auto n = ( next == std::string::npos ? url.size() : next ) - pos;

        v.push_back( url.substr( pos, n ) ); 

        pos = next;                    
    }

    for ( const auto &s : v ) std::cout << s << '\n';

}

程序输出是

rlz=1C1CHBF_enUS851US851
oq=i+need+help
aqs=chrome.0.69i59j0l3j69i60l2.4646j0j7
sourceid=chrome
ie=UTF-8

或者您可以编写一个单独的函数,例如

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>

std::vector<std::string> split_url( const std::string &url, char c = '&' )
{
    size_t n = std::count_if( std::begin( url ), std::end( url ),
                              [=]( const auto &item )
                              {
                                 return item == c;
                              } );

    std::vector<std::string> v;
    v.reserve( n );

    for ( auto pos = url.find( c, 0 );  pos != std::string::npos; )
    {
        auto next = url.find( c, ++pos );

        auto n = ( next == std::string::npos ? url.size() : next ) - pos;

        v.push_back( url.substr( pos, n ) ); 

        pos = next;                    
    }

    return v;
}

int main() 
{
    std::string url = "https://www.google.com/search?q=i+need+help"
                      "&rlz=1C1CHBF_enUS851US851"
                      "&oq=i+need+help"
                      "&aqs=chrome.0.69i59j0l3j69i60l2.4646j0j7"
                      "&sourceid=chrome&ie=UTF-8";


    auto v = split_url(url );

    for ( const auto &s : v ) std::cout << s << '\n';

}

【讨论】:

    【解决方案2】:

    您可以尝试以下使用正则表达式解析url的代码。

    #include <regex>
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main(){
        string url = "https://www.google.com/search?q=i+need+help&rlz=1C1CHBF_enUS851US851&oq=i+need+help&aqs=chrome.0.69i59j0l3j69i60l2.4646j0j7&sourceid=chrome&ie=UTF-8";
        regex rg("[\?&](([^&]+)=([^&]+))");
        for(smatch sm; regex_search(url, sm, rg); url=sm.suffix())
            cout << sm[1] <<endl;
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      Tbh 我真的认为您应该为这项工作使用适当的 URI 解析器,因为可能会有很多边缘情况。但是给你:

      #include <iostream>
      #include <string>
      
      int main()
      {
        std::string url = "https://www.google.com/search?q=i+need+help&rlz=1C1CHBF_enUS851US851&oq=i+need+help&aqs=chrome.0.69i59j0l3j69i60l2.4646j0j7&sourceid=chrome&ie=UTF-8";
        char delimiter = '&';
        size_t start = url.find(delimiter);
        size_t end;
        while (start != std::string::npos) {
            end = url.find(delimiter, start + 1);
            std::cout << url.substr(start + 1, end - start - 1) << std::endl;
            start = end;
        }
      }
      

      游乐场:http://cpp.sh/8pshy7

      【讨论】:

      • 我应该补充一下这是专门针对搜索查询的,有些有一点一致性
      【解决方案4】:

      只需在循环中从上一个&amp; 中找到下一个&amp;,如果找不到更多&amp;,则退出循环并处理第一个元素:

      vector<string> foo(const string& url)
      {
          vector<string> result;
          auto a = url.find("?");
          if (a == string::npos) return result;
      
          auto b = url.find("&");
          if (b == string::npos)
          {
              result.push_back(url.substr(a + 1, string::npos));
              return result;
          }
          result.push_back(url.substr(a + 1, b - a - 1));
          do
          {
              a = b;
              b = url.find("&", a + 1);
              result.push_back(url.substr(a + 1, b - a - 1));
          } while (b != string::npos);
      
          return result;
      }
      

      适用于您的示例:https://ideone.com/SiRZQB

      【讨论】:

        猜你喜欢
        • 2020-01-06
        • 1970-01-01
        • 2022-10-13
        • 2015-08-01
        • 2015-06-19
        • 2015-05-11
        • 2021-02-22
        • 2021-07-03
        • 2017-03-30
        相关资源
        最近更新 更多