The strspn function computes the length of the maximum initial segment of the string pointed to by s1 which consists entirely of characters from the string pointed to by s2. 函數的參數s2指向的字符串組成了一個接受字符集,注意不包含字符串結束標志’/0’,這個字符比較特殊。s2中字符的重復出現并不影響函數的返回值。 函數完成的功能是根據接受字符集對s1指向的字符串從頭開始匹配,直到發現一個不在接受字符集中的字符(或是到達字符串的結尾,這也意味著匹配結束),然后返回匹配字符的數量。
在查看C99標準的這段英文描述時,要注意一個詞匯”the string pointed to by s1”中的”string”,指針指向的數據一般由三種情況: - string - array - object 這三個詞匯代表的含義略有不同。string一定是字符串,以’/0’結尾;array可能是字符串,也可能是普通的內存塊,在函數實現中,如果遇到了’/0’,那么要將它當成字符串,知道目前已經到了結尾了;而object則看做內存塊,實現中不會根據值為0的字節而武斷的認為到了結尾。 例如:
void *memchr(const void *s, int c, size_t n);/* ... the object pointed to by s ... */int strncmp(const char *s1, const char *s2, size_t n);/* ... the array pointed to by s1 ... */可見C標準的措辭嚴謹。 掌握這些措辭的細節,對理解函數的實現和使用是有幫助的。
這段代碼的難點在于BITOP宏的理解。 byteset數組大小為32個字節,32*8=256個位,我們知道char類型數據的長度是8位,最多有256個不同的char數據,而byteset恰是256位,每個位對應了一個char類型的字符,看到這你有可能猜到了函數的主體是如何實現的。 第一個for循環,根據s2指向的字串統計接受字符集。 試舉一例,通過查ascii碼我們知道 01100001 97 a 如果遇到了’a’,那么BITOP(…)操作的效果是byteset的第(97-1)位設置為1。這代表’a’是可接受字符。 第二個for循環是從頭開始匹配s1中的每個字符。發生不匹配時立刻停止。 使用bitmap可以極大的節約存儲空間,其中的位操作乍看之下讓人眼花繚亂,但是讀懂之后想要重構的更簡單,貌似也沒有更好的辦法,讀懂之后也跟作者一樣連注釋也懶得添加。這種算法比嵌套的兩層循環要節約很多時間,值得花些時間來理解(走過,路過,不要錯過)。
新聞熱點
疑難解答