前言

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

   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. C++ MD5类封装

    c++ md5 算法封装 md5.h #ifndef MD5_H #define MD5_H #include <string> #include <fstream> /* T ...

  2. Winform消息与并行的形象比喻

    有一次我给同事讲述跨线程调用时使用了高速行驶的并行列车来比喻,感觉比较形象. 线程列车 多线程就像多个并行的列车,每个线程在各自的轨道上不断向前行驶.主界面所在的线程称为UI线程,也叫主线程,主线程依 ...

  3. python学习:字符串

    字符串 #字符串操作# 对应操作:# 1.重复输出字符串# print('hello'*2)# 2.[],[:]通过索引获取字符串中字符,这里和列表的切片操作是相同的,具体内容见列表#print('h ...

  4. ajaj简介

    1. 什么是ajax? ajax的全称 Asynchronous(异步) JavaScript and XML. ajax是一种用于创建快速动态网页的技术. 主要用于前后台的交互,在前后台的交互中还有 ...

  5. 用万能马甲免费看VIP电影

    什么是:万能马甲? 它浏览器的一个扩展程序插件,安装后能看一些热门网址的VIP特权,免费观看付费电影等. 使用过程: 1. 访问网址:http://www.wndd123.com/ 点击免费看电影时提 ...

  6. Web开发者の实用代码账簿

    介里就都是恶魔菌整理的我平时会用的代码啦-现在在这里总结规划一下,希望能对你以及其他阅读这篇文章的小可耐们有帮助喵!欢迎订阅我的博客来get恶魔菌记事簿的新动态鸭! ↓ ↓ ↓ 以下就是内容啦~记得看 ...

  7. 怎么修改kodexplorer网盘下的版权

    前言: 要说kodexplorer,可是个好东西,在线web管理服务器文件,着实是网站管理员的好助手.内置的adminer管理数据库,用起来也是很顺手. 这么好的工具,还是免费的.但就是页面底部有ko ...

  8. [AtCoder 2702]Fountain Walk - LIS

    Problem Statement In the city of Nevermore, there are 108 streets and 108 avenues, both numbered fro ...

  9. Ubuntu下安装Pycharm出现unsupported major.minor version 52.0

    (一)原因 Ubuntu下pycharm安装:https://jingyan.baidu.com/article/60ccbceb4e3b0e64cab19733.html pycharm激活:htt ...

  10. -bash:syntax error near unexpected token '('

    在Xshell5中编写int main(int argc,char** argv)时, 出现-bash:syntax error near unexpected token '('  : 可是我是按照 ...