1. 程式人生 > >從iniparser中瞭解到強大的sscanf字串處理函式

從iniparser中瞭解到強大的sscanf字串處理函式

最近在學習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;
}

真乃為解析字串之大器!