2019-04-21 C正則璧亚,sprintf,sccanf

                                        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)生錯誤吉嚣,獲取包含錯誤信息的字符串
  1. 函數(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.

  1. 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。
  1. void regfree (regex_t *compiled)
    作用: 清空compiled指向regex_t結(jié)構(gòu)體內(nèi)容海洼。如重新編譯砍聊,一定先清空regex_t結(jié)構(gòu)體。
  2. 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)先級

2.png

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 格式化輸出

3.png

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)中撤嫩。
  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’;//將最后的逗號換成回車
  1. 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);
  1. 不定數(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); 
  其余:略
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末因篇,一起剝皮案震驚了整個濱河市泞辐,隨后出現(xiàn)的幾起案子笔横,更是在濱河造成了極大的恐慌,老刑警劉巖咐吼,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吹缔,死亡現(xiàn)場離奇詭異,居然都是意外死亡锯茄,警方通過查閱死者的電腦和手機厢塘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肌幽,“玉大人晚碾,你說我怎么就攤上這事∥辜保” “怎么了格嘁?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長廊移。 經(jīng)常有香客問我糕簿,道長,這世上最難降的妖魔是什么狡孔? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任懂诗,我火速辦了婚禮,結(jié)果婚禮上苗膝,老公的妹妹穿的比我還像新娘殃恒。我一直安慰自己,他們只是感情好辱揭,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布芋类。 她就那樣靜靜地躺著,像睡著了一般界阁。 火紅的嫁衣襯著肌膚如雪侯繁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天泡躯,我揣著相機與錄音贮竟,去河邊找鬼丽焊。 笑死,一個胖子當(dāng)著我的面吹牛咕别,可吹牛的內(nèi)容都是我干的技健。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼惰拱,長吁一口氣:“原來是場噩夢啊……” “哼雌贱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起偿短,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤欣孤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后昔逗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體降传,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年勾怒,在試婚紗的時候發(fā)現(xiàn)自己被綠了婆排。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡笔链,死狀恐怖段只,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鉴扫,我是刑警寧澤赞枕,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站幔妨,受9級特大地震影響鹦赎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜误堡,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一古话、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锁施,春花似錦陪踩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至姥饰,卻和暖如春傻谁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背列粪。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工审磁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谈飒,地道東北人。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓态蒂,卻偏偏與公主長得像杭措,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子钾恢,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容