• 搞定C系语言的的swap


    http://www.cs.utsa.edu/~wagner/CS2213/swap/swap.html 原地址

    Parameters, by value and by reference: Both C and Java use only parameters that pass by value, which means that the value of the actual parameter is used to initialize the formal parameter. For simple variables C allows one to pass the address of the variable explicitly. (Java does not allow this.) This is sometimes called passing a parameter by reference. C++ allows this also, but C++ also allows an implicit pass by reference, which will be described at the end of this writeup.

    In C, the mechanism above is what is used for parameters in the scanf function, which have the extra & (the "address of" operator) in front of them.


    A swapping values: In C and in Java, we can always swap values with the use of three assignment statement and no function or paramters. The code on the left shows this, while the code on the right shows how the same task can be accomplished using the C exclusive-or operator ^. (Notice that is this case you don't need the variable t.)

    C Simple Swap Program -- AssignmentsC Simple Swap Program -- Exclusive-Or
    
    #include <stdio.h>
    
    int main() {
       int a = 23, b = 47;
       int t;
       printf("Before. a: %d, b: %d
    ", a, b);
       t = a;
       a = b;
       b = t;
       printf("After.  a: %d, b: %d
    ", a, b);
       return 0;
    }
    
    
    #include <stdio.h>
    
    int main() {
       int a = 23, b = 47;
       
       printf("Before. a: %d, b: %d
    ", a, b);
       a ^= b;
       b ^= a;
       a ^= b;
       printf("After.  a: %d, b: %d
    ", a, b);
       return 0;
    }
    
    Runs of the two programs
    % cc -o swap_simple0 swap_simple0.c
    % swap_simple0
    Before. a: 23, b: 47
    After.  a: 47, b: 23
    
    % cc -o swap_simple1 swap_simple1.c
    % swap_simple1
    Before. a: 23, b: 47
    After.  a: 47, b: 23
    

    A swapping function: To understand how explicit pass by reference of parameters works in C, consider implementing a swap function in C, that is, a function that passes in two variables and swaps their values. The code on the left below shows one failed attempt at an implementation. The code on the right uses pointers, that is, explicitly passes the address of variables, and manipulates the numbers that are at that address, using the * operator (the "dereference" operator that fetches the contents of the given address).

    C Swap Program -- FailsC Swap Program with Pointers -- Works
    
    #include <stdio.h>
    
    void swap(int i, int j) {
       int t = i;
       i = j;
       j = t;
    }
    
    int main() {
       int a = 23, b = 47;
       printf("Before. a: %d, b: %d
    ", a, b);
       swap(a,b);
       printf("After.  a: %d, b: %d
    ", a, b);
       return 0;
    }
    
    
    #include <stdio.h>
    
    void swap(int *i, int *j) {
       int t = *i;
       *i = *j;
       *j = t;
    }
    
    void main() {
       int a = 23, b = 47;
       printf("Before. a: %d, b: %d
    ", a, b);
       swap(&a, &b);
       printf("After . a: %d, b: %d
    ", a, b);
    }
    
    Runs of the two programs
    % cc -o swap0 swap0.c
    % swap0
    Before. a: 23, b: 47
    After.  a: 23, b: 47
    
    % cc -o swap1 swap1.c
    % swap1
    Before. a: 23, b: 47
    After.  a: 47, b: 23
    

    With the program on the left, no swapping took place. The values of a and b are passed to swap, and the function does swap them, but when the function returns, nothing has changed in the main function.

    To get an idea of what this code does, print it out, draw the two integers a and b, and enter 23 and 47 in them. Now draw the two pointers i and j, along with the integer t. When swap is called, it is passed the addresses of a and b. Thus, i points to a (draw an arrow from i to a) and j points to b (draw another arrow from b to j). Once the pointers are initialized by the function call, *i is another name for a, and *j is another name for b. Now run the code in swap. When the code uses *i and *j, it really means a and b. When the function completes, a and b have been swapped.

    Suppose you accidentally forget the & when the swap function is called, and that the swap line accidentally looks like this: swap(a, b);. This causes a segmentation fault. When you leave out the &, the value of a is passed instead of its address. Therefore, i points to an invalid location in memory and the system crashes when *i is used.

    This is also why scanf crashes if you forget the & on variables passed to it. The scanf function is using pointers to put the value it reads back into the variable you have passed. Without the &scanf is passed a bad address and crashes. Reference parameters are one of the most common uses of pointers in C. Another way to say this is to say that the calling function is telling the called function where to find the variable.


    Swapping in Java: The swapping just above using reference parameters in C doesn't work in Java, since Java doesn't have these kind of parameters, but often an application really only needs to swap two values in an array. In this case one can pass the array and the two indexes to swap as three parameters, and this will work in Java. The "bubble sort" program below illustrates this.

    Java BubbleSort ProgramRun of the Program
    public class BubbleSort {
       // swap: interchange inside array
       static void swap(int[] a, int i, int j) {
          int t = a[i];
          a[i] = a[j];
          a[j] = t;
       }
    
       // bubbleSort: very short code, but ineffient
       static void bubbleSort(int[] a) {
          for (;;) {
             boolean sorted = true;
             for (int i = 0; i < a.length - 1; i++)
                if (a[i] > a[i+1]) {
                   sorted = false;
                   swap(a, i, i + 1);
                }
             if (sorted) break;
          }
       }
    
       static void printArray(int[] a) {
          for (int i = 0; i < a.length; i++) {
             if (i%4 == 0) System.out.println();
             System.out.print(a[i] + " 	");
          }
          System.out.println();
       }
    
       public static void main(String[] args) {
          int size = Integer.parseInt(args[0]);
          System.out.println("Bubblesort, size = " +
             size);
          int[] r = new int[size];
          for (int i = 0; i < size; i++)
             r[i] = (int)(Math.random()*size*10 + 1);
          long startTime =System.currentTimeMillis();
          bubbleSort(r);
          System.out.println("Elapsed time(millis) "+
             (System.currentTimeMillis()-startTime));
          // printArray(r);
       }
    }
    
    % javac BubbleSort.java
    % java BubbleSort 60
    Bubblesort, size = 60
    Elapsed time (millis) 1
    
    5       7       9       18
    21      27      41      44
    67      104     104     109
    116     118     151     151
    170     175     181     182
    196     196     207     220
    231     240     241     242
    244     247     251     274
    279     290     302     325
    329     339     341     363
    366     369     376     380
    385     411     435     440
    471     484     492     504
    505     547     556     559
    564     583     588     591
    % java BubbleSort 100
    Bubblesort, size = 100
    Elapsed time (millis) 3
    % java BubbleSort 1000
    Bubblesort, size = 1000
    Elapsed time (millis) 394
    % java BubbleSort 10000
    Bubblesort, size = 10000
    Elapsed time (millis) 39518
    % java BubbleSort 20000
    Bubblesort, size = 20000
    Elapsed time (millis) 158317
    % java BubbleSort 40000
    Bubblesort, size = 40000
    Elapsed time (millis) 646717
    

    Swapping in Java Using Wrapped Integers: In Java we can get the swap function to work if we use wrapped integers and pass references to them to the function. However, the Java wrapper class for int is Integer and it doesn't allow you to alter the data field inside. Thus we need our own wrapper class, which I have called MyInteger below. The program here is only presented as what could be done, not as an example of how to do swaps. If one passes the address of an object to a function, then changes to the inside of that object will persist after returning from the function

    Java Swapping Using a Wrapper Class
    
    // MyInteger: similar to Integer, but can change value
    class MyInteger {
       private int x;                   // single data member
       public MyInteger(int xIn) { x = xIn; } // constructor
       public int getValue() { return x; }  // retrieve value
       public void insertValue(int xIn) { x = xIn;} // insert
    }
    
    public class Swapping {
       // swap: pass references to objects
       static void swap(MyInteger rWrap, MyInteger sWrap) {
          // interchange values inside objects
          int t = rWrap.getValue();
          rWrap.insertValue(sWrap.getValue());
          sWrap.insertValue(t);
       }
    
       public static void main(String[] args) {
          int a = 23, b = 47;
          System.out.println("Before. a:" + a + ", b: " + b);
          MyInteger aWrap = new MyInteger(a);
          MyInteger bWrap = new MyInteger(b);
          swap(aWrap, bWrap);
          a = aWrap.getValue();
          b = bWrap.getValue();
          System.out.println("After.  a:" + a + ", b: " + b);
       }
    }
    
    % javac Swapping.java
    % java Swapping
    Before: a: 23, b: 47
    After:  a: 47, b: 23
    

    Swapping in C++: Of course the C swapping methods will work in C++ also, but C++ has the very important concept of references, which we probably won't study in this course. However, below is a C++ swap program using this feature. Notice that the code for the actual swap is simple: swap(a, b);. In a similar way, the simple form of C++ input, such as cin >> x >> y; requires these kind of parameters.

    C++ Swap Program Using References
    
    #include <iostream>
    using std::cout;
    
    void swap(int& i, int& j) {
        int t = i;
        i = j;
        j = t;
    }
    
    int main() {
        int a = 23, b = 47;
        cout << "Before. a: " << a << ", b: " << b << "
    ";
        swap(a, b);
        cout << "After.  a: " << a << ", b: " << b << "
    ";
        return 0;
    }
    
    Run of the program
    % CC -o swap_CC swap.cpp
    % swap_CC
    Before: a: 23, b: 47
    After:  a: 47, b: 23
    

    Swapping in C Using the Preprocessor: Another very good way to swap in C (perhaps the best way) uses the C preprocessor, which we will study later. For now, a preprocessor function like swap below does a textual substitution, before the actual compiler is invoked. The second listing below is what is sent to the compiler. (This is why there is no semicolon at the end of swap(int, a, b), since in the compiled code it would become a redundant semicolon at the end of a block (although not an error).)

    C Swap Program Using Preprocessor
    
    #define swap(type, i, j) {type t = i; i = j; j = t;}
    
    int main() {
        int a = 23, b = 47;
        printf("Before swap. a: %d, b: %d
    ", a, b);
        swap(int, a, b)
        printf("After swap.  a: %d, b: %d
    ", a, b);
        return 0;
    }
    
    Preprocessed Output
    
    % cc -E swap_p.c
    int main() {
        int a = 23, b = 47;
        printf("Before swap. a: %d, b: %d
    ", a, b);
         { int t = a ; a = b ; b = t ; }
        printf("After swap.  a: %d, b: %d
    ", a, b);
        return 0;
    }
    
    Run of the program
    % cc -o swap_p swap_p.c
    %  swap_p
    Before swap: a: 23, b: 47
    After swap:  a: 47, b: 23
    
  • 相关阅读:
    SharePoint下载大文件失败 异常信息: system.OutOfMemoryException
    SharePoint Server 2010 容量管理:软件边界和限制
    PowerShell 备份sharepoint站点命令
    SharePoint 开发自定义WebService
    SPCAMLEditor 10分钟打造一个在线视频播放库
    使用PowerShell批量注册DLL到GAC
    设计模式之二 策略模式
    (转)Github上的热门iOS开源项目:AFNetworking、MagicalRecord、BlocksKit以及XVim
    (转)iOS开发常用的宏 大家一起来收集~
    (转)iOS开发资源:推送通知相关开源项目PushSharp、APNSPHP以及Pyapns等
  • 原文地址:https://www.cnblogs.com/dgwblog/p/9196762.html
Copyright © 2020-2023  润新知