從iniparser中瞭解到強大的sscanf字串處理函式
阿新 • • 發佈:2019-01-25
最近在學習iniparser的原始碼,發現了C語言處理字串的大器(sscanf)!
具體的原始碼如下:
函式功能:解析一行字串,識別出 節名,鍵名,鍵值。
/*-------------------------------------------------------------------------*/
/**
@brief Load a single line from an INI file
@param input_line Input line, may be concatenated multi-line input 可能存在拼接行
@param section Output space to store section
@param key Output space to store key
@param value Output space to store value
@return line_status value
*/
/*--------------------------------------------------------------------------*/
static line_status iniparser_line(
const char * input_line,
char * section,
char * key,
char * value)
{
line_status sta ;
char * line = NULL;
size_t len ;
line = xstrdup(input_line); //將入參存入臨時變數
len = strstrip(line); //刪除多於的空格
sta = LINE_UNPROCESSED ;
if (len<1) {
/* Empty line 空行 */
sta = LINE_EMPTY ;
} else if (line[0 ]=='#' || line[0]==';') {
/* Comment line 註釋行 */
sta = LINE_COMMENT ;
} else if (line[0]=='[' && line[len-1]==']') {
/* Section name 節名 */
sscanf(line, "[%[^]]", section); //跳過'[',取[]之間的字串內容
strstrip(section);
strlwc(section, section, len); //轉換成小寫字元
sta = LINE_SECTION ;
} else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2 //等號左邊的值作為key,右邊作為value
|| sscanf (line, "%[^=] = '%[^\']'", key, value) == 2) { // \' \" -- 表示轉義字元
/* Usual key=value with quotes, with or without comments */ // 其中value帶引號
strstrip(key);
strlwc(key, key, len);
/* Don't strip spaces from values surrounded with quotes */
sta = LINE_VALUE ;
} else if (sscanf (line, "%[^=] = %[^;#]", key, value) == 2) {
/* Usual key=value without quotes, with or without comments */
strstrip(key);
strlwc(key, key, len);
strstrip(value);
/*
* sscanf cannot handle '' or "" as empty values
* this is done here
*/
if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) {
value[0]=0 ;
}
sta = LINE_VALUE ;
} else if (sscanf(line, "%[^=] = %[;#]", key, value)==2
|| sscanf(line, "%[^=] %[=]", key, value) == 2) {
/*
* Special cases:
* key=
* key=;
* key=#
*/
strstrip(key);
strlwc(key, key, len);
value[0]=0 ;
sta = LINE_VALUE ;
} else {
/* Generate syntax error */
sta = LINE_ERROR ;
}
free(line);
return sta ;
}
下面咱們就來深度的剖析一下該神器,其中有用到了一些正則表示式的知識
這邊先列出一些基本的規則,我們之後一一驗證
1. %[^=] ; %[^A-Z] ; %[^;#] –取出特殊符號集(等號、A-Z、;#)之前的字串
2. [% ; a-c% ; @#% –過濾字串之前特殊符號集([、 a-c、 @#)
3. %s ; %[0-9] ; –過濾字串之後特殊符號集(string、 0-9),該引數不需要儲存
4. %[0-9] ; –取出匹配特殊符號集的字串(0-9)
總結為, 左邊為需要過濾的內容 << % >> 右邊為需要取出的內容
測試程式碼如下:
/*****************************************************
* ** Name : ini_sscanf.c
* ** Author : lamar
* ** Version : 1.0
* ** Date : 2018-03
* ** Description : test sscanf function
* ******************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
static void ini_sscanf(void)
{
int ret;
char *str;
char buf_1[1024];
char buf_2[1024];
char buf_3[1024];
str = "Year=\"2018\"";
ret = sscanf (str, "%[^=] = \"%[^\"]\"", buf_1, buf_2);
printf("ret:%d, buf_1:%s buf_2:%s \n", ret, buf_1, buf_2);
//執行結果:ret:2, buf_1:Year buf_2:2018
str = "abcYear=@#2018";
ret = sscanf (str, "a%[^=]=%s", buf_1, buf_2);
printf("ret:%d, buf_1:%s buf_2:%s \n", ret, buf_1, buf_2);
//執行結果:ret:2, buf_1:bcYear buf_2:@#2018
str = "abOcYear=@#2018";
ret = sscanf (str, "%[a-z] %[^0-9]", buf_1, buf_3);
printf("ret:%d, buf_1:%s buf_3:%s \n", ret, buf_1, buf_3);
//執行結果:ret:2, buf_1:ab buf_3:OcYear=@#
str = "abc=2018 year";
ret = sscanf (str, "abc=%[0-9] %[^r]", buf_1, buf_2);
printf("ret:%d, buf_1:%s buf_2:%s \n", ret, buf_1, buf_2);
//執行結果:ret:2, buf_1:2018 buf_2:yea
str = "abc=2018 @@#lamar";
ret = sscanf (str, "%*[^@] %[@#] %[a-z]", buf_1, buf_2);
printf("ret:%d, buf_1:%s buf_2:%s \n", ret, buf_1, buf_2);
//執行結果:ret:2, buf_1:@@# buf_2:lamar
return ;
}
int main()
{
ini_sscanf();
printf("end the main function\n");
return 0;
}
真乃為解析字串之大器!