c语言sscanf使用正则表达式

C 語言中的 scanf 函數,是初學者都會使用的,但也是大部分人都會誤用,或者是無法充分發揮其功能的。

C 語言的 sscanf() 與 ssprintf() 這兩個函數,採用的是一種既創新又好用的設計法,

事實上,函數 sscanf() 比 scanf() 更為好用,sscanf() 甚至支援了類似 Regular Expression 的功能,可以讓我們輕易的剖析格式化的字串。

sscanf 的函數原形如下,其中的 format 格式字串具有複雜的格式指定功能,以下我們將詳細說明這些格式的用途。

int sscanf ( const char * str, const char * format, ...);

str : 被剖析的字串
format: 剖析格式

在 format 字串中,以 % 起頭者為剖析段落,通常在剖析完成後會指定給後面的變數,其格式語法如下:

剖析段落的語法:%[*][width][modifiers]type

  % 代表變數開始

  * 代表省略不放入變數中

  width 代表最大讀取寬度

  modifier 可以是 {h|I|L} 之一
  說明 : 其中 h 代表 2 byte 的變數 (像 short int),
              l 代表 4 byte 的變數 (像 long int),
              L 代表 8 byte 的變數 (像 long double)

  type 則可以是 c, d,e,E,f,g,G,o, s, u, x, X 等基本型態,
       也可以是類似 Regular Expression 的表達式。
  說明: c : 字元 (char); 
        d : 整數 (Decimal integer); 
        f : 浮點數 (Floating Point); 
        e,E : 科學記號 (Scientific notation); 
        g,G : 取浮點數或科學記號當中短的那個; 
        o : 八進位 (Octal Integer); 
        u : 無號數 (unsigned integer); 
        x, X : 十六進位 (Hexadecimal integer)

為了說明 sscanf 函數的用法,我們寫了以下程式,以示範 format 欄位的各種寫法。

檔案:sscanf.c

#include <stdio.h>

int main() {
  char name[20], tel[50], field[20], areaCode[20], code[20];
  int age;
  sscanf("name:john age:40 tel:082-313530", "%s", name);
  printf("%s\n", name);
  sscanf("name:john age:40 tel:082-313530", "%8s", name);
  printf("%s\n", name);
  sscanf("name:john age:40 tel:082-313530", "%[^:]", name);
  printf("%s\n", name);
  sscanf("name:john age:40 tel:082-313530", "%[^:]:%s", field, name);
  printf("%s %s\n", field, name);
  sscanf("name:john age:40 tel:082-313530", "name:%s age:%d tel:%s", name, &age, tel);
  printf("%s %d %s\n", name, age, tel);
  sscanf("name:john age:40 tel:082-313530", "%*[^:]:%s %*[^:]:%d %*[^:]:%s", name, &age, tel);
  printf("%s %d %s\n", name, age, tel);
  
  char protocol[10], site[50], path[50];
  sscanf("http://ccckmit.wikidot.com/cp/list/hello.txt", 
         "%[^:]:%*2[/]%[^/]/%[a-zA-Z0-9._/-]", 
         protocol, site, path);
  printf("protocol=%s site=%s path=%s\n", protocol, site, path);
  return 1;
}

其編譯執行結果如下所示。

D:\oc>gcc sscanf.c -o sscanf

D:\oc>sscanf
name:john
name:joh
name
name john
john 40 082-313530
john 40 082-313530
protocol=http site=ccckmit.wikidot.com path=cp/list/hello.txt

程式碼解析

您應該可以看到,在上述程式碼當中,所有的 %s, %d 等輸入欄位,預設都是以空白做為結尾的,例如以下指令就只會掃描到 name="name:john",因為後面是空白了,所以就把 %s 的內容丟到了變數 name 當中。

  sscanf("name:john age:40 tel:082-313530", "%s", name);
  printf("%s\n", name);

如果我們在 %s 等樣式中指定長度,像是以下這個 sscanf 所採用的 %8s,那麼掃描到 8 個字元之後就會停止了,所以此時 name="name:joh" 。

  sscanf("name:john age:40 tel:082-313530", "%8s", name);
  printf("%s\n", name);

