很多時候軟體用到解析一個文本的場合,比如解析一個TXT檔案,將有用的資料讀出來並進行處理;或者讀一個流檔案,找出對應的值取出來。執行個體如下,一個調試文本是如下格式:
// R, Gr, Gb, B per light source
0F12 4819 //,16,0},
/* Clock0, System clock 58MHz, PVI clock 48Mhz, (Preview) */
0F12 F000 //,16,0},
P10
0F12 FA05 //,16,0},
如上,文本構造是:寄存器地址跟Value為一組的序列組成,其中有注釋行,還有以P開頭的延時行。程式需要讀出地址和資料和延時,用來線上調試某些器件。大致程式如下:
uint16 init_reg[4000] = {0}; //寄存器數組,假設有4000個寄存器要寫入uint16 init_val[4000] = {0}; //參數值數組char* curr_ptr = NULL; //字元流指標char* buf ; //BUF是開啟檔案後的記憶體首指標curr_ptr = buf; //從檔案頭開始尋找 while (curr_ptr < (buf + file_size)) //檔案未遍曆完 { while ((*curr_ptr == ' ') || (*curr_ptr == '\t')) /* Skip the 每行開始的Space & TAB */ curr_ptr++; if (((*curr_ptr) == '/') && ((*(curr_ptr + 1)) == '*')) { while (!(((*curr_ptr) == '*') && ((*(curr_ptr + 1)) == '/'))) { curr_ptr++; /* Skip block comment code. */ } while (!((*curr_ptr == 0x0D) && (*(curr_ptr+1) == 0x0A))) //換行 { curr_ptr++; } curr_ptr += 2; /* Skip the enter line */ continue ; //開始下一行的尋找 } if (((*curr_ptr) == '/') && (*(curr_ptr + 1) == '/') ) /* Comment line, skip it. */ { while (!((*curr_ptr == 0x0D) && (*(curr_ptr+1) == 0x0A))) { curr_ptr++; } curr_ptr += 2; /* Skip the enter line */ continue ; //開始下一行的尋找 } /* This just content one enter line. */ if (((*curr_ptr) == 0x0D) && ((*(curr_ptr + 1)) == 0x0A)) //調過單獨的空行 { curr_ptr += 2; continue ; } if ('P' == *curr_ptr) //DELAY碰到延遲時間 { init_reg[i] = 0xFCFC; //延時寄存器 curr_ptr++; init_val[i] = simple_strtol(curr_ptr, NULL, 10); //以十進位把字串轉成資料賦給init_val[i] } else { init_reg[i] = simple_strtol(curr_ptr, NULL, 16); //以十六進位把字串轉成地址賦給init_reg[i] curr_ptr += 4; //跳過4個十六進位數的地址 char c; do{ c = *curr_ptr; if (('0' <= (c) && (c) <= '9') || ('a' <= (c) && (c) <= 'f') || ('A' <= (c) && (c) <= 'F')) { break; //跳過無效字元,直到碰到參數值 } curr_ptr++; }while(1); init_val[i] = simple_strtol(curr_ptr, NULL, 16); //以十六進位把字串轉成參數賦給init_val[i] } i++; //準備下一行待寫的資料 /* Skip to next line directly. */ while (!((*curr_ptr == 0x0D) && (*(curr_ptr+1) == 0x0A))) { curr_ptr++; } curr_ptr += 2; //轉下一行 }
遍曆完就可以從init_reg和init_val獲得要寫入的地址和參數。
===================================================================================================================
sscanf/sprintf的典型用法:
sprintf (&szBuffer[strlen(szBuffer)], " [%d, %s]", (int)ui32Line, pszFileName); //方向是從右向左,把右邊的參數按照格式儲存到左邊字串變數中。
sscanf(regBuf, "%2s", temp) ;
sscanf(temp, "%0x", &RegAddr) ; //方向是從左向右,把左邊的參數按照格式儲存到右邊的變數中。