C++ 正则库与HTTP请求

news2024/11/26 2:28:58

正则表达式的概念和语法

用于描述和匹配字符串的工具,通过特定的语法规则,灵活的定义复杂字符串匹配条件

常用语法总结

  • 基本字符匹配

    • a:匹配字符'a'
    • abc:匹配字符串'abc'
  • 元字符(特殊含义的字符)

    • .:匹配任意单个字符(除了换行符)
    • ^:匹配字符串的开始位置
    • $:匹配字符串的结束位置
    • *:匹配前面的元素零次或多次
    • +:匹配前面的元素一次或多次
    • ?:匹配前面的元素零次或一次
    • |:表示逻辑“或”操作
    • \:转义字符,用于匹配特殊字符
  • 字符类(匹配一组字符中的任意一个

    • [abc]:匹配'a'、'b'或'c'
    • [a-z]:匹配所有小写字母
    • [^abc]:匹配除'a'、'b'、'c'之外的任意字符
  • 预定义字符类

    • \d:匹配任何数字,等价于[0-9]
    • \D:匹配任何非数字字符
    • \w:匹配任何字母、数字或下划线,等价于[a-zA-Z0-9_]
    • \W:匹配任何非字母、数字或下划线字符
    • \s:匹配任何空白字符(空格、制表符等)
    • \S:匹配任何非空白字符
  • 重复限定符

    • {n}:匹配前面的元素恰好n次
    • {n,}:匹配前面的元素至少n次
    • {n,m}:匹配前面的元素至少n次,至多m次
  • 分组与捕获(分组和捕获匹配的字符串)

    • (abc):匹配'abc',并捕获该匹配
    • (?:abc):匹配'abc',但不捕获该匹配
  • 断言(匹配位置)

    • (?=...):正向先行断言,要求后面的字符必须匹配
    • (?!...):负向先行断言,要求后面的字符不能匹配
    • (?<=...):正向后行断言,要求前面的字符必须匹配
    • (?<!...):负向后行断言,要求前面的字符不能匹配

 

使用

 创建正则表达式对象

正则匹配(检查是否一致);正则搜索(只要包含即可) 

 

正则替换:通过正则表达式,对字符串中的字符进行更换 

 

提取匹配的子字符串,提取的子字符串都存储在了smatch中 

 

处理异常:使用try_catch捕获异常 

 

测试代码汇总 

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

int main()
{
    // std::regex pattern("abc");
    //正则匹配
    // std::string str = "abcddfd";
    // if(std::regex_match(str,pattern))
    // {
    //     std::cout<<"match fount"<<std::endl;
    // }
    // else 
    // {
    //     std::cout<<"match not found"<<std::endl;
    // }

    // //正则搜索(只要有查询的字符即可)
    // if(std::regex_search(str,pattern))
    // {
    //     std::cout<<"search found"<<std::endl;
    // }
    // else
    // {
    //     std::cout<<"search not fount"<<std::endl;
    // }

    // //正则替换
    // std::string replaced = std::regex_replace(str,pattern,"mmm");
    // std::cout<<replaced<<std::endl;

    //提取匹配的子字符串
    std::string str1 = "abc123";
    std::regex pattern("(abc)(\\d+)");
    std::smatch matches;
    if(std::regex_search(str1,matches,pattern))
    {
        for(size_t i =0;i<matches.size();i++)
        {
            std::cout << "Match " << i << ": " << matches[i].str() << std::endl;
        }
    }

    return 0;
}

HTTP解析和响应 

解析请求分析

 

([A-Z]+)

  • [A-Z]:匹配单个大写字母。
  • +:匹配前面的字符一次或多次,即匹配一个或多个大写字母。
  • ():捕获组,用于提取匹配的子字符串。
  • 这个部分匹配HTTP方法,如 GETPOSTPUT 等。

(.+)

  • .:匹配任意单个字符(除换行符外)。
  • +:匹配前面的字符一次或多次,即匹配一个或多个任意字符。
  • ():捕获组,用于提取匹配的子字符串。
  • 这个部分匹配请求的路径,如 /index.html

HTTP/([0-9\\.]+)

  • HTTP/:匹配字符串 HTTP/
  • [0-9\\.]:匹配数字(0-9)或点号(.)。
  • +:匹配前面的字符一次或多次,即匹配一个或多个数字或点号。
  • ():捕获组,用于提取匹配的子字符串。
  • 这个部分匹配HTTP版本号,如 1.1

\r\n

  • \r:匹配回车符。
  • \n:匹配换行符。
  • 这个部分匹配HTTP请求行的结尾。

 解析头部字段

([A-Za-z-]+)

  • [A-Za-z-]:匹配单个字母(大小写皆可)或连字符。
  • +:匹配前面的字符一次或多次,即匹配一个或多个字母或连字符。
  • ():捕获组,用于提取匹配的子字符串。
  • 这个部分匹配头部字段的名称,如 HostUser-AgentAccept

  • 匹配冒号和一个空格,作为头部字段名称与值的分隔符。

(.+)

  • .:匹配任意单个字符(除换行符外)。
  • +:匹配前面的字符一次或多次,即匹配一个或多个任意字符。
  • ():捕获组,用于提取匹配的子字符串。
  • 这个部分匹配头部字段的值,如 www.example.comcurl/7.68.0*/* 等。

/r/n

  • \r:匹配回车符。
  • \n:匹配换行符。
  • 这个部分匹配头部字段行的结尾

 

构成响应

  • 构建状态行:HTTP版本+状态码+状态描述符
  • 构建头部字段:遍历headers哈希表,将其加入到响应字符串职工
  • 构建响应体:头部字段后添加一个空行\r\n,然后追加响应体内容 

 

完整测试代码

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

struct HttpRequest {
    std::string method;
    std::string path;
    std::string version;
    std::map<std::string, std::string> headers;
    std::string body;
};

HttpRequest parseHttpRequest(const std::string& request) {
    HttpRequest httpRequest;
    std::regex requestLinePattern("([A-Z]+) (.+) HTTP/([0-9\\.]+)\r\n");
    std::regex headerPattern("([A-Za-z-]+): (.+)\r\n");

    std::smatch matches;

    // 解析请求行
    if (std::regex_search(request, matches, requestLinePattern)) {
        httpRequest.method = matches[1].str();
        httpRequest.path = matches[2].str();
        httpRequest.version = matches[3].str();
    }

    // 解析头部字段
    auto headersBegin = std::sregex_iterator(request.begin(), request.end(), headerPattern);
    auto headersEnd = std::sregex_iterator();

    for (std::sregex_iterator i = headersBegin; i != headersEnd; ++i) {
        std::smatch match = *i;
        httpRequest.headers[match[1].str()] = match[2].str();
    }

    // 查找请求体的开始位置
    size_t bodyPos = request.find("\r\n\r\n");
    if (bodyPos != std::string::npos) {
        httpRequest.body = request.substr(bodyPos + 4);
    }

    return httpRequest;
}

std::string generateHttpResponse(const std::string& status, const std::map<std::string, std::string>& headers, const std::string& body) {
    std::string response = "HTTP/1.1 " + status + "\r\n";
    
    for (const auto& header : headers) {
        response += header.first + ": " + header.second + "\r\n";
    }
    
    response += "\r\n" + body;
    return response;
}

int main() {
    std::string request = "GET /index.html HTTP/1.1\r\nHost: www.example.com\r\nUser-Agent: curl/7.68.0\r\nAccept: */*\r\n\r\n";
    
    // 解析HTTP请求
    HttpRequest httpRequest = parseHttpRequest(request);
    
    // 打印解析结果
    std::cout << "Method: " << httpRequest.method << std::endl;
    std::cout << "Path: " << httpRequest.path << std::endl;
    std::cout << "Version: " << httpRequest.version << std::endl;
    for (const auto& header : httpRequest.headers) {
        std::cout << header.first << ": " << header.second << std::endl;
    }
    std::cout << "Body: " << httpRequest.body << std::endl;

    // 生成HTTP响应
    std::map<std::string, std::string> headers = {
        {"Content-Type", "text/html"},
        {"Content-Length", "13"}
    };
    std::string body = "<h1>Hello</h1>";
    std::string response = generateHttpResponse("200 OK", headers, body);
    
    // 打印响应报文
    std::cout << response << std::endl;

    return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1941502.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【医学影像】RK3588+FPGA:满足远程诊疗系统8K音视频编解码及高效传输需求

医学影像 提供基于Intel平台、NXP平台、Rockchip平台的核心板、Mini-ITX主板、PICO-ITX主板以及工业整机等计算机硬件。产品板载内存&#xff0c;集成超高清编码/解码视频引擎&#xff0c;具有出色的数据处理能力和图形处理能力&#xff0c;功能高集成&#xff0c;可应用于超声…

可信推荐系统论文分享-1

《Debiasing Recommendation by Learning Identifiable Latent Confounders》

openmv学习笔记(24电赛备赛笔记)

#openmv简介 openmv一种小型&#xff0c;可编程机器视觉摄像头&#xff0c;设计应用嵌入式应用和计算边缘&#xff0c;是图传模块&#xff0c;或者认为是一种&#xff0c;具有图像处理功能的单片机&#xff0c;提供多种接口&#xff08;I2C SPI UART CAN ADC DAC &#xff0…

【BUG】已解决:Uncaught SyntaxError: Unexpected token ‘<‘

已解决&#xff1a;Could not install packages due to an EnvironmentError: [Errno 13] Permission denied 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市开发者社区主理人 …

如何训练出模型的推理规划能力

背景 近期opanai对AGI做了等级划分&#xff1b;等级划分意味着AGI有了一个考核定义&#xff0c;有了升级打怪的评价指标。并给出了目前openai正处在第一级&#xff0c;即将达到第二级的论断。预计在一年或者一年半内实现第二级&#xff0c;可以完成基本问题解决任务的系统。 …

抖音客户端一面

C | 字节抖音客户端一面 Http握手过程 1. 客户端问候(Client Hello) 客户端向服务器发送一个“问候”消息&#xff0c;其中包含客户端支持的SSL/TLS版本、加密算法、压缩方法以及一个随机数。 version 版本号,https也有版本号哦TLS 1.0、TLS 1.1、TLS 1.2等等 random 随机数…

【Linux】进程信号 --- 信号保存

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

Linux中进程间通信--匿名管道和命名管道

本篇将会进入 Linux 进程中进程间通信&#xff0c;本篇简要的介绍了 Linux 中进程为什么需要通信&#xff0c;进程间通信的常用方式。然后详细的介绍了 Linux 进程间的管道通信方式&#xff0c;管道通信分为匿名管道和命名管道&#xff0c;本篇分别介绍了其实现的原理&#xff…

4.Java Web开发模式(javaBean+servlet+MVC)

Java Web开发模式 一、Java Web开发模式 1.javaBean简介 JavaBeans是Java中一种特殊的类&#xff0c;可以将多个对象封装到一个对象&#xff08;bean&#xff09;中。特点是可序列化&#xff0c;提供无参构造器&#xff0c;提供getter方法和setter方法访问对象的属性。名称中…

顺序 IO 和 随机IO

顺序 IO 和 随机IO 顺序IO 和 随机IO 是计算机存储系统领域中的概念&#xff0c;主要涉及数据的读取和写入方式。这些术语通常在讨论硬盘驱动器&#xff08;HDDs&#xff09;、固态驱动器&#xff08;SSD&#xff09;以及其他存储设备的性能时使用。 顺序IO&#xff08;Sequen…

TeamViewer关闭访问密码或固定一组密码不变

TeamViewer的新UI界面变化较大&#xff0c;网上的一些信息已经不再有效&#xff0c;更新后的访问密码在如下图所示&#xff1a; 演示的版本为7.21.4—— 设置每次你的设备访问的密码

Hi6274 反激式20瓦电源芯片

HI6274为高性能多模式 PWM 反激式20瓦电源芯片。HI6274较少的外围元器件、较低的系统成本可设计出高性能的"无Y"开关电源。HI6274提供了极为全面和性能优异的智能化保护功能&#xff0c;包括逐周期过流保护、过载保护、软启动、芯片过温保护、可编程输出过压保护功能…

Kettle 登录示例 POST请求

登录接口是post请求&#xff0c;组装Body为json字符串 var body "{\"username\":\""username"\",\"password\": \""password"\",\"code\":\""verification"\",\"uuid\…

【算法/训练】:前缀和差分

&#x1f680; 前言&#xff1a; 前面我们已经通过 【算法/学习】前缀和&&差分-CSDN博客 学习了前缀和&&差分的效相关知识&#xff0c;现在我们开始进行相关题目的练习吧 1. 校门外的树 思路&#xff1a;给[0, n]的数组都标记为1&#xff0c;然后输出m行范围…

初学Mybatis之配置解析

MyBatis 中文网配置教程 mybatis-config.xml 环境配置&#xff08;environments&#xff09; 尽管可以配置多个环境&#xff0c;但每个 SqlSessionFactory 实例只能选择一种环境 可以有多个 enviroment&#xff0c;但是 enviroments default&#xff08;默认&#xff09;只…

Linux:Linux发展史

大家好&#xff01;此篇文章并非技术博文&#xff0c;而是简单了解Linux的时代背景和发展史&#xff0c;只有知其所以然才能让我们更好地让走进Liunx的世界&#xff01; 一、计算机的发展历史背景 首先我们要知道&#xff0c;早期大多数科技的进步都是以国家的对抗为历史背景的…

【优秀设计案例】基于K-Means聚类算法的球员数据聚类分析设计与实现

背景及意义 随着NBA比赛的日益竞争激烈&#xff0c;球队需要更加深入地了解球员的能力和特征&#xff0c;以制定更有效的战术和球队管理策略。而NBA球员的统计数据包含了大量有价值的信息&#xff0c;通过对这些数据进行聚类分析&#xff0c;可以揭示出球员之间的相似性和差异…

Java生成四位纯数字并且确保唯一性

背景&#xff1a; 给了我一个需求&#xff0c;由于某些问题原因&#xff0c;需要给属性和数据添加一个code字段&#xff0c;这是给我发的消息 这两个要求其实是同一个需求&#xff0c;就是在创建对象的时候塞入一个unique的code嘛&#xff0c;听起来很简单吧&#xff0c;但是实…

WPF串口通讯程序

目录 一 设计原型 二 后台源码 一 设计原型 二 后台源码 using HardwareCommunications; using System.IO.Ports; using System.Windows;namespace PortTest {/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainW…

二叉树精选面试题

&#x1f48e; 欢迎大家互三&#xff1a;2的n次方_ 1. 相同的树 100. 相同的树 同时遍历两棵树 判断结构相同&#xff1a;也就是在遍历的过程中&#xff0c;如果有一个节点为null&#xff0c;另一棵树的节点不为null&#xff0c;那么结构就不相同 判断值相同&#xff1a;只需…