但是我們可以透過類似正規表達式的語法,來設定掃描的方式,舉例而言,像是以下的 sscanf 所採用的 %[^:] ,就讓我們 可以掃描到 : 符號為止,其中的樣式 [^abc] 符號代表不要比對 a, b, c 這些字元,所以 [^:] 代表的是不可比對到 : 這個符號,因此就會在比對到該符號時停止了。於是掃描的結果會是 name="name" 。

  sscanf("name:john age:40 tel:082-313530", "%[^:]", name);
  printf("%s\n", name);

當然、這些 %s, %d 等樣式之間還可以串接,以便進行連續掃描,因此下面這個 sscanf 指令可以一次掃出 field 與 name 兩個欄位, 結果會是 field="name", name="john" 。

  sscanf("name:john age:40 tel:082-313530", "%[^:]:%s", field, name);
  printf("%s %s\n", field, name);

而且、在掃描到整數或浮點等非字串欄位時,還會將掃描到的結果轉為該型態放入變數中,例如下列 sscanf 指令中的 &age 欄位, 就會直接得到整數值,不需要像一般正規表達式那樣還需要經過轉型才能使用。

  sscanf("name:john age:40 tel:082-313530", "name:%s age:%d tel:%s", name, &age, tel);
  printf("%s %d %s\n", name, age, tel);

如果我們希望某些欄位在掃描後,直接丟棄而不要存入任何變數中,那麼就可以用 %*... 這種加上 * 號的格式,此時 sscanf 會知道要將該欄位丟棄,不要存入到後面的變數裏。

  sscanf("name:john age:40 tel:082-313530", "%*[^:]:%s %*[^:]:%d %*[^:]:%s", name, &age, tel);
  printf("%s %d %s\n", name, age, tel);

甚至、我們可以真的把 sscanf 當成「正規表達式」使用,只是語法稍有差異,功能也不像正規表達式那麼強,不過通常也夠用了。

舉例而言,以下的 sscanf 可以將一個網址剖析成 protocol, site, path 等三個段落,您可以看到我們使用的 "%[^:]:%*2[/]%[^/]/%[a-zA-Z0-9._/-]" 這個樣式,看起來是不是真的很像「正規表達式」呢?

  char protocol[10], site[50], path[50];
  sscanf("http://ccckmit.wikidot.com/cp/list/hello.txt", 
         "%[^:]:%*2[/]%[^/]/%[a-zA-Z0-9._/-]", 
         protocol, site, path);
  printf("protocol=%s site=%s path=%s\n", protocol, site, path);
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
sscanfC语言中的一个函数,用于从字符串中按照指定的格式读取数据。它的原型如下: ```c int sscanf(const char *str, const char *format, ...); ``` `str`是要解析的字符串,`format`是解析的格式字符串,后面的参数是要读取的变量。 例如,假设有一个字符串`"name: John, age: 25"`,我们可以使用sscanf来解析出名字和年龄: ```c char name[20]; int age; sscanf("name: John, age: 25", "name: %s, age: %d", name, &age); ``` 在这个例子中,`%s`表示按照字符串的格式读取,`%d`表示按照整数的格式读取。`name`和`age`分别是要读取的变量。 正则表达式是一种强大的文本匹配工具,用于在字符串中查找特定模式的内容。在C语言中,可以使用正则表达式库来实现正则表达式的功能,例如POSIX标准库中的`regex.h`。 使用正则表达式需要先编译正则表达式模式,然后使用相应的函数进行匹配操作。以下是一个简单的示例: ```c #include <stdio.h> #include <regex.h> int main() { regex_t regex; int ret; char str[] = "Hello, World!"; char pattern[] = "Hello"; ret = regcomp(&regex, pattern, 0); if (ret) { printf("Failed to compile regex\n"); return ret; } ret = regexec(&regex, str, 0, NULL, 0); if (!ret) { printf("String matches pattern\n"); } else if (ret == REG_NOMATCH) { printf("String does not match pattern\n"); } else { printf("Failed to execute regex\n"); return ret; } regfree(&regex); return 0; } ``` 在这个例子中,我们使用`regcomp`函数编译正则表达式模式,然后使用`regexec`函数匹配字符串和模式。如果匹配成功,返回值为0;如果不匹配,返回值为`REG_NOMATCH`。 以上是关于sscanf正则表达式的简单介绍,希望能对你有帮助!如果有任何疑问,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值