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

            woaidongmao

            文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
            數據加載中……

            不用臨時變量也可以交換變量的值

            當要交換兩個數的值時,通常的做法是定義一個臨時變量,然后再進行交換。那么能不能不用臨時變量而交換兩個數的值呢?可以的!C語言提供的異或運算就可以實現這樣的操作。

            異或運算符^也稱XOR運算符,它的規則是若參加運算的兩個二進位同號,則結果為0(假);異號為1(真)。即0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0 

            例:

            #include <stdio.h>

            int main(int argc, char *argv[])
            {
               
            int a = 2, b = 6;

                a
            = a ^ b;
                b
            = b ^ a;
                a
            = a ^ b;

               
            printf("a = %d b = %d\n", a, b);

               
            return 0;
            }

            結果如下:

            a = 6 b = 2

            分析:

            前兩個賦值語句:“a = a ^ b“b = b ^ a相當于b = b ^ (a ^ b),而b ^ a ^ b等于a ^ b ^ bb ^ b的結果為0,因為同一個數與相向相^,結果必為0。因此b的值等于a ^ 0,即a,其值為2

            再執行第三個賦值語句:“a = a ^ b”。由于a的值等于(a ^ b)b的值等于(b ^ a ^ b),因此,相當于a = a ^ b ^ b ^ a ^ b,即a的值等于a ^ a ^ b ^ b ^ b,等于b

            今天又發現另外兩種方法,特補上。 

            方法一

            void swap(int *p, int *q)
            {
               
            *p = *p + *q;
               
            *q = *p - *q;
               
            *p = *p - *q;
            }

            方法二

            void swap(int *p, int *q)
            {
               
            *p = *p + *q - (*q = *p);
            }

            原理為算術運算符的結合順序為自左至右。

            2007.06.18

             

            可以把異或的三條語句壓縮為一條: 

            a ^= b ^= a ^= b;

            要交換三個變量的值,可以用以下語句:

            c = a + c - (a = b, b = c);

            2007.09.11

            謝謝網友cool8jay指出上面紅色部分的錯誤,下面來分析一下,先看一個示例程序,如下:

            #include <stdio.h>

            int main(int argc, char *argv[])
            {
               
            int a = 1;
               
            int b = 2;
               
            int c = 3;

                c
            = a + c - (a = b, b = c);

               
            printf("a = %d\n", a);
               
            printf("b = %d\n", b);
               
            printf("c = %d\n", c);

               
            return 0;
            }

            編譯運行,結果如下:

            a = 2 b = 3 c = 2

            可見,最初目標中的c = 1部分沒能實現。于是分析原因:

            The C Programming Language·Second EditionP205介紹說,“The additive operators + and - group left-to-right”,即附加運算符加號和減號的結合順序是自左向右;P209介紹說,“A pair of expressions separated by a comma is evaluated left-to-right, and the value of the left expression is discarded. The type and value of the result are the type and value of the right operand”,即逗號表達式的計算順序是從左向右,逗號左邊表達式的值被舍棄,表達式結果的類型和數值是逗號右邊表達式的類型和數值。

            既然如此,那結果應該是正確的,為什么還會出錯呢?再來看一下VC6.0下編譯產生的匯編代碼:

            7: int a = 1;
            00401028
            mov dword ptr [ebp-4],1
            8
            : int b = 2;
            0040102F
            mov dword ptr [ebp-8],2
            9
            : int c = 3;
            00401036
            mov dword ptr [ebp-0Ch],3
            10
            :
            11
            : c = a + c - (a = b, b = c);
            0040103D
            mov eax,dword ptr [ebp-8]
            00401040
            mov dword ptr [ebp-4],eax
            00401043
            mov ecx,dword ptr [ebp-4]
            00401046
            add ecx,dword ptr [ebp-0Ch]
            00401049
            mov edx,dword ptr [ebp-0Ch]
            0040104C
            mov dword ptr [ebp-8],edx
            0040104F
            sub ecx,dword ptr [ebp-8]
            00401052
            mov dword ptr [ebp-0Ch],ecx

            可以看到,第11行代碼的執行過程如下:

            先把b的值賦給a,再把ac的值相加,結果放在寄存器ecx中,然后把c的值賦給b,最后再把ecxb的值相減,結果賦給c。分解為C語句為:

            a = b; /* a = 2, b = 2 */
            ecx
            = a + c; /* ecx = 5, a = 2, c = 3 */
            b
            = c; /* b = 3, c = 3 */
            c
            = ecx - b; /* c = 2, ecx = 5, b = 3 */

            這下就清楚了,原來程序運行時先把逗號左邊表達式的值計算出來丟棄掉,然后再做其它的運算,最開始的錯誤也就錯在了這里。

            好了,既然上面的式子有問題,那有沒有其它正確的方法能一條語句實現三個變量的值的交換呢?恕本人愚鈍,還沒有想出來。如果誰知道,請給我留言。在此先致謝!

            還有一個問題,也是網友cool8jay提出來的,就是交換三個變量的值(每個變量值都要改變)應該有兩種情況,123可以變為231312。我當時想到過,只是覺得可以類比就沒有說明,現在看來可能會誤導讀者,這里說明一下。

            不用臨時變量順次交換N個變量的值

             

             

            NN>=2)個變量,不使用臨時變量,如何順次交換它們的值?能否只用一條語句實現?如

             

            +---+---+---+---+---+
            | a | b | c | d | e |
            +---+---+---+---+---+
            | 1 | 2 | 3 | 4 | 5 |
            +---+---+---+---+---+

             

            要把它變為

             

            +---+---+---+---+---+
            | a | b | c | d | e |
            +---+---+---+---+---+
            | 2 | 3 | 4 | 5 | 1 |
            +---+---+---+---+---+

             

            怎樣實現?

             

            首先,我們考慮用異或實現兩個變量的交換,可參考我的這篇文章《不用臨時變量交換兩個數的值》。用C++寫函數如下:

             

            int &swap(int &a, int &b)
            {
                b
            = b ^ a;
                a
            = a ^ b;
                b
            = b ^ a;

               
            return b;
            }

            然后可以把代碼優化為:

            int &swap(int &a, int &b)
            {
                b ^
            = a;
                a ^
            = b;
                b ^
            = a;

               
            return b;
            }

            繼續優化,把三句壓縮為一句,如下:

            int &swap(int &a, int &b)
            {
                b ^
            = a ^= b ^= a;
               
               
            return b;
            }

            還可再優化,如下:

            int &swap(int &a, int &b)
            {
               
            return (b ^= a ^= b ^= a);
            }

            現在來順次交換5個變量的值,如下:

            swap(a, b);        //返回b

            swap(b, c);        //返回c

            swap(c, d);        //返回d

            swap(d, e);       

            既然有返回值,那么可以寫成鏈式的,如下:

            swap(a, b);                                 //返回b

            swap(swap(a, b), c);                        //返回c

            swap(swap(swap(a, b), c), d);               //返回d

            swap(swap(swap(swap(a, b), c), d), e);       

            現在,讓我們來把swap函數依次用相應的函數體替換掉,如下:

            e ^= d ^= e ^= swap(swap(swap(a, b), c), d);

            e ^
            = d ^= e ^= d ^= c ^= d ^= swap(swap(a, b), c);

            e ^
            = d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= swap(a, b);

            e ^
            = d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= b ^= a ^= b ^= a;

            好了,最后一個語句就實現了順次交換五個變量的值,寫程序驗證如下:

            /******************************************************************
            * Copyright (c) 2005-2007 CUG-CS
            * All rights reserved
            *
            *
            文件名稱:xor.c
            *
            簡要描述:實現五個變量的順次交換
            *
            *
            當前版本:1.0
            *
            作 者:raincatss
            *
            完成日期:2007-10-18
            * 開發環境:Windows XP Sp2 + VC6.0
            *
            個人博客:http://raincatss.cublog.cn/
            ******************************************************************/


            #include <stdio.h>

            #define PRINT(A) do {\
               
            printf("%d\n", A);\
               
            } while (0)

            int main()
            {
               
            int a = 1;
               
            int b = 2;
               
            int c = 3;
               
            int d = 4;
               
            int e = 5;

            //    b ^= a ^= b ^= a;        // swap(a, b)

            //    c ^= b ^= c ^= b;        // swap(b, c)

            //    d ^= c ^= d ^= c;        // swap(c, d)

            //    e ^= d ^= e ^= d;        // swap(d, e)


                e ^
            = d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= b ^= a ^= b ^= a;

                PRINT
            (a);
                PRINT
            (b);
                PRINT
            (c);
                PRINT
            (d);
                PRINT
            (e);

               
            return 0;
            }

            運行結果如下:

            2 3 4 5 1

            測試結果正確,達到預定目標。

             

            posted on 2008-11-07 23:06 肥仔 閱讀(1898) 評論(1)  編輯 收藏 引用 所屬分類: C++ 基礎

            評論

            # re: 不用臨時變量也可以交換變量的值  回復  更多評論   

            c = a + c - (a = b, b = c);

            改成c = a + b- (a = b, b = c);看可不可以
            2008-11-18 10:16 | qun454
            久久免费视频观看| 久久天堂AV综合合色蜜桃网| 久久婷婷激情综合色综合俺也去| 亚洲精品乱码久久久久久蜜桃| www亚洲欲色成人久久精品| 香蕉久久夜色精品国产小说| 99久久成人18免费网站| 青青国产成人久久91网| 99久久免费只有精品国产| 久久久久无码专区亚洲av| 精品人妻伦九区久久AAA片69| 中文字幕乱码人妻无码久久| 久久97精品久久久久久久不卡 | 久久综合国产乱子伦精品免费| 久久精品天天中文字幕人妻 | 一级做a爰片久久毛片毛片| 亚洲精品国产美女久久久| 久久99精品久久久久久齐齐| 午夜欧美精品久久久久久久| 日本道色综合久久影院| 国产精品国色综合久久| 日韩人妻无码一区二区三区久久99| 久久精品国产亚洲av高清漫画 | 一本色综合久久| 久久久人妻精品无码一区| 久久成人国产精品一区二区| 中文字幕成人精品久久不卡| 国产一区二区三区久久| 国产精品久久精品| 9191精品国产免费久久| 久久99国产一区二区三区| 国内精品欧美久久精品| 一本久久免费视频| 精品熟女少妇a∨免费久久| 2021精品国产综合久久| 国产综合免费精品久久久| 香蕉久久AⅤ一区二区三区| 国产成人精品综合久久久| 国产精品欧美亚洲韩国日本久久| 无码国内精品久久综合88| 久久精品国产亚洲AV麻豆网站|