日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

在C/C++语言中使用正则表达式

發(fā)布時(shí)間:2025/3/21 c/c++ 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在C/C++语言中使用正则表达式 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
本文所有的內(nèi)容都來自網(wǎng)絡(luò),加上一些個(gè)人的理解,不保證正確性,歡迎批評指正
  說起 正則表達(dá)式(Regular Expression),也許有的朋友天天都在使用,比如grep、vim、sed、awk,只是可能對這個(gè)名詞不大熟悉。 正則表達(dá)式一般簡寫為regex或者regexp,甚至是RE。關(guān)于 正則表達(dá)式的介紹,有很多的文章,用搜索引擎查找就可以找到很不錯(cuò)的使用說明。但是在C/C++語言中如何去使用,相應(yīng)的介紹比較缺乏。大多數(shù)C標(biāo)準(zhǔn)庫自帶regex,可以通過/usr/include/regex.h去看,或者man regex看使用說明。perl,php等語言更是提供了功能強(qiáng)大的 正則表達(dá)式,最著名的C語言 正則表達(dá)式庫為PCRE(Perl Compatible Regular Expression)。本文主要對regex和pcre的使用做一點(diǎn)入門介紹。
  1、regex
  regex的使用非常簡單,只要看一下示例代碼1就能明白(示例代碼是從“GNU C 規(guī)則表達(dá)式入門”這篇文章里摘取出來的,是否為原始出處就
  不得而知了)。
  CODE:#include <stdio.h>
  #include <string.h>
  #include <regex.h>
  #define SUBSLEN 10????????????? /* 匹配子串的數(shù)量 */
  #define EBUFLEN 128????????? /* 錯(cuò)誤消息buffer長度 */
  #define BUFLEN 1024????????? /* 匹配到的字符串buffer長度 */
  int main()
  {
  size_t?????? len;
  regex_t?????? re;????? /* 存儲(chǔ)編譯好的 正則表達(dá)式, 正則表達(dá)式在使用之前要經(jīng)過編譯 */
  regmatch_t??? subs [SUBSLEN]; /* 存儲(chǔ)匹配到的字符串位置 */
  char????????? matched [BUFLEN];???? /* 存儲(chǔ)匹配到的字符串 */
  char????????? errbuf [EBUFLEN]; /* 存儲(chǔ)錯(cuò)誤消息 */
  int????????? err, i;
  char????????? src??? [] = "111 <title>Hello World</title> 222"; /* 源字符串 */
  char????????? pattern [] = "<title>(.*)</title>"; /* pattern字符串 */
  printf("String : %s\n", src);
  printf("Pattern: \"%s\"\n", pattern);
  /* 編譯 正則表達(dá)式 */
  err = regcomp(&re, pattern, REG_EXTENDED);
  if (err) {
  len = regerror(err, &re, errbuf, sizeof(errbuf));
  printf("error: regcomp: %s\n", errbuf);
  return 1;
  }
  printf("Total has subexpression: %d\n", re.re_nsub);
  /* 執(zhí)行模式匹配 */
  err = regexec(&re, src, (size_t) SUBSLEN, subs, 0);
  if (err == REG_NOMATCH) { /* 沒有匹配成功 */
  printf("Sorry, no match ...\n");
  regfree(&re);
  return 0;
  } else if (err) {?? /* 其它錯(cuò)誤 */
  len = regerror(err, &re, errbuf, sizeof(errbuf));
  printf("error: regexec: %s\n", errbuf);
  return 1;
  }
  /* 如果不是REG_NOMATCH并且沒有其它錯(cuò)誤,則模式匹配上 */
  printf("\nOK, has matched ...\n\n");
  for (i = 0; i <= re.re_nsub; i++) {
  len = subs[i].rm_eo - subs[i].rm_so;
  if (i == 0) {
  printf ("begin: %d, len = %d?? ", subs[i].rm_so, len); /* 注釋1 */
  } else {
  printf("subexpression %d begin: %d, len = %d?? ", i, subs[i].rm_so, len);
  }
  memcpy (matched, src + subs[i].rm_so, len);
  matched[len] = '\0';
  printf("match: %s\n", matched);
  }
  regfree(&re); /* 用完了別忘了釋放 */
  return (0);
  }
  執(zhí)行結(jié)果是
  CODE:String : 111 <title>Hello World</title> 222
  Pattern: "<title>(.*)</title>"
  Total has subexpression: 1
  OK, has matched ...
  begin: %, len = 4?? match: <title>Hello World</title>
  subexpression 1 begin: 11, len = 11?? match: Hello World
  從示例程序可以看出,使用之前先用regcomp()編譯一下,然后調(diào)用regexec()進(jìn)行實(shí)際匹配。如果只是看有沒有匹配成功,掌握這2個(gè)函數(shù)的用法即可。有時(shí)候我們想要取得匹配后的子表達(dá)式,比如示例中想獲得title是什么,需要用小括號 "( )"把子表達(dá)式括起來"<title>(.*)</title>",表達(dá)式引擎會(huì)將小括號 "( )" 包含的表達(dá)式所匹配到的字符串記錄下來。在獲取匹配結(jié)果的時(shí)候,小括號包含的表達(dá)式所匹配到
  的字符串可以單獨(dú)獲取,示例程序就是我用來獲取http網(wǎng)頁的主題(title)的方式。
  regmatch_t subs[SUBSLEN]是用來存放匹配位置的,subs[0]里存放這個(gè)匹配的字符串位置,subs[1]里存放第一個(gè)子表達(dá)式的匹配位置,也就是例子中的title,通過結(jié)構(gòu)里的rm_so和rm_eo可以取到,這一點(diǎn)很多人不太注意,應(yīng)該強(qiáng)調(diào)一下。
  注釋1:開始調(diào)試代碼的時(shí)候是在FreeBSD 6.2上進(jìn)行的,print出來的len總是0,但print出來的字符串又沒錯(cuò),很是迷惑,把它放到Linux上則完全正常,后來仔細(xì)檢查才發(fā)現(xiàn)rm_so在Linux上是32位,在FreeBSD上是64位,用%d的話實(shí)際取的是rm_so的高32位,而不是實(shí)際的len,把print rm_so的地方改為%llu就可以了。
  regex雖然簡單易用,但對 正則表達(dá)式的支持不夠強(qiáng)大,中文處理也有問題,于是引出了下面要說的PCRE。
  2、PCRE?? ( http://www.pcre.org)
  PCRE的名字就說明了是Perl Compatible,熟悉Perl、PHP的人使用起來完全沒有問題。PCRE有非常豐富的使用說明和示例代碼(看看
  pcredemo.c就能明白基本的用法),下面的程序只是把上面regex改為pcre。
  CODE:/* Compile thuswise:
  * gcc -Wall pcre1.c -I/usr/local/include -L/usr/local/lib -R/usr/local/lib -lpcre
  *
  */
  #include <stdio.h>
  #include <string.h>
  #include <pcre.h>
  #define OVECCOUNT 30 /* should be a multiple of 3 */
  #define EBUFLEN 128
  #define BUFLEN 1024
  int main()
  {
  pcre????????? *re;
  const char??? *error;
  int????????? erroffset;
  int????????? ovector[OVECCOUNT];
  int????????? rc, i;
  char????????? src [] = "111 <title>Hello World</title> 222";
  char????????? pattern [] = "<title>(.*)</title>";
  printf("String : %s\n", src);
  printf("Pattern: \"%s\"\n", pattern);
  re = pcre_compile(pattern, 0, &error, &erroffset, NULL);
  if (re == NULL) {
  printf("PCRE compilation failed at offset %d: %s\n", erroffset, error);
  return 1;
  }
  rc = pcre_exec(re, NULL, src, strlen(src), 0, 0, ovector, OVECCOUNT);
  if (rc < 0) {
  if (rc == PCRE_ERROR_NOMATCH) printf("Sorry, no match ...\n");
  else printf("Matching error %d\n", rc);
  free(re);
  return 1;
  }
  printf("\nOK, has matched ...\n\n");
  for (i = 0; i < rc; i++) {
  char *substring_start = src + ovector[2*i];
  int substring_length = ovector[2*i+1] - ovector[2*i];
  printf("%2d: %.*s\n", i, substring_length, substring_start);
  }
  free(re);
  return 0;
  }
  執(zhí)行結(jié)果是:
  CODE:String : 111 <title>Hello World</title> 222
  Pattern: "<title>(.*)</title>"
  OK, has matched ...
  0: <title>Hello World</title>
  1: Hello World
  比較這2個(gè)例子可以看出,在regex用的是regcomp()、regexec(),pcre則使用pcre_compile()、pcre_exec(),用法幾乎完全一致。
  pcre_compile()有很多選項(xiàng),詳細(xì)說明參見 http://www.pcre.org/pcre.txt。如果是多行文本,可以設(shè)置PCRE_DOTALL的選項(xiàng)pcre_complie(re,
  PCRE_DOTALL,....),表示'.'也匹配回車換行"\r\n"。
  3、pcre++
  pcre++( http://www.daemon.de/PCRE)對pcre做了c++封裝,使用起來更加方便。
  CODE:/*
  * g++ pcre2.cpp -I/usr/local/include -L/usr/local/lib -R/usr/local/lib -lpcre++ -lpcre
  */
  #include <string>
  #include <iostream>
  #include <pcre++.h>
  using namespace std;
  using namespace pcrepp;
  int main()
  {
  string src("111 <title>Hello World</title> 222");
  string pattern("<title>(.*)</title>");
  cout << "String : " << src << endl;
  cout << "Pattern : " << pattern << endl;
  Pcre reg(pattern, PCRE_DOTALL);
  if (reg.search(src) == true) { //
  cout << "\nOK, has matched ...\n\n";
  for(int pos = 0; pos < reg.matches(); pos++) {
  cout << pos << ": " << reg[pos] << endl;
  }
  } else {
  cout << "Sorry, no match ...\n";
  return 1;
  }
  return 0;
  }
  執(zhí)行結(jié)果是:
  CODE:String : 111 <title>Hello World</title> 222
  Pattern : <title>(.*)</title>
  OK, has matched ...
  0: Hello World
  4、oniguruma
  還有一個(gè) 正則表達(dá)式的庫oniguruma( http://www.geocities.jp/kosako3/oniguruma/),對于東亞文字支持比較好,開始是用在ruby上,也可用于C++,是日本的開發(fā)人員編寫的。大多數(shù)人都不會(huì)用到,也就不做介紹了。如果有疑問可以通過email來討論它的用法。
  5、Regular Expression的內(nèi)部實(shí)現(xiàn)
  關(guān)于Regular Expression的實(shí)現(xiàn),用到了不少自動(dòng)機(jī)理論(Automata Theory)的知識,有興趣的可以找這方面的資料來看,這本書“
  Introduction to Automata Theory, Languages, and Computation”寫的很好,編譯原理的書也有這方面的內(nèi)容。 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的在C/C++语言中使用正则表达式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。