• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 200, comments - 8, trackbacks - 0, articles - 0

                           第四章、現場編寫類似strstr/strcpy/strpbrk的函數   

             

            作者:July。
                說明: 如果在博客中代碼使用了\n,csdn blog系統將會自動回給我變成/n。據后續驗證,可能是原來舊blog版本的bug,新版已不存在此問題。至于,本文代碼,日后統一修正。July、2012.05.02。  
                微博:http://weibo.com/julyweibo  。
                出處:http://blog.csdn.net/v_JULY_v 
                wiki:http://tctop.wikispaces.com/
            ----------------------------------------------


            前奏

                有網友向我反應,之前三章(http://t.cn/hgVPmH)的面試題目,是否有點太難了。誠如他所說,絕大部分公司的面試題不會像微軟等公司的面試題目出的那么變態,或復雜。

                面試考察的是你對基礎知識的掌握程度,及編程能力是否過硬的一種檢測,所以,扎實基礎知識,提高編程能力,比去看什么所謂的面經,或去背面試題目的答案強多了。

                很多中、小型公司自己的創造能力,包括人力,物力資源都有限,所以,他們的面試題目除了copy一些大公司的題庫之外(當然,考察你對基礎知識的掌握情況,是肯定不會放過的),還有一個途徑就是讓你在限定時間內(如十分鐘),當場實現一些類似strcpy/strcat/strpbrk等庫函數,這個主要看你對細節的把握,以及編程能力是否之扎實了。

                同時,本章里出現的代碼(除了第4節的c標準庫部分源碼)都是個人限定在短時間內(正好,突出現場感)編寫的,很多問題,難免有所考慮不周。所以,如果你發現本章任何一段代碼有任何問題,懇請不吝指正。


            第一節、字符串查找
            1.1題目描述:
            給定一個字符串A,要求在A中查找一個子串B。
            如A="ABCDF",要你在A中查找子串B=“CD”。

            分析:比較簡單,相當于實現strstr庫函數,主體代碼如下:

            1. //在字符串中查找指定字符串的第一次出現,不能找到則返回-1      
            2. int strstr(char *string, char *substring)      
            3. {     
            4.     if (string == NULL || substring == NULL)        
            5.         return -1;        
            6.       
            7.     int lenstr = strlen(string);     
            8.     int lensub = strlen(substring);     
            9.       
            10.     if (lenstr < lensub)        
            11.         return -1;         
            12.       
            13.     int len = lenstr - lensub;  
            14.     for (int i = 0; i <= len; i++)   //復雜度為O(m*n)     
            15.     {     
            16.         for (int j = 0; j < lensub; j++)     
            17.         {     
            18.             if (string[i+j] != substring[j])     
            19.                 break;     
            20.         }     
            21.         if (j == lensub)     
            22.             return i + 1;     
            23.     }     
            24.     return -1;     
            25. }    

             

                讀者反饋@xiaohui5319:樓主啊,對于你那個strstr的函數,我覺得有點小問題。我查了一下C標準庫的源碼,它給的聲明是這樣的,兩個參數都有const。

            char *

            STRSTR (const char *haystack_start, const char *needle_start)

                而且標準庫中沒有調用strlen函數,因為假如你是標準庫的設計者,strlen()函數還沒設計出來,你怎么去計算兩個字符串的長度?是不是只能通過指針移動來實現,我覺得這些都是微軟要考察的地方。

                此外:還有int lenstr=strlen(string);這是不安全的?
                strlen函數的返回類型是size_t型,也就是無符號整型,假如我的數組長度很長(假如是用堆分配的,可以很大很大),長過2的31次方減1的話,會發生一處,你這lenstr就會變成負值了
                用size_t類型最保險。

                以后,本編程藝術系列中有任何問題,暫未來得及及時修正,請讀者多加思考,多加辨明

                上述程序已經實現了在字符串中查找第一個子串的功能,時間復雜度為O(n*m),也可以用KMP算法,復雜度為O(m+n)。為人打通思路,提高他人創造力,我想,這是狂想曲與其它的面試解答所不同的地方,也是我們寫狂想曲系列文章的意義與價值之所在。

            1.2、題目描述

            在一個字符串中找到第一個只出現一次的字符。如輸入abaccdeff,則輸出b。 

            代碼則可以如下編寫:

            1. //查找第一個只出現一次的字符,     
            2. //copyright@ yansha     
            3. //July、updated,2011.04.24.     
            4. char FirstNotRepeatChar(char* pString)     
            5. {     
            6.     if(!pString)     
            7.         return '/0';     
            8.       
            9.     const int tableSize = 256;    
            10.     //有點要提醒各位注意,一般常數的空間消耗,如這里的256,我們也認為此空間復雜度為O(1)。  
            11.     int hashTable[tableSize] = {0}; //存入數組,并初始化為0     
            12.       
            13.     char* pHashKey = pString;     
            14.     while(*(pHashKey) != '/0')     
            15.         hashTable[*(pHashKey++)]++;     
            16.       
            17.     while(*pString != '/0')     
            18.     {     
            19.         if(hashTable[*pString] == 1)     
            20.             return *pString;     
            21.           
            22.         pString++;     
            23.     }     
            24.     return '/0';  //沒有找到滿足條件的字符,退出     
            25. }    

             

            代碼二,bitmap:

            1. # include<stdio.h>  
            2. # include<string.h>  
            3.   
            4. const int N = 26;  
            5. int bit_map[N];  
            6.   
            7. void findNoRepeat(char *src)  
            8. {  
            9.     int pos;  
            10.     char *str = src;  
            11.     int i ,len = strlen(src);  
            12.       
            13.     //統計  
            14.     for(i = 0 ; i < len ;i ++)  
            15.         bit_map[str[i]-'a'] ++;  
            16.       
            17.     //從字符串開始遍歷 其bit_map==1 那么就是結果  
            18.     for(i = 0 ; i < len ; i ++)  
            19.     {  
            20.         if(bit_map[str[i]-'a'] == 1)  
            21.         {  
            22.             printf("%c",str[i]);  
            23.             return ;  
            24.         }  
            25.     }  
            26. }  
            27.   
            28. int main()  
            29. {     
            30.     char *src = "abaccdeff";  
            31.     findNoRepeat(src);  
            32.     printf("/n");  
            33.     return 0;  
            34. }  
              

             

            第二節、字符串拷貝
            題目描述:
            要求實現庫函數strcpy,
            原型聲明:extern char *strcpy(char *dest,char *src); 
            功能:把src所指由NULL結束的字符串復制到dest所指的數組中。  
            說明:src和dest所指內存區域不可以重疊且dest必須有足夠的空間來容納src的字符串。  
            返回指向dest的指針。

                分析:如果編寫一個標準strcpy函數的總分值為10,下面給出幾個不同得分的答案

            1. //得2分     
            2. void strcpy( char *strDest, char *strSrc )     
            3. {     
            4.     while( (*strDest++ = * strSrc++) != '/0' );     
            5. }      
            6.   
            7. //得4分     
            8. void strcpy( char *strDest, const char *strSrc )      
            9. {     
            10.     //將源字符串加const,表明其為輸入參數,加2分     
            11.     while( (*strDest++ = * strSrc++) != '/0' );     
            12. }      
            13.   
            14. //得7分     
            15. void strcpy(char *strDest, const char *strSrc)      
            16. {     
            17.     //對源地址和目的地址加非0斷言,加3分     
            18.     assert( (strDest != NULL) && (strSrc != NULL) );     
            19.     while( (*strDest++ = * strSrc++) != '/0' );     
            20. }      
            21.   
            22. //得9分     
            23. //為了實現鏈式操作,將目的地址返回,加2分!     
            24. char * strcpy( char *strDest, const char *strSrc )      
            25. {     
            26.     assert( (strDest != NULL) && (strSrc != NULL) );     
            27.     char *address = strDest;      
            28.     while( (*strDest++ = * strSrc++) != '/0' );      
            29.     return address;     
            30. }    
            31.   
            32. //得10分,基本上所有的情況,都考慮到了  
            33. //如果有考慮到源目所指區域有重疊的情況,加1分!     
            34. char * strcpy( char *strDest, const char *strSrc )      
            35. {     
            36.     if(strDest == strSrc) { return strDest; }  
            37.     assert( (strDest != NULL) && (strSrc != NULL) );     
            38.     char *address = strDest;      
            39.     while( (*strDest++ = * strSrc++) != '/0' );      
            40.     return address;     
            41. }    

             

            第三節、小部分庫函數的實現
                考察此類編寫同庫函數一樣功能的函數經常見于大大小小的IT公司的面試題目中,以下是常見的字符串庫函數的實現,希望,對你有所幫助,有任何問題,歡迎不吝指正:

            1. //@yansha:字串末尾要加結束符'/0',不然輸出錯位結果  
            2. char *strncpy(char *strDes, const char *strSrc, unsigned int count)      
            3. {      
            4.     assert(strDes != NULL && strSrc != NULL);      
            5.     char *address = strDes;      
            6.     while (count-- && *strSrc != '/0')      
            7.         *strDes++ = *strSrc++;   
            8.     *strDes = '/0';  
            9.     return address;      
            10. }   
            11.   
            12. //查找字符串s中首次出現字符c的位置   
            13. char *strchr(const char *str, int c)   
            14. {   
            15.     assert(str != NULL);   
            16.     for (; *str != (char)c; ++ str)   
            17.         if (*str == '/0')   
            18.             return NULL;   
            19.         return str;   
            20. }   
            21.   
            22. int strcmp(const char *s, const char *t)   
            23. {   
            24.     assert(s != NULL && t != NULL);   
            25.     while (*s && *t && *s == *t)   
            26.     {   
            27.         ++ s;   
            28.         ++ t;   
            29.     }   
            30.     return (*s - *t);   
            31. }   
            32.   
            33. char *strcat(char *strDes, const char *strSrc)   
            34. {   
            35.     assert((strDes != NULL) && (strSrc != NULL));   
            36.     char *address = strDes;   
            37.     while (*strDes != '/0')   
            38.         ++ strDes;   
            39.     while ((*strDes ++ = *strSrc ++) != '/0')   
            40.         NULL;   
            41.     return address;   
            42. }   
            43.   
            44. int strlen(const char *str)   
            45. {   
            46.     assert(str != NULL);   
            47.     int len = 0;   
            48.     while (*str ++ != '/0')   
            49.         ++ len;   
            50.     return len;   
            51. }   
            52.   
            53. //此函數,夢修改如下     
            54. char *strdup_(char *strSrc)     
            55. //將字符串拷貝到新的位置     
            56. {     
            57.     if(strSrc!=NULL)     
            58.     {     
            59.         char *start=strSrc;     
            60.         int len=0;     
            61.         while(*strSrc++!='/0')     
            62.             len++;     
            63.           
            64.         char *address=(char *)malloc(len+1);     
            65.         assert(address != NULL);  
            66.           
            67.         while((*address++=*start++)!='/0');      
            68.         return address-(len+1);      
            69.     }     
            70.     return NULL;     
            71. }     
            72.   
            73. //多謝laoyi19861011指正  
            74. char *strstr(const char *strSrc, const char *str)   
            75. {   
            76.     assert(strSrc != NULL && str != NULL);   
            77.     const char *s = strSrc;   
            78.     const char *t = str;   
            79.     for (; *strSrc != '/0'; ++ strSrc)   
            80.     {   
            81.         for (s = strSrc, t = str; *t != '/0' && *s == *t; ++s, ++t)   
            82.             NULL;   
            83.         if (*t == '/0')   
            84.             return (char *) strSrc;   
            85.     }   
            86.     return NULL;   
            87. }   
            88.   
            89. char *strncat(char *strDes, const char *strSrc, unsigned int count)   
            90. {   
            91.     assert((strDes != NULL) && (strSrc != NULL));   
            92.     char *address = strDes;   
            93.     while (*strDes != '/0')   
            94.         ++ strDes;   
            95.     while (count -- && *strSrc != '/0' )   
            96.         *strDes ++ = *strSrc ++;   
            97.     *strDes = '/0';   
            98.     return address;   
            99. }   
            100.   
            101. int strncmp(const char *s, const char *t, unsigned int count)   
            102. {   
            103.     assert((s != NULL) && (t != NULL));   
            104.     while (*s && *t && *s == *t && count --)   
            105.     {   
            106.         ++ s;   
            107.         ++ t;   
            108.     }   
            109.     return (*s - *t);   
            110. }   
            111.   
            112. char *strpbrk(const char *strSrc, const char *str)   
            113. {   
            114.     assert((strSrc != NULL) && (str != NULL));   
            115.     const char *s;   
            116.     while (*strSrc != '/0')   
            117.     {   
            118.         s = str;   
            119.         while (*s != '/0')   
            120.         {   
            121.             if (*strSrc == *s)   
            122.                 return (char *) strSrc;   
            123.             ++ s;   
            124.         }   
            125.         ++ strSrc;   
            126.     }   
            127.     return NULL;   
            128. }   
            129.   
            130. int strcspn(const char *strSrc, const char *str)   
            131. {   
            132.     assert((strSrc != NULL) && (str != NULL));   
            133.     const char *s;   
            134.     const char *t = strSrc;   
            135.     while (*t != '/0')   
            136.     {   
            137.         s = str;   
            138.         while (*s != '/0')   
            139.         {   
            140.             if (*t == *s)   
            141.                 return t - strSrc;   
            142.             ++ s;   
            143.         }   
            144.         ++ t;   
            145.     }   
            146.     return 0;   
            147. }   
            148.   
            149. int strspn(const char *strSrc, const char *str)   
            150. {   
            151.     assert((strSrc != NULL) && (str != NULL));   
            152.     const char *s;   
            153.     const char *t = strSrc;   
            154.     while (*t != '/0')   
            155.     {   
            156.         s = str;   
            157.         while (*s != '/0')   
            158.         {   
            159.             if (*t == *s)   
            160.                 break;   
            161.             ++ s;   
            162.         }   
            163.         if (*s == '/0')   
            164.             return t - strSrc;   
            165.         ++ t;   
            166.     }   
            167.     return 0;   
            168. }   
            169.   
            170. char *strrchr(const char *str, int c)   
            171. {   
            172.     assert(str != NULL);   
            173.     const char *s = str;   
            174.     while (*s != '/0')   
            175.         ++ s;   
            176.     for (-- s; *s != (char) c; -- s)   
            177.         if (s == str)   
            178.             return NULL;   
            179.         return (char *) s;   
            180. }   
            181.   
            182. char* strrev(char *str)   
            183. {   
            184.     assert(str != NULL);   
            185.     char *s = str, *t = str, c;   
            186.     while (*t != '/0')   
            187.         ++ t;   
            188.     for (-- t; s < t; ++ s, -- t)   
            189.     {   
            190.         c = *s;   
            191.         *s = *t;   
            192.         *t = c;   
            193.     }   
            194.     return str;   
            195. }   
            196.   
            197. char *strnset(char *str, int c, unsigned int count)   
            198. {   
            199.     assert(str != NULL);   
            200.     char *s = str;   
            201.     for (; *s != '/0' && s - str < count; ++ s)   
            202.         *s = (char) c;   
            203.     return str;   
            204. }   
            205.   
            206. char *strset(char *str, int c)   
            207. {   
            208.     assert(str != NULL);   
            209.     char *s = str;   
            210.     for (; *s != '/0'; ++ s)   
            211.         *s = (char) c;   
            212.     return str;   
            213. }   
            214.   
            215. //@heyaming  
            216. //對原 strtok 的修改,根據MSDN,strToken可以為NULL.實際上第一次call strtok給定一字串,  
            217. //再call strtok時可以輸入NULL代表要接著處理給定字串。  
            218. //所以需要用一 static 保存沒有處理完的字串。同時也需要處理多個分隔符在一起的情況。  
            219. char *strtok(char *strToken, const char *str)  
            220. {  
            221.     assert(str != NULL);  
            222.     static char *last;  
            223.       
            224.     if (strToken == NULL && (strToken = last) == NULL)  
            225.         return (NULL);  
            226.       
            227.     char *s = strToken;  
            228.     const char *t = str;  
            229.     while (*s != '/0')  
            230.     {  
            231.         t = str;  
            232.         while (*t != '/0')  
            233.         {  
            234.             if (*s == *t)  
            235.             {  
            236.                 last = s + 1;  
            237.                 if (s - strToken == 0) {  
            238.                     strToken = last;  
            239.                     break;  
            240.                 }  
            241.                 *(strToken + (s - strToken)) = '/0';  
            242.                 return strToken;  
            243.             }  
            244.             ++ t;  
            245.         }  
            246.         ++ s;  
            247.     }  
            248.     return NULL;  
            249. }  
            250.   
            251. char *strupr(char *str)   
            252. {   
            253.     assert(str != NULL);   
            254.     char *s = str;   
            255.     while (*s != '/0')   
            256.     {   
            257.         if (*s >= 'a' && *s <= 'z')   
            258.             *s -= 0x20;   
            259.         s ++;   
            260.     }   
            261.     return str;   
            262. }   
            263.   
            264. char *strlwr(char *str)   
            265. {   
            266.     assert(str != NULL);   
            267.     char *s = str;   
            268.     while (*s != '/0')   
            269.     {   
            270.         if (*s >= 'A' && *s <= 'Z')   
            271.             *s += 0x20;   
            272.         s ++;   
            273.     }   
            274.     return str;   
            275. }   
            276.   
            277. void *memcpy(void *dest, const void *src, unsigned int count)   
            278. {   
            279.     assert((dest != NULL) && (src != NULL));   
            280.     void *address = dest;   
            281.     while (count --)   
            282.     {   
            283.         *(char *) dest = *(char *) src;   
            284.         dest = (char *) dest + 1;   
            285.         src = (char *) src + 1;   
            286.     }   
            287.     return address;   
            288. }   
            289.   
            290. void *memccpy(void *dest, const void *src, int c, unsigned int count)   
            291. {   
            292.     assert((dest != NULL) && (src != NULL));   
            293.     while (count --)   
            294.     {   
            295.         *(char *) dest = *(char *) src;   
            296.         if (* (char *) src == (char) c)   
            297.             return ((char *)dest + 1);   
            298.         dest = (char *) dest + 1;   
            299.         src = (char *) src + 1;   
            300.     }   
            301.     return NULL;   
            302. }   
            303.   
            304. void *memchr(const void *buf, int c, unsigned int count)   
            305. {   
            306.     assert(buf != NULL);   
            307.     while (count --)   
            308.     {   
            309.         if (*(char *) buf == c)   
            310.             return (void *) buf;   
            311.         buf = (char *) buf + 1;   
            312.     }   
            313.     return NULL;   
            314. }   
            315.   
            316. int memcmp(const void *s, const void *t, unsigned int count)   
            317. {   
            318.     assert((s != NULL) && (t != NULL));   
            319.     while (*(char *) s && *(char *) t && *(char *) s == *(char *) t && count --)   
            320.     {   
            321.         s = (char *) s + 1;   
            322.         t = (char *) t + 1;   
            323.     }   
            324.     return (*(char *) s - *(char *) t);   
            325. }   
            326.   
            327. //@big:  
            328. //要處理src和dest有重疊的情況,不是從尾巴開始移動就沒問題了。  
            329. //一種情況是dest小于src有重疊,這個時候要從頭開始移動,  
            330. //另一種是dest大于src有重疊,這個時候要從尾開始移動。  
            331. void *memmove(void *dest, const void *src, unsigned int count)   
            332. {  
            333.     assert(dest != NULL && src != NULL);  
            334.     char* pdest = (char*) dest;  
            335.     char* psrc = (char*) src;  
            336.       
            337.     //pdest在psrc后面,且兩者距離小于count時,從尾部開始移動. 其他情況從頭部開始移動  
            338.     if (pdest > psrc && pdest - psrc < count)   
            339.     {  
            340.         while (count--)   
            341.         {  
            342.             *(pdest + count) = *(psrc + count);  
            343.         }  
            344.     } else   
            345.     {  
            346.         while (count--)   
            347.         {  
            348.             *pdest++ = *psrc++;  
            349.         }  
            350.     }  
            351.     return dest;  
            352. }  
            353.   
            354. void *memset(void *str, int c, unsigned int count)   
            355. {   
            356.     assert(str != NULL);   
            357.     void *s = str;   
            358.     while (count --)   
            359.     {   
            360.         *(char *) s = (char) c;   
            361.         s = (char *) s + 1;   
            362.     }   
            363.     return str;   
            364. }  
                      
              測試:以上所有的函數,都待進一步測試,有任何問題,歡迎任何人隨時不吝指出。

             

            第四節、c標準庫部分源代碼

                為了給各位一個可靠的參考,以下,我摘取一些c標準框里的源代碼,以饗各位:

            1. char * __cdecl strcat (char * dst,const char * src)  
            2. {  
            3.     char * cp = dst;  
            4.       
            5.     while( *cp )  
            6.         cp++;                   /* find end of dst */  
            7.       
            8.     while( *cp++ = *src++ ) ;       /* Copy src to end of dst */  
            9.       
            10.     return( dst );                  /* return dst */  
            11.       
            12. }  
            13.   
            14. int __cdecl strcmp (const char * src,const char * dst)  
            15. {  
            16.     int ret = 0 ;  
            17.       
            18.     while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)  
            19.         ++src, ++dst;  
            20.       
            21.     if ( ret < 0 )  
            22.         ret = -1 ;  
            23.     else if ( ret > 0 )  
            24.         ret = 1 ;  
            25.       
            26.     return( ret );  
            27. }  
            28.   
            29. size_t __cdecl strlen (const char * str)  
            30. {  
            31.     const char *eos = str;  
            32.       
            33.     while( *eos++ ) ;  
            34.       
            35.     return( (int)(eos - str - 1) );  
            36. }  
            37.   
            38. char * __cdecl strncat (char * front,const char * back,size_t count)  
            39. {  
            40.     char *start = front;  
            41.       
            42.     while (*front++)  
            43.         ;  
            44.     front--;  
            45.       
            46.     while (count--)  
            47.         if (!(*front++ = *back++))  
            48.             return(start);  
            49.           
            50.         *front = '/0';  
            51.         return(start);  
            52. }  
            53.   
            54. int __cdecl strncmp (const char * first,const char * last,size_t count)  
            55. {  
            56.     if (!count)  
            57.         return(0);  
            58.       
            59.     while (--count && *first && *first == *last)  
            60.     {  
            61.         first++;  
            62.         last++;  
            63.     }  
            64.       
            65.     return( *(unsigned char *)first - *(unsigned char *)last );  
            66. }  
            67.   
            68. /* Copy SRC to DEST.  */  
            69. char *  
            70. strcpy (dest, src)  
            71. char *dest;  
            72. const char *src;  
            73. {  
            74.     reg_char c;  
            75.     char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);  
            76.     const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;  
            77.     size_t n;  
            78.       
            79.     do  
            80.     {  
            81.         c = *s++;  
            82.         s[off] = c;  
            83.     }  
            84.     while (c != '/0');  
            85.       
            86.     n = s - src;  
            87.     (void) CHECK_BOUNDS_HIGH (src + n);  
            88.     (void) CHECK_BOUNDS_HIGH (dest + n);  
            89.       
            90.     return dest;  
            91. }  
            92.   
            93. char * __cdecl strncpy (char * dest,const char * source,size_t count)  
            94. {  
            95.     char *start = dest;  
            96.       
            97.     while (count && (*dest++ = *source++))    /* copy string */  
            98.         count--;  
            99.       
            100.     if (count)                              /* pad out with zeroes */  
            101.         while (--count)  
            102.             *dest++ = '/0';  
            103.           
            104.         return(start);  
            105. }  

             

            有關狂想曲的修訂

            程序員面試題狂想曲-tctop(the crazy thinking of programers)的修訂wiki(http://tctop.wikispaces.com/)已于今天建立,我們急切的想得到讀者的反饋,意見,建議,以及更好的思路,算法,和代碼優化的建議。所以,

            • 如果你發現了狂想曲系列中的任何一題,任何一章(http://t.cn/hgVPmH)中的錯誤,問題,與漏洞,歡迎告知給我們,我們將感激不盡,同時,免費贈送本blog內的全部博文集錦的CHM文件1期;
            • 如果你能對狂想曲系列的創作提供任何建設性意見,或指導,歡迎反饋給我們,并真誠邀請您加入到狂想曲的wiki修訂工作中;
            • 如果你是編程高手,對狂想曲的任何一章有自己更好的思路,或算法,歡迎加入狂想曲的創作組,以為千千萬萬的讀者創造更多的價值,更好的服務。
              Ps:狂想曲tctop的wiki修訂地址為:
              http://tctop.wikispaces.com/。歡迎圍觀,更歡迎您加入到狂想曲的創作或wiki修訂中。

            版權所有,本人對本blog內所有任何內容享有版權及著作權。實要轉載,請以鏈接形式注明出處。

            久久青青草视频| 国内精品人妻无码久久久影院导航 | 91精品无码久久久久久五月天 | 久久99国产精品久久99| 久久久不卡国产精品一区二区| 久久久久久久综合综合狠狠| 日本WV一本一道久久香蕉| 精品久久久久久无码中文字幕一区 | 久久精品国产99国产精品澳门| 国内精品久久久久久久亚洲| 色综合久久无码五十路人妻| 94久久国产乱子伦精品免费| 国产精品99久久久精品无码| 国产福利电影一区二区三区久久老子无码午夜伦不 | 久久免费精品视频| 久久久久亚洲av综合波多野结衣 | 国内精品久久久久影院日本| 精品无码久久久久久国产| 久久久久亚洲AV无码专区体验| 少妇久久久久久久久久| 一本一道久久精品综合| 精品久久久久香蕉网| 亚洲综合精品香蕉久久网| 久久久久久噜噜精品免费直播| 久久精品国产亚洲一区二区| 精品久久久久久无码中文字幕一区| 久久久久久久91精品免费观看| 国产精久久一区二区三区| 99久久99这里只有免费费精品 | 色婷婷噜噜久久国产精品12p| 久久99国产精品久久久| 狠狠色丁香久久婷婷综合五月| 午夜天堂av天堂久久久| 色妞色综合久久夜夜| 99久久国产亚洲综合精品| 思思久久99热免费精品6| 久久久久无码中| 亚洲国产精品成人久久蜜臀| 亚洲AⅤ优女AV综合久久久| 午夜精品久久久久久影视777| 一本一道久久a久久精品综合|