• <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>

            The power of C, the power of MD

            A problem is a chance to do your best
            posts - 11, comments - 22, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            strcat在某種特定條件下的優化

            Posted on 2010-07-28 21:46 roy 閱讀(2173) 評論(10)  編輯 收藏 引用 所屬分類: C/C++
            strcatC語言一個基本的字符串操作函數,它的源代碼一般是這樣的。

            char *strcat(char *dest, const char *src)   
            {   
                
            char *tmp = dest;   
                
            while (*dest) dest++;   
                
            while ((*dest++ = *src++!= '\0');   
                
            return tmp;   
            }
              


            由此可見,strcat調用時,先移動目標字符串的指針到其尾部,再進行復制。這種做法對于下標比較大的數組重復調用時,效率比較低。想象一下,第一次調用strcat時,指針由0數到100,只不過復制了幾個字符,第二次調用strcat時,指針又從0數到108,無論調用多少次,指針總是從0數起,就會知道這個時候是多么浪費系統資源了!

            我找到一個辦法,字符串追加時,事先給出目標字符串結尾所在的位置,追加時,也就不用從頭開始計算其長度了,復制的過程中,目標字符串的結尾也隨之移動,下一次再追加也就可以使用它了。以下就是優化過的string_append,與strcat相比,增加了一個整形指針以傳遞目標字符串長度的地址。

            /*
             * optimizer for strcat when appending to a large array again and again
             
            */

            char *string_append(char *dest, int *end, const char *src) {
                
            if ( *end >= 0 && dest && src ) {
                    
            char *= dest + *end;
                    
            while ( *p++ = *src++ ) (*end)++;
                }

                
            return dest;
            }


            經試驗,string_append在大數組重復追加內容的情形下,優勢非常明顯。其它情形下,使用原來的strcat也就足夠了。

            #include <stdio.h>
            #include 
            <string.h>
            #include 
            <time.h>

            #define BUFF_SIZE 4096

            /*
             * optimizer for strcat when appending to a large array again and again
             
            */

            char *string_append(char *dest, int *end, const char *src) {
                
            if ( *end >= 0 && dest && src ) {
                    
            char *= dest + *end;
                    
            while ( *p++ = *src++ ) (*end)++;
                }

                
            return dest;
            }


            int main() {
                
            int i = 0, j = 0;
                
            int retry = 100000;
                
            int field = 100;
                
            char output1[BUFF_SIZE], output2[BUFF_SIZE];
                time_t time1 
            = time(NULL);
                
            for ( i = 0; i < retry; i++ ) {
                    memset(output1, 
            0, BUFF_SIZE);
                    
            int length = 0;
                    string_append(output1, 
            &length, "header\n");
                    
            for ( j = 0; j < field; j++ ) {
                        string_append(output1, 
            &length, "\tcall detail record ");
                        
            char c[8];
                        sprintf(c, 
            "%d", j);
                        string_append(output1, 
            &length, c);
                        string_append(output1, 
            &length, "\n");
                    }

                    string_append(output1, 
            &length, "trailer\n");
                }

                time_t time2 
            = time(NULL);
                printf(
            "It takes %d seconds to show the performance of string_append()\n", time2 - time1);

                time1 
            = time(NULL);
                
            for ( i = 0; i < retry; i++ ) {
                    memset(output2, 
            0, BUFF_SIZE);
                    strcat(output2, 
            "header\n");
                    
            for ( j = 0; j < field; j++ ) {
                        strcat(output2, 
            "\tcall detail record ");
                        
            char c[8];
                        sprintf(c, 
            "%d", j);
                        strcat(output2, c);
                        strcat(output2, 
            "\n");
                    }

                    strcat(output2, 
            "trailer\n");
                }

                time2 
            = time(NULL);
                printf(
            "It takes %d seconds to show the performance of strcat()\n", time2 - time1);
                
            if ( strcmp(output1, output2) )
                    printf(
            "They are NOT equal\n");
                
            else
                    printf(
            "They are equal\n");
                
            return 0;
            }

             

            -bash-3.2$ ./string_append_demo

            It takes 2 seconds to show the performance of string_append()

            It takes 11 seconds to show the performance of strcat()

            They are equal


            本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/yui/archive/2010/05/22/5616455.aspx

            Feedback

            # re: strcat在某種特定條件下的優化  回復  更多評論   

            2010-07-28 23:55 by 陳梓瀚(vczh)
            所以C++的string類都有記錄長度的。

            # re: strcat在某種特定條件下的優化  回復  更多評論   

            2010-07-29 00:57 by lwch
            沒有檢查緩沖區長度...
            會造成溢出

            # re: strcat在某種特定條件下的優化  回復  更多評論   

            2010-07-29 09:03 by roy
            @lwch

            原始的strcat一樣會溢出,這個問題應該由調用者負責

            # re: strcat在某種特定條件下的優化[未登錄]  回復  更多評論   

            2010-07-29 12:04 by c++
            我的程序里一直在strlen(name)。我想是該考慮string的記錄len。

            # re: strcat在某種特定條件下的優化  回復  更多評論   

            2010-07-30 06:10 by hoodlum1980
            在現實應用里,都是隨機化的處理,使用你的方法,實際上還需要求一次strlen,這樣也就沒有什么優勢(和實用性)可言了。
            這是C字符串模型的一種特點(在這里體現出是缺點,但在其他大部分地方都體現的是高效和靈活性)導致的,例如其他有些語言的字符串是在前面存儲字符串長度的,但是這樣相對而言對字符串處理庫函數會提高一些維護難度,因為總是要同時照顧這個長度信息。

            # re: strcat在某種特定條件下的優化  回復  更多評論   

            2010-08-02 09:24 by roy
            @hoodlum1980

            這個例子中,從來沒用到strlen,而且,這是在某種特定條件下的優化,初始值是空串,長度為0,請看清楚

            # re: strcat在某種特定條件下的優化  回復  更多評論   

            2010-08-04 09:16 by roy
            @hoodlum1980

            唉,我反而覺得你沒理解好,你是說每次調用string_append都要先調用strlen嗎?根本不需要,每次string_append就已經計算了下一次執行時的偏移量了

            # re: strcat在某種特定條件下的優化  回復  更多評論   

            2010-08-06 02:55 by hoodlum1980
            如果是每次你能知道是從哪里連接的場合,你只需要strcpy(s+length, src); 就好了呀。我的意思就是那個本來就是在常規場合使用的。也就是說,在你自己維護的上下文內,你當然能夠盡可能的達到最精確的控制。但在各種交叉處理之中,strcat相對而言就是一種最通用和恰當的庫函數之一。同時C字符串在效率上給了你充分的自由度。我說的就是在特定的應用場合當然可以根據其背景做出特定的優化,但是要做通用性的實現,因為考慮到通用性,不是所有的假設都能成立,特定的優化可能因而不宜提供,這也是C字符串庫函數形成現在這個系列的原因了。

            # re: strcat在某種特定條件下的優化  回復  更多評論   

            2010-08-06 03:02 by hoodlum1980
            簡單說,strcat可以說是strlen和strcpy的功能疊加。如果使用strcat,通常也就是不知道字符串長度(但是要保證原來的空間足夠容納連接的字符串)或者不想關注這個信息的場合。如果你自己精確的知道或者已經維護了這個信息,那么你當然可以直接使用strcpy,是不是呢?這樣表達可能有點繞,如有不妥,當我沒說把。

            # re: strcat在某種特定條件下的優化  回復  更多評論   

            2010-08-06 10:09 by roy
            @hoodlum1980

            首先感謝你一直關心拙作,我們都是技術人員,關于技術問題沒什么不能談的,是嗎?

            其次,我并沒有用string_append代替strcat的意思,事實上,通常情況下,我都只用strcat,只有在strcat對效率影響實在太大的時候,才考慮string_append。這個例子中直接用strcpy當然可以,但還是需要strlen計算附加串的長度。
            精品多毛少妇人妻AV免费久久 | 亚洲国产精品久久久久| 丰满少妇高潮惨叫久久久| 久久精品无码一区二区三区| 韩国三级中文字幕hd久久精品| 无码任你躁久久久久久久| 亚洲中文久久精品无码| 青青青国产成人久久111网站| 无码8090精品久久一区| 国内精品久久久久影院一蜜桃| 国产精品美女久久久网AV| 久久久久av无码免费网| 亚洲国产天堂久久综合网站 | 国产伊人久久| 天天爽天天狠久久久综合麻豆| 国产精品成人无码久久久久久| 99久久精品国产一区二区| 久久强奷乱码老熟女| 久久福利青草精品资源站| 亚洲综合伊人久久综合| 久久精品夜色噜噜亚洲A∨| 久久99精品国产99久久6男男| 久久久精品人妻一区二区三区蜜桃| 狠狠色伊人久久精品综合网| 国产精品美女久久久m| 久久夜色精品国产亚洲| 久久久久这里只有精品 | 国产99久久久久久免费看| 香蕉久久夜色精品升级完成| 日韩人妻无码一区二区三区久久99| 99热精品久久只有精品| 久久91精品国产91久久户| 国产精品禁18久久久夂久| 久久久久久亚洲AV无码专区| 无码国内精品久久人妻蜜桃| 国产免费久久精品99re丫y| 久久综合亚洲色HEZYO社区 | 狠狠精品干练久久久无码中文字幕| 国产精品久久久久aaaa| 嫩草影院久久国产精品| 9191精品国产免费久久|