C正則
簡介
第一部分:C/C++如何使用正則获询;
第二部分:正則介紹
第三部分:C中使用部分正則的函數(shù)(sccanf涨岁,sprintf等)
第一部分:C/C++如何使用正則
一.介紹:
核心: 標(biāo)準(zhǔn)的C和C++都不支持正則表達式拐袜,但函數(shù)庫提供該功能:函數(shù)如下:
1)編譯正則表達式 regcomp()
2)匹配正則表達式 regexec()
3)釋放正則表達式 regfree()
4)獲取regcomp 或者regexec 產(chǎn)生錯誤吉嚣,獲取包含錯誤信息的字符串
- 函數(shù)聲明
int regcomp (regex_t *compiled, const char *pattern, int cflags)
參數(shù)1: regex_t *compiled—》一種特定的數(shù)據(jù)格式。
參數(shù)2: const char *pattern—》指定的正則表達式
參數(shù)3: 有如下4個值或者是它們或運算(|)后的值:
REG_EXTENDED 以功能更加強大的擴展正則表達式的方式進行匹配蹬铺。
REG_ICASE 匹配字母時忽略大小寫尝哆。
REG_NOSUB 不用存儲匹配后的結(jié)果。
REG_NEWLINE 識別換行符甜攀,'$'從行尾開始匹配秋泄,'^'從行開頭開始匹配琐馆。
作用: 將正則表達式編譯成regex_t結(jié)構(gòu)體格式。下面函數(shù)會處理編譯的正則表達式恒序。
返回值:成功返回0.
- int regexec (regex_t *compiled, char *string, size_t nmatch, regmatch_t matchptr [], int eflags)
作用: 使用編譯好的正則表達式瘦麸,進行匹配字符串—》找到想要的字符串
參數(shù)1: compiled 是用regcomp函數(shù)編譯好的正則表達式。
參數(shù)2: string 是目標(biāo)文本串歧胁。
參數(shù)3: nmatch 是regmatch_t結(jié)構(gòu)體數(shù)組的長度滋饲。
參數(shù)4: matchptr regmatch_t類型的結(jié)構(gòu)體數(shù)組,存放匹配文本串的位置信息喊巍。
即:用于把匹配結(jié)果返回給調(diào)用程序屠缭。
參數(shù)5:eflags 有兩個值
?取值1: REG_NOTBOL不匹配行的開頭,除非在 regcomp 編譯時 cflag 設(shè)置 REG_NEWLINE崭参。
'^'匹配行的開頭 , 不管 regexec 中是否設(shè)置 eflags 為 REG_NOTBOL 呵曹。
取值2: REG_NOTEOL不匹配行的結(jié)束,除非在 regcomp 編譯時 cflag 設(shè)置
REG_NEWLINE 何暮。'$' 匹配行的末尾 , 不管 regexec 中是否設(shè)置 eflags 為
REG_NOTEOL 奄喂。
返回值:執(zhí)行成功返回0。
- void regfree (regex_t *compiled)
作用: 清空compiled指向regex_t結(jié)構(gòu)體內(nèi)容海洼。如重新編譯砍聊,一定先清空regex_t結(jié)構(gòu)體。 - size_t regerror (int errcode, regex_t *compiled, char *buffer, size_t length)
作用:執(zhí)行前兩個函數(shù)產(chǎn)生錯誤的時候贰军,就可調(diào)用該函數(shù)而返回包含錯誤信息的字符串玻蝌。
參數(shù)1: errcode 是由regcomp 和 regexec 函數(shù)返回的錯誤代號。
參數(shù)2: compiled 是已經(jīng)用regcomp函數(shù)編譯好的正則表達式词疼,這個值可以為NULL俯树。
參數(shù)3:buffer 指向用來存放錯誤信息的字符串的內(nèi)存空間。如果不需要贰盗,可為空
參數(shù)4: length 指明buffer的長度许饿。如果該值小于錯誤信息長度:
函數(shù)會自動截斷超出的字符串,但他仍然會返回完整的字符串的長度舵盈。
size_t length = regerror (errcode, compiled, NULL, 0);
添加頭文件
#include <sys/types.h>
#include <regex.h>
第二部分:正則介紹
一.用于字符串操作
定義: 用事先定義好的特定字符組合陋率,進行“字符串匹配”的規(guī)律邏輯 。
組成: 普通字符+ 元字符(特殊字符秽晚,限定符瓦糟,定位符)
特殊字符—》特殊含義的字符
限定符------》限定出現(xiàn)的次數(shù);
定位符-----》限定出現(xiàn)的位置赴蝇;
1. 特殊字符
(1)$ 匹配輸入字符串的結(jié)尾位置菩浙。要匹配 $ 字符本身,請使用 \$。
(2)( ) 標(biāo)記一個子表達式的開始和結(jié)束位置劲蜻。
(3)* 匹配前面的子表達式零次或多次陆淀。 要匹配 * 字符請使用 \*。
(4)+ 匹配前面的子表達式一次或多次先嬉。 要匹配 + 字符請使用 \+轧苫。
(5)? 匹配前面的子表達式零次或一次。要匹配 ? 字符請使用 \?疫蔓。
(6). 匹配除換行符 \n 之外的任何單字符浸剩。要匹配 . 請使用 \. 。
(7)[ 標(biāo)記一個中括號表達式的開始鳄袍。 要匹配 [請使用 \[绢要。
集合介紹:
[xyz] 匹配所包含的任意一個字符。
[^xyz] 匹配未包含的任意字符拗小。
[a-z] 字符范圍重罪。匹配指定范圍內(nèi)的任意字符。
[^a-z] 負值字符范圍哀九。匹配任何不在指定范圍內(nèi)的任意字符剿配。
(8)\ 轉(zhuǎn)移字符,如:\? 就匹配到阅束?
(9)^ (方括號外[])匹配輸入字符串的開始位置;
(方括號內(nèi)[])表示不接受該字符集合呼胚。要匹配 ^ 字符本身,請使用 \^息裸。
(10){ 標(biāo)記限定符表達式的開始蝇更。要匹配 {請使用 \{。
(11)| 指明兩項之間的一個選擇呼盆。要匹配 |請使用 \|年扩。
例子:x|y 匹配 x 或 y。
2. 限定符(限定次數(shù))有 * 或 + 或 ? 或 {n} 或 {n,} 或 {n,m}
* 匹配前面的子表達式零次或多次访圃。 * 等價于{0,}
+ 匹配前面的子表達式一次或多次厨幻。 + 等價于 {1,}
? 匹配前面的子表達式零次或一次。 ? 等價于 {0,1}
{n} 匹配確定的 n 次腿时。
{n,} 至少匹配n 次况脆。
{n,m} 其中n <= m。最少匹配 n 次且最多匹配 m 次批糟。
例子:ZO* 可以匹配到Z格了,ZO,ZOO…跃赚,因為可以0次笆搓,即:不要前面的單個字符
3. 定位符(描述字符串或單詞的邊界)
^ 和 $ 分別指字符串的開始與結(jié)束,
\b 描述單詞的前或后邊界纬傲,
\B 表示非單詞邊界
4. 正則的優(yōu)先級
5. 例子簡介
(1)^[a-z][0-9]$ #重點是開頭满败,結(jié)束定位符的使用。
首先:[]優(yōu)先級最高叹括,位置限定^$較低算墨。
即:以一個字母開頭 加一個數(shù)字結(jié)束。
注意:沒有限定符汁雷,即一次净嘀,可以是s5,但不可以是s55侠讯。
(2)^[^0-9][0-9]$ #重點是[]內(nèi)的^ 與 []外的^區(qū)別
首先:[]內(nèi)的^ 是“排除”的意思挖藏,不是數(shù)字。加上[]外的^ :不以數(shù)字開頭厢漩;
然后:以數(shù)字結(jié)束的兩位字符膜眠。
(3)[^\\\/\^] 注意: \ 是轉(zhuǎn)義字符, \\, \/, \^
即:除了(\)(/)(^)之外的所有字符
部分三. C支持正則的函數(shù)(部分支持)
一.sscanf
#include <stdio.h>
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...); #文件輸入
int sscanf(const char *str, const char *format, ...);(用于拆分字符串)
相同點:都是可變參數(shù)溜嗜,都是輸入函數(shù)—》按照一定形式存入到…部分宵膨。
不同點:輸入原不同—》stdin(標(biāo)準(zhǔn)輸入)輸入;文件輸入炸宵;字符串輸入辟躏;
1. sscanf函數(shù)(從字符串提取數(shù)據(jù)):用于字符串操作!土全!
* 根據(jù)格式從字符串中提取數(shù)據(jù)捎琐。
* 取指定長度的字符串
* 取到指定字符為止的字符串
* 取僅包含指定字符集的字符串
* 取到指定字符集為止的字符串
(1)功能1: sscanf支持格式字符%[]
- 表示范圍,如:%[1-9]表示只讀取1-9這幾個數(shù)字
%[a-z]表示只讀取a-z小寫字 注:遇到不是的停止裹匙。
char s[]="hello, my friend”; // 注意, 逗號在不 a-z 之間
sscanf( s, “%[a-z]”, string ) ; // string=hello
^ 表示不取野哭,如:%[^1]表示讀取除'1'以外的所有字符
%[^/]表示除/以外的字符
例子: 如果碰到 a-z 之間的字符則停止
char s[]="HELLOkitty” ;
sscanf( s, “%[^a-z]”, string ) ; // string=HELLO
, 范圍可以用","相連接 如%[1-9,a-z]表示同時取1-9數(shù)字和a-z小寫字母
* 表示不保存變量, 跳過此數(shù)據(jù)不讀入. %*[^=] , %*s跳過符合條件的字符串幻件。
char s[]="notepad=1.0.0.1001" ;
int i = sscanf( s, "%*[^=]", string ) ; #為NULL, 因為沒保存
int i = sscanf( s, "%*[^=]=%s",string) ;
#為1.0.0.1001等號前不取拨黔,取等號后
(2)功能2 取指定長度的字符串—》取最大長度為4字節(jié)的字符串。
sscanf("123456 ", "%4s", buf);
printf("%s\n", buf); 結(jié)果為:1234
(3)功能3: 取到指定字符為止的字符串---》取遇到空格為止字符串绰沥。
sscanf("123456 abcdedf", "%[^ ]", buf); # 遇到空格結(jié)束
printf("%s\n", buf); 結(jié)果為:123456
(4)功能4: 取僅包含指定字符集的字符串---》取僅包含1到9和小寫字母的字符串篱蝇。
sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);
printf("%s\n", buf); 結(jié)果為:123456abcdedf
注:遇到不在范圍內(nèi)的就結(jié)束
(5)功能5: 取到指定字符集為止的字符串---》取遇到大寫字母為止的字符串。
sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);
printf("%s\n", buf); 結(jié)果為:123456abcdedf
歷程1:給定一個字符串iios/12DDWDFF@122徽曲,獲取 / 和 @ 之間的字符串零截,
先將 "iios/"過濾掉,再將非'@'的一串內(nèi)容送到buf中
sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf);
printf("%s\n", buf); 結(jié)果為:12DDWDFF
注:%s的結(jié)束條件—》遇回車(\n)或空格結(jié)束秃臣。
2. scanf()從控制臺輸入
int a,b,c;
printf("輸入 a, b, c\n");
scanf("%d,%d,%d", &a, &b, &c);
3. fscanf 從文件輸入,存入可變參數(shù)中
fscanf按照一定格式從文本中獲取內(nèi)容--》遇到空格和換行時結(jié)束(fgets遇到空格不結(jié)束)
FILE *fp;
char a[10]; int b; double c;
fscanf(fp,"%s%d%lf",a,&b,&c)
二.man printf 格式化輸出
1. 格式化輸出
共同點:將format后參數(shù)…按照format形式輸出涧衙;
不同點: 輸出到地方不同哪工,分別--》stdout,文件弧哎,字符串中雁比。
int printf(const char *format,***) #寫入stdout
?int fprintf(FILE *steam,const char *format,***) #寫入文件
?int sprintf(char *str,const char *format,***) #寫入到字符串(參數(shù)1)中撤嫩。
- sprintf的使用場景 :
場景1:格式化數(shù)字字符串--》 將整數(shù)轉(zhuǎn)換為字符串偎捎。
場景2:連接字符串--》 組合新的字符串(將幾個字符串合并連接)。
場景3: 控制浮點數(shù)打印格式
場景4: 打印地址信息
場景5: sprintf的返回值是本次調(diào)用打印到字符緩沖區(qū)中的字符數(shù)目
缺點: 可能出現(xiàn)問題內(nèi)存溢出序攘,第一個參數(shù)長度太短茴她,導(dǎo)致出現(xiàn)內(nèi)存溢出而程序崩潰。
改善: int snprintf(char *str, size_t n ,const char *format,*** )
#寫入n個字符到字符串中程奠。
函數(shù)說明:最多從源串中拷貝n-1個字符到字符緩沖區(qū)丈牢,然后在后面加一個 “\0” 。
函數(shù)返回值:若成功返回欲寫入的字符串長度瞄沙,出錯返回負值赡麦。
注意點:返回值是欲寫入的字符串長度,并不是實際寫入緩沖區(qū)中的長度帕识。
(1)輸出格式
b 解釋為整數(shù)并作為二進制輸出
c 解釋為整數(shù)并作為字符表示輸出(ASCII碼)
d 解釋為整數(shù)并作為整數(shù)輸出
e 解釋為浮點數(shù)輸出
f 解釋為雙精度并作為浮點數(shù)輸出
o 解釋為整數(shù)并作為八進制數(shù)輸出
s 解釋為字符串并為字符串輸出
u 解釋為無符號整數(shù)輸出
g 解釋自動選擇合適的表示法
p 解釋為指針的值 --》地址嗎
x 解釋為整數(shù)并作為帶有小寫字母a-f的十六進制數(shù)輸出
X 解釋為整數(shù)并作為帶有大寫字母A-F的十六進制數(shù)輸出
1). 可以在%”和字母(樣式)之間插進數(shù)字—》表示最大寬度泛粹。
%3d :表示輸出3位整型數(shù), 不夠3位右對齊。
%9.2f :表示輸出寬度9浮點數(shù), 小數(shù)位2, 整數(shù)位6, 小數(shù)點一位, 不夠右對齊肮疗。
%8s :表示輸出8個字符的字符串, 不夠8個字符右對齊晶姊。
注: 如果用浮點數(shù)表示—》字符或整型量的輸出格式,:
小數(shù)點后的數(shù)字代表最大寬度,
小數(shù)點前的數(shù)字代表最小寬度。
例如: %6.9s 表示長度不小于6且不大于9字符串伪货。若大于9, 則第9個字符后的內(nèi)容將被刪除们衙。
2). 可以在”%”和字母之間加小寫字母l, 表示輸出的是長型數(shù)。
%ld: 表示輸出long整數(shù)
%lf : 表示輸出double浮點數(shù)
3).在”%”和字母之間加入一個”-” 號可說明輸出為左對齊, 否則為右對齊碱呼。
%-7d: 表示輸出7位整數(shù)左對齊
4). 一些特殊規(guī)定字符
①\n 換行 ②\f 清屏并換頁 ③\r 回車 ④\t Tab符
(2)sprintf()使用
用途1: 格式化數(shù)字字符串蒙挑,代替 itoa()
sprintf(s, “%d”, 123); # 產(chǎn)生”123”
可以指定寬度,不足的左邊補空格:
sprintf(s, “%8d%8d”, 123, 4567); //產(chǎn)生:“ 123 4567”
也可以左對齊:
sprintf(s, “%-8d%8d”, 123, 4567); //產(chǎn)生:“123 4567”
用途2:控制浮點數(shù)打印格式(即:可控制浮點數(shù)的位數(shù))
格式: ”%m.nf”愚臀,其中m 表示打印的寬度忆蚀,n 表示小數(shù)點后的位數(shù)。
sprintf(s, “%10.3f”, 3.1415626); # 產(chǎn)生:” 3.142”
sprintf(s, “%.3f”, 3.1415626); # 不指定總寬度姑裂,產(chǎn)生:”3.142”
用途3: 連接字符串(替代strcat)馋袜,且更強大
char* who = “I”;
char* whom = “you”;
sprintf(s, “%s love %s.”, who, whom); //要求:參數(shù)1的要足夠大,不溢出
注:也可以前后都只取部分字符:
char a1[] = {‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’};
char a2[] = {‘H’, ‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’};
sprintf(s, “%.6s%.5s”, a1, a2);//產(chǎn)生:”ABCDEFHIJKL”
注: 指定長度的數(shù)字可以是動態(tài)的舶斧,采用”*”來占用寬度或精度的常數(shù)位置
sprintf(s, “%.*s%.*s”, 7, a1, 7, a2);
用途4: 打印地址信息
間接地址打有辣睢: 十進制”%u” ,16 進制%x
直接地址打印%p: sprintf(s, “%p”, &i);
用途5: 利用sprintf 的返回值
返回值: 本次函數(shù)調(diào)用最終打印到字符緩沖區(qū)中的字符數(shù)目茴厉。
所以:其返回值就是偏移量泽台,可以用于計數(shù)等什荣,即寫入的總長度:
offset += sprintf(s + offset, “%d,”, rand() % 100);
s[offset - 1] = ‘\n’;//將最后的逗號換成回車
- fprintf()的使用---》用于文件操作
int fprintf(FILE *stream, const char *format, ...) 發(fā)送格式化輸出到流 stream 中
fp = fopen ("file.txt", "w+");
fprintf(fp, "%s %s %s %d", "We", "are", "in", 2014);
fclose(fp);
- 不定數(shù)量參數(shù) 的格式化輸出
int vsprintf(char *string, char *format, va_list param);
例子如下:vsprintf 是sprintf 的一個變形,用于執(zhí)行有不定數(shù)量參數(shù)的函數(shù)怀酷。
參數(shù)1: 用于保存結(jié)果的字符串緩沖區(qū)
參數(shù)2: 一個格式化字符串稻爬。
參數(shù)3: 是指向格式化參數(shù)隊列的指針。va_list胰坟、va_start和va_end宏(STDARG.H)
char buffer[256];
int vsceshi(char *format, ...)
{
va_list aptr;
int ret;
va_start(aptr, format);
ret = vsprintf(buffer, format, aptr); //將結(jié)構(gòu)存儲到 buffer中
va_end(aptr);
return(ret);
}
調(diào)用如下:vsceshi("%d %s", i, str);
其余:略