前言

   首先,祝大家国庆假期玩的嗨皮!可能有的人已经在回家的路上了,是不是都看不到我的真挚祝福了?

   C语言对于一些东西的封装比较少,比如正则表达式,但速度快一直使它立于不败之地,今天就要介绍如何用C封装。

   一、正则表达式

     1、介绍

    应该都听过正则吧?主要应用在字符串匹配,而且它是通用的,各种语言都支持。例如可以用它匹配IP地址、邮箱等。举个例子说明一下正则有啥用:

    例如,我在的公司,页面用PHP,后台用C,当添加用户邮箱时,我们老大就要求:PHP和C都要对用户输入的用户邮箱进行校验,这时正则表达式就派上用场了。

   2、grep命令    

    我会用grep进行简单的举例,所以要简单介绍一下。    

    grep是一种查找过滤工具,正则表达式在grep中用来查找符合模式的字符串。其实正则表达式还有一个重要的应用是验证用户输入是否合法,例如用户通过网页表单提交自己的email地址,就需要用程序验证一下是不是合法的email地址,这个工作可以在网页的Javascript中做,也可以在网站后台的程序中做,例如PHP、Perl、Python、Ruby、Java或C,所有这些语言都支持正则表达式,可以说,目前不支持正则表达式的编程语言实在很少见。

    egrep相当于grep -E,表示采用Extended正则表达式语法。

    注意grep找的是包含某一模式的行,而不是完全匹配某一模式的行。

   3、基本语法

    对于正则表达式的语法,我只列出比较常见的,基本就够用了,如果有兴趣的可以再去网上学习,去深入了解。

    字符类

   

   数量限定符

    

   位置限定符

  

  举例:查找IP的正则

  用^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$查找

  其它特殊字符

  

  4、分类

  大致分为两类:Basic正则和Extended正则

  区别:

  以上介绍的是grep正则表达式的Extended规范,Basic规范也有这些语法,只是字符?+{}|()应解释为普通字符,要表示上述特殊含义则需要加\转义。如果用grep而不是egrep,并且不加-E参数,则应该遵照Basic规范来写正则表达式。

  二、正则表达式相关函数

  C语言处理正则表达式常用的函数有regcomp()、regexec()、regfree()和regerror()

  C语言中使用正则表达式一般分为三步:

  • 编译正则表达式 regcomp()
  • 匹配正则表达式 regexec()
  • 释放正则表达式 regfree()

  下边将对三个函数的详细解释。

  1、regcomp函数

  功能:这个函数把指定的正则表达式pattern编译成一种特定的数据格式compiled,这样可以使匹配更有效。

  原型:int regcomp(regex_t *preg, const char *regex, int cflags);

  参数说明: 

  regex_t     是一个结构体数据类型,用来存放编译后的正则表达式,它的成员re_nsub 用来存储正则表达式中的子正则表达式的个数,子正则表达式就是用圆括号包起来的部分表达式。

 参数regex:     是指向我们写好的正则表达式的指针。

 参数cflags:      有如下4个值或者是它们或运算(|)后的值:

REG_EXTENDED    以功能更加强大的扩展正则表达式的方式进行匹配。

REG_ICASE         匹配字母时忽略大小写。

REG_NOSUB         不用存储匹配后的结果,只返回是否成功匹配。如果设置该标志位,那么在regexec(在下边介绍)将忽略nmatch和pmatch两个参数。

REG_NEWLINE     识别换行符,这样'$'就可以从行尾开始匹配,'^'就可以从行的开头开始匹配。

  2、regexec函数

  功能:函数regexec 会使用这个数据在目标文本串中进行模式匹配。 

  原型:int regexec(const regex_t *preg, const char *string, size_t nmatch,regmatch_t pmatch[], int eflags);

  先来介绍下参数4中的regmatch_t结构体: 

  regmatch_t 是一个结构体数据类型,在regex.h中定义:

typedef struct {

regoff_t rm_so;

regoff_t rm_eo;

} regmatch_t;

  成员rm_so 存放匹配文本串在目标串中的开始位置,rm_eo 存放结束位置。通常我们以数组的形式定义一组这样的结构。

  参数说明: 

  preg    是已经用regcomp函数编译好的正则表达式。

  string      是目标文本串。

  nmatch      是regmatch_t结构体数组的长度。

  matchptr    regmatch_t类型的结构体数组,存放匹配文本串的位置信息。

  eflags 有两个值:

 REG_NOTBOL 让特殊字符^无作用

REG_NOTEOL 让特殊字符$无作用

  3、regfree函数

  功能:可以用这个函数清空regex_t结构体的内容  

  原型:void regfree(regex_t *preg);

  4、regerror函数

  功能:当执行regcomp 或者regexec 产生错误的时候,就可以调用这个函数而返回一个包含错误信息的字符串。

  原型:size_t regerror(int errcode, const regex_t *preg, char *errbuf,size_t errbuf_size);

  参数说明:

  errcode     是由regcomp 和 regexec 函数返回的错误代号。

  preg   是已经用regcomp函数编译好的正则表达式,这个值可以为NULL。

  errbuf     指向用来存放错误信息的字符串的内存空间。

  errbuf_size     指明buffer的长度,如果这个错误信息的长度大于这个值,则regerror 函数会自动截断超出的字符串,但他仍然会返回完整的字符串的长度。所以我们可以用如下的方法先得到错误字符串的长度。

  三、程序示例

  输入两个参数,第一个参数:正则表达式,第二个参数:字符串,校验是否匹配,程序如下:

  

