c++分割std::string成多个string

问题描述

假设我们有一个http服务器,此服务器接收客户端发来的http请求,假设请求如下

GET / HTTP/1.1

我们怎么将这个Http请求分割成三份,分别存入不同的string中分别处理?

前置知识

首先std::string的本身存于stack中,但是std::string指向的string存于Heap中,std::string在stack作用域消失的时候自动清除Heap中的字符串

关于std::string的操作
假设我们有一个std::string如下

std::string s;

我们可以有以下的操作

寻找指定字符

s.find('c');

寻找std::string s中的字符c的位子,且返回其下标

s.find('c', 10);

std::string s的下标10开始寻找字符c,且返回其下标

注意下标是从1开始算,而不是0

我们的find找到最后可能会返回一个不存在的数字,这个数字就是std::string::npos;,我们可以将这个数字当成find的结束符号(如果find在循环中)

扫描二维码关注公众号,回复: 14722612 查看本文章
s.find('c', POSITION);

如果我们从str::find返回的结果中查找,比如上述代码POSITION就是一个str.find()的返回值,上述代码会从POSITION的位子开始找(包含POSITION)

分割字符串成子字符串

s.substr(start, end);

对于std::string s从index为start开始到index为end结束(不包括end)的字符串截取出来返回

比如我们有一个字符串"hello world"我们对其做s.substr(0, 7);结果是返回"hello w",也就是返回index从0到6的字符串
index是从0开始
假如我们传入的是2个从s.find查找的结果,就从这个位子开始截取,比如我们有字符串"abcdefghij"P1指向'b'(P1s.find的返回值),P2指向'f'(P2也是s.find的返回值),我们截取字符串s.substr(P1, P2);得到的结果等于"bcdef"

解决代码

那么我们就非常容易解决上述问题

#include <iostream>
//#include <thread>
#include <string>
#include <vector>

int main(){
    
    

    std::vector<std::string> v;

    std::string s{
    
    "GET / HTTP/1.1"};

    std::string::size_type start = 0;
    std::string::size_type end = s.find(' ');
   
    for(int i = 0; i < 3; i++){
    
    
        if(end == std::string::npos) v.push_back(s.substr(start, s.length()));
        std::cout << s.substr(start, end-start) << "\n";
        v.push_back(s.substr(start, end-start));
        start = ++end;
        end = s.find(' ', end);
    }
    /*
    for(auto i: v){
        std::cout << i <<'\n';
    } 
    */  
}

根据上述的方法给我们一个url,我们如何将其截取出scheme,host,port,path?
解决方法如下

#include <iostream>
#include <string>
#include <vector>
#include <memory>

class uri{
    
    
public:
    uri();
    ~uri() = default;
    
    bool                      parseuri(const std::string&);
    std::string               get_scheme() const ;
    std::string               get_host()   const;
    uint16_t                  get_port()   const;
    std::vector<std::string>  get_path()   const;


private:
    struct Impl;
    std::shared_ptr<struct Impl> impl_;
};

struct uri::Impl{
    
    
    std::string scheme;
    std::string host;
    uint16_t port;
    std::vector<std::string> path;
};

uri::uri()
: impl_(new Impl){
    
    

}

bool uri::parseuri(const std::string& uri){
    
    
    //注意uri.find('X', POSISTION)是从POSISTION这个下标开始find最重要的寻找范围包括这个下标

    auto colon = uri.find(':');
    impl_->scheme = uri.substr(0, colon);

    auto slash = uri.find('/', colon+1);
    auto sec_slash = uri.find('/', slash+1);
    auto path_root = uri.find('/', sec_slash+1);
    
    auto sec_colon = uri.find(':', slash);
    if(sec_colon == std::string::npos){
    
     //没有第二个冒号也意味着没有端口号那么直接默认80
        impl_->port = 80;
        impl_->host = uri.substr(sec_slash+1, path_root-sec_slash-1);
    }else{
    
     //带表有第二个冒号也就是指定了端口号
        impl_->port = std::stoi(uri.substr(sec_colon + 1, path_root - sec_colon - 1));
        impl_->host = uri.substr(sec_slash+1, sec_colon - sec_slash - 1);
    }

    auto start = path_root;
    auto end = start;

    while((end = uri.find('/', end + 1))!= std::string::npos){
    
    
        impl_->path.push_back(uri.substr(start + 1, end - start - 1));
        start = end; 
        if(uri.find('/', end + 1) == std::string::npos){
    
    
            impl_->path.push_back(uri.substr(end + 1, uri.length()));
        }
    }
    return true;
   
}


std::string uri::get_scheme()               const {
    
     return impl_->scheme; } 
std::string uri::get_host()                 const {
    
     return impl_->host; }
uint16_t    uri::get_port()                 const {
    
     return impl_->port; }
std::vector<std::string>  uri::get_path()   const {
    
     return impl_->path; }


int main(){
    
    
    uri a;
    auto if_true = a.parseuri("http:://www.baidu.com:80/foo/bar/ui/abc");

    std::cout << a.get_scheme() << std::endl;
    std::cout << a.get_host() << std::endl;
    std::cout << a.get_port() << std::endl;
    
    auto paths = a.get_path();
    for(auto i : paths){
    
    
        std::cout << i << std::endl;
    } 
}

猜你喜欢

转载自blog.csdn.net/qq_37026934/article/details/129368735