#include <sys/types.h>
#include <regex.h>
#include <stdio.h> int main(int argc, char ** argv)
{
if (argc != ) {
printf("Usage: %s RegexString Text\n", argv[]);
return ;
}
const char * pregexstr = argv[];
const char * ptext = argv[];
regex_t oregex;
int nerrcode = ;
char szerrmsg[] = {};
size_t unerrmsglen = ;
if ((nerrcode = regcomp(&oregex, pregexstr, REG_EXTENDED|REG_NOSUB)) == ) {
if ((nerrcode = regexec(&oregex, ptext, , NULL, )) == ) {
printf("%s matches %s\n", ptext, pregexstr);
regfree(&oregex);
return ;
}
}
unerrmsglen = regerror(nerrcode, &oregex, szerrmsg, sizeof(szerrmsg));
unerrmsglen = unerrmsglen < sizeof(szerrmsg) ? unerrmsglen : sizeof(szerrmsg) - ;
szerrmsg[unerrmsglen] = '\0';
printf("ErrMsg: %s\n", szerrmsg);
regfree(&oregex); return ;
}

  演示匹配邮箱:

  执行:./a.out "^[a-zA-Z0-9]+@[a-zA-Z0-9]+.[a-zA-Z0-9]+" "ldw@itcast.com"

  演示结果如下:

  

  总结

  希望喜欢的点关注,不迷路哦!会持续更新linux C/C++相关内容,谢谢支持!

  

C语言用regcomp、regexec、regfree和regerror函数实现正则表达式校验的更多相关文章

  1. C语言正则表达式详解 regcomp() regexec() regfree()详解

    标准的C和C++都不支持正则表达式,但有一些函数库可以辅助C/C++程序员完成这一功能,其中最著名的当数Philip Hazel的Perl-Compatible Regular Expression库 ...

  2. [转]C语言文件输入/输出ACM改进版(freopen函数)

    C语言文件输入/输出ACM改进版(freopen函数) 2009年5月27日 10:379,457 浏览数发表评论阅读评论   文章作者:姜南(Slyar) 文章来源:Slyar Home (www. ...

  3. 智能合约语言 Solidity 教程系列10 - 完全理解函数修改器

    这是Solidity教程系列文章第10篇,带大家完全理解Solidity的函数修改器. Solidity系列完整的文章列表请查看分类-Solidity. 写在前面 Solidity 是以太坊智能合约编 ...

  4. PHP 语言结构(Language constructs)和函数的区别

    相信大家经常看到对比一些PHP应用中,说用isset() 替换 strlen(),isset比strlen执行速度快等. 例子: if ( isset($username[5]) ) { // The ...

  5. regcomp/regexec/regfree--POSIX regex functions

    语法 #include <sys/types.h> #include <regex.h> int regcomp(regex_t *preg, const char *rege ...

  6. C语言中的回调函数调用过程以及函数指针使用

    回调函数比喻: 你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货. 在这个例子里,你的电话号码就叫回调 ...

  7. TCL语言笔记:TCL中的数学函数

    一.TCL数学函数列表 函数名 说明 举例 abs(arg) 取绝对值 set a –10  ; #a=-10 set a [expr abs($a)]; # a=10 acos(arg) 反余弦 s ...

  8. c程序设计语言_习题1-16_自己编写getline()函数,接收整行字符串,并完整输出

    Revise the main routine of the longest-line program so it will correctly print the length of arbitra ...

  9. c语言里用结构体和指针函数实现面向对象思想

    一.基础研究 观察如下两个程序a.c和b.c: A.c: B.c: 这两个程序都是要实现在屏幕上第10行40列打印一个绿色的字符c: 这两个程序的数据组织方式是一样的,都是使用结构体,而且对共性和个性 ...

随机推荐

  1. LOJ.6435.[PKUSC2018]星际穿越(倍增)

    LOJ BZOJ 参考这儿qwq. 首先询问都是求,向左走的最短路. \(f[i][j]\)表示从\(i\)走到\(j\)最少需要多少步.表示这样只会\(O(n^2\log n)\)的= =但是感觉能 ...

  2. dotnet core 3.0 linux 部署小贴士

    dotnet core 3.0 目前还是测试版,在linux下安装 sdk 需要有一些注意事项 1.下载url https://dotnet.microsoft.com/download/thank- ...

  3. [CF1132G]Greedy Subsequences

    [CF1132G]Greedy Subsequences 题目大意: 定义一个序列的最长贪心严格上升子序列为:任意选择第一个元素后,每次选择右侧第一个大于它的元素,直到不能选为止. 给定一个长度为\( ...

  4. 解析时间parse time

    下面是一个解析时间的一个类 <?php /** * @purpose : 解析时间 * author: 袋鼠 * date: 2019/3/1 * time: 19:43 */ class Pa ...

  5. docker之使用System.Drawing生成图片缺少Gdiplus.dll错误

    1.在docker 上找到并运行需要System.Drawing的镜像 然后退出执行另一语句 docker run -it container01 进入镜像以方便安装gdiplus docker ex ...

  6. H5本地存储详细使用教程(localStorage + JSON数据存储应用框架)

    一.Web Storage教程 1.概述: 对于Web Storage来说,实际上是Cookies存储的进化版.如果了解Cookie的人几乎一看Web Storage就会用,如果你从来没用过没了解过C ...

  7. 理解pytorch中的softmax中的dim参数

    import torch import torch.nn.functional as F x1= torch.Tensor( [ [1,2,3,4],[1,3,4,5],[3,4,5,6]]) y11 ...

  8. java方法的调用

    各种方法的调用实例 package cn.edu.fhj.day004; public class FunctionDemo { // 定义全局的变量 public int a = 3; public ...

  9. Django之csrf防御机制

    1.csrf攻击过程 csrf攻击说明: 1.用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A; 2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站 ...

  10. scala 2.11.x/spec/03-types.md

    scala/spec/03-types.md title: Types layout: default chapter: 3 --- Types Type ::= FunctionArgTypes ' ...