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

            tbwshc

            tbw

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              95 Posts :: 8 Stories :: 3 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(4)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            #

            什么是約瑟夫環呢?
              約瑟夫環是一個數學的應用問題:已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重復下去,直到圓桌周圍的人全部出列。
              我們用程序說話,實現約瑟夫環:

            import java.util.Scanner;
            public class Josephus{
             private static class Node{
              public int no;//編號
              public Node next;//下一個節點

             public Node(int no){
              this. no=no
             }
             }
            public static void main(String[]args)  {
                  SCanner scanner=new Scanner(System.in);
                  System.out.print('out. print("請輸入總人數:");
                  int totalNum=scanner. nextInt);
                  System.out.print("請輸入報數的大小:");
                  int cycleNum=canner. nextInt();
                  Node heade==new Node(1);
                  Node pointer=heade;
                  for(int i=2;i<=totalNum;i++){
                       pointer.next=new Node(i);
                       pointer=pointer.next;
             }


            pointer=pointer. next;
            pointer. next=header;
            //初始化環形鏈表結束
            System.out.p:Intln("out. println("以下是出列tb的順序:‘)‘
            while (pointer!,pointer. next)  {
            for (int i=1;:<cycleNum; i++)
                pointer=pointer. next;
                }
                System.out.prlntln(pointer.next.no)out. println(pointer. next.no);
                pointer. next=pointer. next. next;
            }
            System. out. println(pointer.next.no);
            }
            }



            posted @ 2012-09-26 12:04 tbwshc 閱讀(950) | 評論 (-1)編輯 收藏

              在JAVA平臺,實現異步調用的角色有如下三個角色:調用者 提貨單 真實數據一個調用者在調用耗時操作,不能立即返回數據時,先返回一個提貨單.然后在過一斷時間后憑提貨單來獲取真正的數據.去蛋糕店買蛋糕,不需要等蛋糕做出來(假設現做要很長時間),只需要領個提貨單就可以了(去干別的事情),等到蛋糕做好了,再拿提貨單取蛋糕就可以了。public class Main { public static void main(String[] args) {

              System.out.println("main BEGIN");

              Host host = new Host();

              Data data1 = host.request(10, 'A');

              Data data2 = host.request(20, 'B');

              Data data3 = host.request(30, 'C');

              System.out.println("main otherJob BEGIN");

              try {

              Thread.sleep(200);

              } catch (InterruptedException e) {

              }

              System.out.println("main otherJob END");

              System.out.println("data1 = " + data1.getContent());

              System.out.println("data2 = " + data2.getContent());

              System.out.println("data3 = " + data3.getContent());

              System.out.println("main END");

              }

              }

              這里的main類就相當于“顧客”,host就相當于“蛋糕店”,顧客向“蛋糕店”定蛋糕就相當于“發請求request”,返回的數據data是FutureData的實例,就相當于提貨單,而不是真正的“蛋糕”。在過一段時間后(sleep一段時間后),調用data1.getContent(),也就是tb拿提貨單獲取執行結果。

              下面來看一下,顧客定蛋糕后,蛋糕店做了什么:

              public class Host {

              public Data request(final int count, final char c) {

              System.out.println("request(" + count + ", " + c + ") BEGIN");

              // (1) 建立FutureData的實體

              final FutureData future = new FutureData();

              // (2) 為了建立RealData的實體,啟動新的線程

              new Thread() {

              public void run() {

              //在匿名內部類中使用count、future、c。

              RealData realdata = new RealData(count, c);

              future.setRealData(realdata);

              }

              }.start();

              System.out.println("request(" + count + ", " + c + ") END");

              // (3) 取回FutureData實體,作為傳回值

              return future;

              }

              }

              host("蛋糕店")在接到請求后,先生成了“提貨單”FutureData的實例future,然后命令“蛋糕師傅”RealData去做蛋糕,realdata相當于起個線程去做蛋糕了。然后host返回給顧客的僅僅是“提貨單”future,而不是蛋糕。當蛋糕做好后,蛋糕師傅才能給對應的“提貨單”蛋糕,也就是future.setRealData(realdata)。

            下面來看看蛋糕師傅是怎么做蛋糕的:

              建立一個字符串,包含count個c字符,為了表現出犯法需要花費一些時間,使用了sleep。

              public class RealData implements Data { private final String content;

              public RealData(int count, char c) {

              System.out.println("making RealData(" + count + ", " + c + ") BEGIN");

              char[] buffer = new char[count];

              for (int i = 0; i < count; i++) {

              buffer[i] = c;

              try {

              Thread.sleep(1000);

              } catch (InterruptedException e) {

              }

              }

              System.out.println("making RealData(" + count + ", " + c + ") END");

              this.content = new String(buffer);

              }

              public String getContent() {

              return content;

              }

              }

              現在來看看“提貨單”future是怎么與蛋糕"content"對應的:

              public class FutureData implements Data { private RealData realdata = null;

              private boolean ready = false;

              public synchronized void setRealData(RealData realdata) {

              if (ready) {

              return; // 防止setRealData被調用兩次以上。

              }

              this.realdata = realdata;

              this.ready = true;

              notifyAll();

              }

              public synchronized String getContent() {

              while (!ready) {

              try {

              wait();

              } catch (InterruptedException e) {

              }

              }

              return realdata.getContent();

              }

              }

              顧客做完自己的事情后,會拿著自己的“提貨單”來取蛋糕:

              System.out.println("data1 = " + data1.getContent());

              這時候如果蛋糕沒做好,就只好等了:

              while (!ready) { try {

              wait();

              } catch (InterruptedException e) {

              }

              //等做好后才能取到

              return realdata.getContent();

              程序分析

              對于每個請求,host都會生成一個線程,這個線程負責生成顧客需要的“蛋糕”。在等待一段時間以后,如果蛋糕還沒有做好,顧客還必須等待。直到“蛋糕被做好”,也就是

              future.setRealData(realdata); 執行以后,顧客才能拿走蛋糕。

              每個線程只是專門負責制作特定顧客所需要的“蛋糕”。也就是顧客A對應著蛋糕師傅A,tb顧客B對應著蛋糕師傅B。即使顧客B的蛋糕被先做好了,顧客A也只能等待蛋糕師傅A把蛋糕做好。換句話說,顧客之間沒有競爭關系。

              類FutureData的兩個方法被設置為synchronized,實際上蛋糕師傅A與顧客A之間的互斥關系,也就是顧客A必須等待蛋糕師傅A把蛋糕做好后,才能拿走,而與蛋糕師傅B是否做好了蛋糕沒有關系。

             

            posted @ 2012-09-26 11:55 tbwshc 閱讀(689) | 評論 (0)編輯 收藏

            如果我們使用Oracle的oerr程序看看ORA-04068的定義,我們會得到下面的信息:
              $oerr ora 04068
              04068, 00000, "existing state of packages has been discarded"
              // *Cause: One of errors 4060 - 4067 when attempt to execute a stored procedure.
              // *Action: Try again after proper re-initialization of any
              // application's state.

              這個錯誤顯示執行包的現有狀態被另一個會話的一個動作無效化了。這個“狀態”涉及包在規范或體中定義的任何全局變量(包括常量)。引起這個錯誤的動作一般是(但不局限于此)在得到了發生錯誤的會話所使用的連接之后包的重新編譯。Oracle 建議的動作是重新初始化應用程序狀態以調整包的新狀態后重新嘗試。

             

            出現原因:

              一般是系統運行過程中,對Package重新編譯,tbw會導致系統對于這個Session的Package失效。

            解決辦法:

              重啟業務系統,重新獲得Oracle Session。

            避免方案:

              不要在系統運行過程中,對Package重新編譯。



            傳說中的04068啊,這個錯誤在開發中比較容易見到,簡單說,就是你與數據庫建立鏈接后,這個package被編譯過,然后你再去調用這個包,會報這個錯誤,但只會報一次。
            所以比較常見的做法,就是程序catch捕獲異常后,判斷錯誤是否是04068,如果是,重新調用一次,第二次調用就沒問題了。
            posted @ 2012-09-24 15:47 tbwshc 閱讀(1283) | 評論 (0)編輯 收藏

            C語言宏定義技巧(常用宏定義)
               
                寫好C語言,漂亮的宏定義很重要,使用宏定義可以防止出錯,提高可移植性,可讀性,方便性 等等。下面列舉一些成熟軟件中常用得宏定義……
               
                CODE:
               
                1,防止一個頭文件被重復包含
               
                #ifndef COMDEF_H
               
                #define COMDEF_H
               
                //頭文件內容
               
                #endif
               
                2,重新定義一些類型,防止由于各種平臺和編譯器的不同tb ,而產生的類型字節數差異,方便移植。
               
                typedef unsigned char     boolean;   /* Boolean value type. */
               
                typedef unsigned long int uint32;     /* Unsigned 32 bit value */
               
                typedef unsigned short   uint16;     /* Unsigned 16 bit value */
               
                typedef unsigned char     uint8;     /* Unsigned 8 bit value */
               
                typedef signed long int   int32;     /* Signed 32 bit value */
               
                typedef signed short     int16;     /* Signed 16 bit value */
               
                typedef signed char     int8;     /* Signed 8 bit value */
               
                //下面的不建議使用
               
                typedef unsigned char   byte;       /* Unsigned 8 bit value type. */
               
                typedef unsigned short   word;       /* Unsinged 16 bit value type. */
               
                typedef unsigned long   dword;     /* Unsigned 32 bit value type. */
               
                typedef unsigned char   uint1;     /* Unsigned 8 bit value type. */
               
                typedef unsigned short   uint2;     /* Unsigned 16 bit value type. */
               
                typedef unsigned long   uint4;     /* Unsigned 32 bit value type. */
               
                typedef signed char     int1;       /* Signed 8 bit value type. */
               
                typedef signed short     int2;       /* Signed 16 bit value type. */
               
                typedef long int       int4;       /* Signed 32 bit value type. */
               
                typedef signed long     sint31;     /* Signed 32 bit value */
               
                typedef signed short     sint15;     /* Signed 16 bit value */
               
                typedef signed char     sint7;     /* Signed 8 bit value */
               
                3,得到指定地址上的一個字節或字
               
                #define MEM_B( x ) ( *( (byte *) (x) ) )
               
                #define MEM_W( x ) ( *( (word *) (x) ) )
               
                4,求最大值和最小值
               
                #define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
               
                #define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )
               
                5,得到一個field在結構體(struct)中的偏移量
               
                #define FPOS( type, field ) \
               
                /*lint -e545 */ ( (dword) &(( type *) 0)-> field ) /*lint +e545 */
               
                6,得到一個結構體中field所占用的字節數
               
                #define FSIZ( type, field ) sizeof( ((type *) 0)->field )
               
                7,按照LSB格式把兩個字節轉化為一個Word
               
                #define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )
               
                8,按照LSB格式把一個Word轉化為兩個字節
               
                #define FLOPW( ray, val ) \
               
                (ray)[0] = ((val) / 256); \
               
                (ray)[1] = ((val) & 0xFF)
               
                9,得到一個變量的地址(word寬度)
               
                #define B_PTR( var ) ( (byte *) (void *) &(var) )
               
                #define W_PTR( var ) ( (word *) (void *) &(var) )
               
                10,得到一個字的高位和低位字節
               
                #define WORD_LO(xxx) ((byte) ((word)(xxx) & 255))
               
                #define WORD_HI(xxx) ((byte) ((word)(xxx) 》 8))
               
                11,返回一個比X大的最接近的8的倍數
               
                #define RND8( x )     ((((x) + 7) / 8 ) * 8 )
               
                12,將一個字母轉換為大寫
               
                #define UPCASE( c ) ( ((c) >= 'a' && (c) <= 'z‘) ? ((c) - 0x20) : (c) )
               
                13,判斷字符是不是10進值的數字
               
                #define DECCHK( c ) ((c) >= '0' && (c) <= '9’)
               
                14,判斷字符是不是16進值的數字
               
                #define HEXCHK( c ) ( ((c) >= '0' && (c) <= '9‘) ||\
               
                ((c) >= 'A' && (c) <= 'F’) ||\
               
                ((c) >= 'a' && (c) <= 'f‘) )
               
                15,防止溢出的一個方法
               
                #define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
               
                16,返回數組元素的個數
               
                #define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
               
                17,返回一個無符號數n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)
               
                #define MOD_BY_POWER_OF_TWO( val, mod_by ) \
               
                ( (dword)(val) & (dword)((mod_by)-1) )
               
                18,對于IO空間映射在存儲空間的結構,輸入輸出處理
               
                #define inp(port)       (*((volatile byte *) (port)))
               
                #define inpw(port)     (*((volatile word *) (port)))
               
                #define inpdw(port)     (*((volatile dword *)(port)))
               
                #define outp(port, val)   (*((volatile byte *) (port)) = ((byte) (val)))
               
                #define outpw(port, val) (*((volatile word *) (port)) = ((word) (val)))
               
                #define outpdw(port, val) (*((volatile dword *) (port)) = ((dword) (val)))
               
                [2005-9-9添加]
               
                19,使用一些宏跟蹤調試
               
                A N S I標準說明了五個預定義的宏名。它們是:
               
                _ L I N E _
               
                _ F I L E _
               
                _ D A T E _
               
                _ T I M E _
               
                _ S T D C _
            如果編譯不是標準的,則可能僅支持以上宏名中的幾個,或根本不支持。記住編譯程序
               
                也許還提供其它預定義的宏名。
               
                _ L I N E _及_ F I L E _宏指令在有關# l i n e的部分中已討論,這里討論其余的宏名。
               
                _ D AT E _宏指令含有形式為月/日/年的串,表示源文件被翻譯到代碼時的日期。
               
                源代碼翻譯到目標代碼的時間作為串包含在_ T I M E _中。串形式為時:分:秒。
               
                如果實現是標準的,則宏_ S T D C _含有十進制常量1.如果它含有任何其它數,則實現是
               
                非標準的。
               
                可以定義宏,例如:
               
                當定義了_DEBUG,輸出數據信息和所在文件所在行
               
                #ifdef _DEBUG
               
                #define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)
               
                #else
               
                #define DEBUGMSG(msg,date)
               
                #endif
               
                20,宏定義防止使用是錯誤
               
                用小括號包含。
               
                例如:#define ADD(a,b) (a+b)
               
                用do{}while(0)語句包含多語句防止錯誤
               
                例如:#difne DO(a,b) a+b;\
               
                a++;
               
                應用時:if(…)
               
                DO(a,b); //產生錯誤
               
                else
               
                解決方法: #difne DO(a,b) do{a+b;\
               
                a++;}while(0)
               
                宏中“#”和“##”的用法
               
                一、一般用法
               
                我們使用#把宏參數變為一個字符串,用##把兩個宏參數貼合在一起。
               
                用法:
               
                #include<cstdio>
               
                #include<climits>
               
                using namespace std;
               
                #define STR(s)   #s
               
                #define CONS(a,b) int(a##e##b)
               
                int main()
               
                {
               
                printf(STR(vck));       // 輸出字符串“vck”
               
                printf(“%d\n”, CONS(2,3)); // 2e3 輸出:2000
               
                return 0;
               
                }
               
                二、當宏參數是另一個宏的時候
               
                需要注意的是凡宏定義里有用'#’或‘##’的地方宏參數是不會再展開。
               
                1, 非‘#’和‘##’的情況
               
                #define TOW     (2)
               
                #define MUL(a,b) (a*b)
               
                printf(“%d*%d=%d\n”, TOW, TOW, MUL(TOW,TOW));
               
                這行的宏會被展開為:
               
                printf(“%d*%d=%d\n”, (2), (2), ((2)*(2)));
               
                MUL里的參數TOW會被展開為(2)。
               
                2, 當有‘#’或‘##’的時候
               
                #define A       (2)
               
                #define STR(s)   #s
               
                #define CONS(a,b) int(a##e##b)
               
                printf(“int max: %s\n”, STR(INT_MAX));   // INT_MAX #include<climits>
               
                這行會被展開為:
               
                printf(“int max: %s\n”, “INT_MAX”);
               
                printf(“%s\n”, CONS(A, A));           // compile error
               
                這一行則是:
               
                printf(“%s\n”, int(AeA));
               
                INT_MAX和A都不會再被展開, 然而解決這個問題的方法很簡單。 加多一層中間轉換宏。
               
                加這層宏的用意是把所有宏的參數在這層里全部展開, 那么在轉換宏里的那一個宏(_STR)就能得到正確的宏參數。
               
                #define A       (2)
               
                #define _STR(s)   #s
               
                #define STR(s)     _STR(s)       // 轉換宏
               
                #define _CONS(a,b) int(a##e##b)
               
                #define CONS(a,b)   _CONS(a,b)     // 轉換宏
               
                printf(“int max: %s\n”, STR(INT_MAX));       // INT_MAX,int型的最大值,為一個變量 #include<climits>
               
                輸出為: int max: 0x7fffffff
               
                STR(INT_MAX) --> _STR(0x7fffffff) 然后再轉換成字符串;
               
                printf(“%d\n”, CONS(A, A));
               
                輸出為:200
               
                CONS(A, A) --> _CONS((2), (2)) --> int((2)e(2))
               
                三、‘#’和‘##’的一些應用特例
               
                1、合并匿名變量名
               
                #define ___ANONYMOUS1(type, var, line) type var##line
               
                #define __ANONYMOUS0(type, line) ___ANONYMOUS1(type, _anonymous, line)
               
                #define ANONYMOUS(type) __ANONYMOUS0(type, __LINE__)
               
                例:ANONYMOUS(static int); 即: static int _anonymous70; 70表示該行行號;
               
                第一層:ANONYMOUS(static int); --> __ANONYMOUS0(static int, __LINE__);
               
                第二層:                 --> ___ANONYMOUS1(static int, _anonymous, 70);
               
                第三層:                 --> static int _anonymous70;
               
                即每次只能解開當前層的宏,所以__LINE__在第二層才能被解開;
               
                2、填充結構
               
                #define FILL(a)   {a, #a}
               
                enum IDD{OPEN, CLOSE};
               
                typedef struct MSG{
               
                IDD id;
               
                const char * msg;
               
                }MSG;
               
                MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
               
                相當于:
               
                MSG _msg[] = {{OPEN, “OPEN”},
               
                {CLOSE, “CLOSE”}};
               
                3、記錄文件名
               
                #define _GET_FILE_NAME(f)   #f
               
                #define GET_FILE_NAME(f)   _GET_FILE_NAME(f)
               
                static char FILE_NAME[] = GET_FILE_NAME(__FILE__);
               
                4、得到一個數值類型所對應的字符串緩沖大小
               
                #define _TYPE_BUF_SIZE(type) sizeof #type
               
                #define TYPE_BUF_SIZE(type)   _TYPE_BUF_SIZE(type)
               
                char buf[TYPE_BUF_SIZE(INT_MAX)];
               
                --> char buf[_TYPE_BUF_SIZE(0x7fffffff)];
               
                --> char buf[sizeof “0x7fffffff”];
               
                這里相當于:
               
            posted @ 2012-09-22 17:59 tbwshc 閱讀(222) | 評論 (0)編輯 收藏

             二叉堆的實現數據結構中如何使用,我任務主要是在操作系統中的任務優先級調度問題,當然也可以用于實現堆排序問題,比如找出數組中的第K個最小值問題,采用二叉堆能夠快速的實現,今天我就采用C語言實現了一個簡單的二叉堆操作,完成這些數據結構我并不知道能干什么,我就當自己在練習C語言的功底吧。逐步完成自己的代碼,希望自己在知識的理解力上有一定的提高。

                二叉堆是非常有特點的數據結構,可以采用簡單的數組就能實現,當然鏈表的實現也是沒有問題的,畢竟是一個二叉樹問題,當然可以采用鏈表實現。采用數組實現時,可以找到兩個特別明顯的規律:

                左兒子:L_Son = Parent * 2;

                右兒子:R_Son = Parent * 2 + 1;

                二叉堆是一顆完全填滿的樹,可能例外的是在底層,底層上的元素是從左到右填入,當然二叉堆可以是基于大值的排序,也可以是基于小值的排列形式,本文采用簡單的基于小值的形式。主要完成的操作:1、最小值的刪除操作,該操作會刪除根節點,然后提升兒子節點來代替根節點,具體的實現過程中通過提升左右兒子中較小的作為父結點,依此提升直到到達最底層,這種實現方式叫做下慮法。2、數據的插入操作,插入操作可能會破壞二叉堆的結構,一般在最底層創建一個空穴,然后比較插入值與空穴父結點的值,如果大于父結點的值,那么直接插入到空穴中,如果小于父結點,則將父結點的值插入到剛創建的空穴中,在父結點所在位置上形成新的父結點,這時候再和父結點的父結點比較,具體操作如上所述,直到找到具體的插入地址。當結點個數為偶數時,在刪除操作中需要注意節點是否有右兒子的情況。具體的可以參考代碼中的說明。

                具體的實現如下:

                結構體:

                #ifndef __BINARYHEAP_H_H_

                #define __BINARYHEAP_H_H_

                #include <stdlib.h>

                #include <assert.h>

                #define bool int

                #define true 1

                #define false 0

                /*打算采用數組的方式實現完全二叉堆*/

                typedef struct _binaryheap

                {

                /*因為需要動態擴展,

                *采用靜態數組不方便*/

                int * parray;

                /*目前存在的結點*/

                int currentSize;

                /*樹的實際容量*/

                int capacity;

                }BinaryHeap_t, *BinaryHeap_handle_t;

                #ifdef __cplusplus

                extern "C"

                {

                #endif

                bool init_BinaryHeap(BinaryHeap_handle_t heap, int capacity);

                bool alloc_BinaryHeap(BinaryHeap_handle_t *heap, int capacity);

                void delete_BinaryHeap(BinaryHeap_handle_t heap);

                void free_BinaryHeap(BinaryHeap_handle_t *heap);

                bool insert(BinaryHeap_handle_t heap,int value);

                int deleteMin(BinaryHeap_handle_t heap);

                bool isEmpty(BinaryHeap_handle_t heap);

                #ifdef __cplusplus

                }

                #endif

                #endif

                實現的接口函數如下:

                #include "binaryheap.h"

                bool isEmpty(BinaryHeap_handle_t heap)

                {

                assert(heap != NULL);

                return heap->currentSize == 0;

                }

                bool init_BinaryHeap(BinaryHeap_handle_t heap, int capacity)

                {

                int *parray = NULL;

                if(heap == NULL)

                return false;

                parray = (int *)calloc(capacity+1,sizeof(int));

                if(parray == NULL)

                return false;

                heap->parray = parray;

                heap->capacity = capacity;

                heap->currentSize = 0;

                return true;

                }

                void delete_BinaryHeap(BinaryHeap_handle_t heap)

                {

                assert(heap != NULL && heap->parray != NULL);

                heap->capacity = 0;

                heap->currentSize = 0;

                free(heap->parray);

                heap->parray = NULL;

                }

                void free_BinaryHeap(BinaryHeap_handle_t *heap)

                {

                assert(*heap != NULL);

                (*heap)->capacity = 0;

                (*heap)->currentSize = 0;

                free((*heap)->parray);

                (*heap)->parray = NULL;

                free(*heap);

                *heap = NULL;

                }

                bool alloc_BinaryHeap(BinaryHeap_handle_t *heap, int capacity)

                {

                int *parray = NULL;

                if(*heap != NULL)

                return false;

                *heap = (int *)calloc(1, sizeof(BinaryHeap_t));

                if(*heap == NULL)

                return false;

                /*其中的1,主要是為了使得數組從下標1開始計算*/

                parray =(int *)calloc(capacity + 1, sizeof(int));

                if(parray == NULL)

                return false;

                (*heap)->parray = parray;

                (*heap)->capacity = capacity;

                (*heap)->currentSize = 0;

                return true;

                }

                /**************************************************

                * 采用上慮法實現數據的插入操作

                * 上慮法的實現方式比較簡單,首先創建一個空節點

                * 然后將需要插入的值與當前空穴的父結點進行比較

                * 如果大于父結點,直接插入空穴中

                * 如果小于父結點的值,則將父結點的值下拉到空穴中

                * 之前父結點的位置就是空穴,接著與上層比較

                * 直到找到父結點大于當前插入值的情況

                **************************************************/

                bool insert(BinaryHeap_handle_t heap, int value)

                {

                int index = 0;

                if(heap == NULL || heap->parray == NULL)

                return false;

                /*得到一個新的空穴下標*/

                index = ++heap->currentSize;

                /*條件是不是第一個下標和插入值比對應父結點小*/

                while(index > 1 && value < heap->parray[index/2])

                {

                /*將父結點保存到當前結點處*/

                heap->parray[index] = heap->parray[index/2];

                /*得到父結點的空穴位置*/

                index /= 2;

                }

                /*將插入的值保存到剩余的空穴中*/

                heap->parray[index] = value;

                return true;

                }

                /***********************************************************

                * 下慮法實現數據的重排序操作

                * 實現的方式,將子結點的兩個兒子進行比較,將小的提升

                * 需要注意的是如何讓判斷節點是否一定存在右兒子

                * 實現的方式主要是利用了二叉堆的特性:

                * 2*pare = L_child

                * 2*pare + 1 = R_child;

                ***********************************************************/

                static void presort_BinaryHeap(BinaryHeap_handle_t heap,int hole)

                {

                /*這是二叉堆的特性*/

                int child = hole * 2;

                /*保存當前數據操作*/

                int tmp = 0;

                assert(heap != NULL && heap->parray != NULL);

                tmp = heap->parray[hole];

                /*hold * 2 <= heap->currentSize 判斷了當前結點是否為最低層*/

                for(; hole * 2 <= heap->currentSize; hole = child)

                {

                child = hole * 2;

                /*******************************

                *這句代碼解決是否存在右結點的問題

                *并確定了那個子結點提升的問題

                *******************************/

                if((child != heap->currentSize)

                && (heap->parray[child + 1] < heap->parray[child]))

                child ++;

                if(heap->parray[child] < tmp)

                {

                /*將子結點提升為父結點*/

                heap->parray[hole] = heap->parray[child];

                }

                }

                /*到達了最低的層,也就是樹葉*/

                heap->parray[hole] = tmp;

                }

                /*實現數據的下慮法實現數據的刪除操作*/

                int deleteMin(BinaryHeap_handle_t heap)

                {

                int ret = 0;

                int index = 0;

                assert(!isEmpty(heap));

                /*需要返回的值*/

                ret = heap->parray[1];

                /*將最后需要釋放內存空間的值保存到第一個內存空間中*/

                heap->parray[1] = heap->parray[heap->currentSize --];

                /*從表頭開始將新的二叉樹進行重新排序*/

                presort_BinaryHeap(heap, 1);

                return ret;

                }

                測試代碼:

                #include "binaryheap.h"

                #include <stdio.h>

                #include <time.h>

                void print_binaryheap(BinaryHeap_handle_t heap)[nettpage]

                {

                int i = 0;

                assert(heap != NULL && heap->parray != NULL);

                for(i = 1; i <= heap->currentSize; ++ i)

                {

                if(i %6)

                printf("%d\t",heap->parray[i]);

                else

                printf("\n%d\t",heap->parray[i]);

                }

                printf("\n");

                }

                int main()

                {

                int i = 0;

                int value = 0;

                srand((int)time(0));

                printf("********Test Binaryheap**************\n");

                BinaryHeap_t bheap;

                BinaryHeap_handle_t *pheap = NULL;

                printf("init and alloc test:\n");

                if(init_BinaryHeap(&bheap,10))

                {

                printf("init_BinaryHeap() successed!\n");

                }

                if (alloc_BinaryHeap(&pheap,15));

                {

                printf("alloc_BInaryHeap() successed!\n");

                }

                printf("***insert test*****\n");

                for(; i < 10; ++ i)

                {

                if(!insert(&bheap,5 * i - rand()%20))

                {

                printf("i = %d:insert failed !!\n",i);

                }

                }

                for(i = 0; i < 15; ++ i)

                {

                if(!insert(pheap,i * 8 - rand()%20))

                {

                printf("i = %d:insert failed!!\n",i);

                }

                }

                print_binaryheap(&bheap);

                print_binaryheap(pheap);

                printf("****deleteMin test****\n");

                for(i = 0; i < 5; ++ i)

                {

                value = deleteMin(&bheap);

                printf("bheap deleted:%d\n",value);

                value = deleteMin(pheap);

                printf("pheap deleted:%d\n",value);

                }

                print_binaryheap(&bheap);

                print_binaryheap(pheap);

                printf("deleteMin test successed\n");

                printf("****delete and free test:*******\n");

                delete_BinaryHeap(&bheap);

                printf("Is the bheap empty ? %s\n",

                isEmpty(&bheap)?"Yes":"No");

                free_BinaryHeap(&pheap);

                printf("*********Test successed!***********\n");

                pheap = NULL;

                return 0;

                }

                測試結果:

                [gong@Gong-Computer c_binaryheap]$ ./testbinaryheap

                ********Test Binaryheap**************

                init and alloc test:

                init_BinaryHeap()

                alloc_BInaryHeap()

                ***insert test*****

                -11    -9    -9    14    15

                10    21    23    40    26

                -16    2    14    20    13

                21    33    49    61    67    76

                86    83    95    109

                ****deleteMin test****

                bheap deleted:-11

                pheap deleted:-16

                bheap deleted:-9

                pheap deleted:2

                bheap deleted:-9

                pheap deleted:13

                bheap deleted:10

                pheap deleted:14

                bheap deleted:14

                pheap deleted:20

                15    23    21    40    26

                21    49    21    61    67

                76    33    95    83    109

                deleteMin test successed

                ****delete and free test:*******

                Is the bheap empty ? Yes

                *********Test

                從上面的測試結果可知,基本上實現了二叉堆的基本插入、刪除操作。代碼的關鍵點在于刪除中的下慮和插入過程中的上慮操作。以及如何判斷代碼是否存在右兒子,如何充分運用二叉堆的特性。    二叉堆的實現數據結構中如何使用,我任務主要是在操作系統中的任務優先級調度問題,當然也可以用于實現堆排序問題,比如找出數組中的第K個最小值問題,采用二叉堆能夠快速的實現,今天我就采用C語言實現了一個簡單的二叉堆操作,完成這些數據結構我并不知道能干什么,我就當自己在練習C語言的功底吧。逐步完成自己的代碼,希望自己在知識的理解力上有一定的提高。

                二叉堆是非常有特點的數據結構,可以采用簡單的數組就能實現,當然鏈表的實現也是沒有問題的,畢竟是一個二叉樹問題,當然可以采用鏈表實現。采用數組實現時,可以找到兩個特別明顯的規律:

                左兒子:L_Son = Parent * 2;

                右兒子:R_Son = Parent * 2 + 1;

                二叉堆是一顆完全填滿的樹,可能例外的是在底層,底層上的元素是從左到右填入,當然二叉堆可以是基于大值的排序,也可以是基于小值的排列形式,本文采用簡單的基于小值的形式。主要完成的操作:1、最小值的刪除操作,該操作會刪除根節點,然后提升兒子節點來代替根節點,具體的實現過程中通過提升左右兒子中較小的作為父結點,依此提升直到到達最底層,這種實現方式叫做下慮法。2、數據的插入操作,插入操作可能會破壞二叉堆的結構,一般在最底層創建一個空穴,然后比較插入值與空穴父結點的值,如果大于父結點的值,那么直接插入到空穴中,如果小于父結點,則將父結點的值插入到剛創建的空穴中,在父結點所在位置上形成新的父結點,這時候再和父結點的父結點比較,具體操作如上所述,直到找到具體的插入地址。當結點個數為偶數時,在刪除操作中需要注意節點是否有右兒子的情況。具體的可以參考代碼中的說明。

                具體的實現如下:

                結構體:

                #ifndef __BINARYHEAP_H_H_

                #define __BINARYHEAP_H_H_

                #include <stdlib.h>

                #include <assert.h>

                #define bool int

                #define true 1

                #define false 0

                /*打算采用數組的方式實現完全二叉堆*/

                typedef struct _binaryheap

                {

                /*因為需要動態擴展,

                *采用靜態數組不方便*/

                int * parray;

                /*目前存在的結點*/

                int currentSize;

                /*樹的實際容量*/

                int capacity;

                }BinaryHeap_t, *BinaryHeap_handle_t;

                #ifdef __cplusplus

                extern "C"

                {

                #endif

                bool init_BinaryHeap(BinaryHeap_handle_t heap, int capacity);

                bool alloc_BinaryHeap(BinaryHeap_handle_t *heap, int capacity);

                void delete_BinaryHeap(BinaryHeap_handle_t heap);

                void free_BinaryHeap(BinaryHeap_handle_t *heap);

                bool insert(BinaryHeap_handle_t heap,int value);

                int deleteMin(BinaryHeap_handle_t heap);

                bool isEmpty(BinaryHeap_handle_t heap);

                #ifdef __cplusplus

                }

                #endif

                #endif

                實現的接口函數如下:

                #include "binaryheap.h"

                bool isEmpty(BinaryHeap_handle_t heap)

                {

                assert(heap != NULL);

                return heap->currentSize == 0;

                }

                bool init_BinaryHeap(BinaryHeap_handle_t heap, int capacity)

                {

                int *parray = NULL;

                if(heap == NULL)

                return false;

                parray = (int *)calloc(capacity+1,sizeof(int));

                if(parray == NULL)

                return false;

                heap->parray = parray;

                heap->capacity = capacity;

                heap->currentSize = 0;

                return true;

                }

                void delete_BinaryHeap(BinaryHeap_handle_t heap)

                {

                assert(heap != NULL && heap->parray != NULL);

                heap->capacity = 0;

                heap->currentSize = 0;

                free(heap->parray);

                heap->parray = NULL;

                }

                void free_BinaryHeap(BinaryHeap_handle_t *heap)

                {

                assert(*heap != NULL);

                (*heap)->capacity = 0;

                (*heap)->currentSize = 0;

                free((*heap)->parray);

                (*heap)->parray = NULL;

                free(*heap);

                *heap = NULL;

                }

                bool alloc_BinaryHeap(BinaryHeap_handle_t *heap, int capacity)

                {

                int *parray = NULL;

                if(*heap != NULL)

                return false;

                *heap = (int *)calloc(1, sizeof(BinaryHeap_t));

                if(*heap == NULL)

                return false;

                /*其中的1,主要是為了使得數組從下標1開始計算*/

                parray =(int *)calloc(capacity + 1, sizeof(int));

                if(parray == NULL)

                return false;

                (*heap)->parray = parray;

                (*heap)->capacity = capacity;

                (*heap)->currentSize = 0;

                return true;

                }

                /**************************************************

                * 采用上慮法實現數據的插入操作

                * 上慮法的實現方式比較簡單,首先創建一個空節點

                * 然后將需要插入的值與當前空穴的父結點進行比較

                * 如果大于父結點,直接插入空穴中

                * 如果小于父結點的值,則將父結點的值下拉到空穴中

                * 之前父結點的位置就是空穴,接著與上層比較

                * 直到找到父結點大于當前插入值的情況

                **************************************************/

                bool insert(BinaryHeap_handle_t heap, int value)

                {

                int index = 0;

                if(heap == NULL || heap->parray == NULL)

                return false;

                /*得到一個新的空穴下標*/

                index = ++heap->currentSize;

                /*條件是不是第一個下標和插入值比對應父結點小*/


            while(index > 1 && value < heap->parray[index/2])

                {

                /*將父結點保存到當前結點處*/

                heap->parray[index] = heap->parray[index/2];

                /*得到父結點的空穴位置*/

                index /= 2;

                }

                /*將插入的值保存到剩余的空穴中*/

                heap->parray[index] = value;

                return true;

                }

                /***********************************************************

                * 下慮法實現數據的重排序操作

                * 實現的方式,將子結點的兩個兒子進行比較tbw,將小的提升

                * 需要注意的是如何讓判斷節點是否一定存在右兒子

                * 實現的方式主要是利用了二叉堆的特性:

                * 2*pare = L_child

                * 2*pare + 1 = R_child;

                ***********************************************************/

                static void presort_BinaryHeap(BinaryHeap_handle_t heap,int hole)

                {

                /*這是二叉堆的特性*/

                int child = hole * 2;

                /*保存當前數據操作*/

                int tmp = 0;

                assert(heap != NULL && heap->parray != NULL);

                tmp = heap->parray[hole];

                /*hold * 2 <= heap->currentSize 判斷了當前結點是否為最低層*/

                for(; hole * 2 <= heap->currentSize; hole = child)

                {

                child = hole * 2;

                /*******************************

                *這句代碼解決是否存在右結點的問題

                *并確定了那個子結點提升的問題

                *******************************/

                if((child != heap->currentSize)

                && (heap->parray[child + 1] < heap->parray[child]))

                child ++;

                if(heap->parray[child] < tmp)

                {

                /*將子結點提升為父結點*/

                heap->parray[hole] = heap->parray[child];

                }

                }

                /*到達了最低的層,也就是樹葉*/

                heap->parray[hole] = tmp;

                }

                /*實現數據的下慮法實現數據的刪除操作*/

                int deleteMin(BinaryHeap_handle_t heap)

                {

                int ret = 0;

                int index = 0;

                assert(!isEmpty(heap));

                /*需要返回的值*/

                ret = heap->parray[1];

                /*將最后需要釋放內存空間的值保存到第一個內存空間中*/

                heap->parray[1] = heap->parray[heap->currentSize --];

                /*從表頭開始將新的二叉樹進行重新排序*/

                presort_BinaryHeap(heap, 1);

                return ret;

                }

                測試代碼:

                #include "binaryheap.h"

                #include <stdio.h>

                #include <time.h>

                void print_binaryheap(BinaryHeap_handle_t heap)

                {

                int i = 0;

                assert(heap != NULL && heap->parray != NULL);

                for(i = 1; i <= heap->currentSize; ++ i)

                {

                if(i %6)

                printf("%d\t",heap->parray[i]);

                else

                printf("\n%d\t",heap->parray[i]);

                }

                printf("\n");

                }

                int main()

                {

                int i = 0;

                int value = 0;

                srand((int)time(0));

                printf("********Test Binaryheap**************\n");

                BinaryHeap_t bheap;

                BinaryHeap_handle_t *pheap = NULL;

                printf("init and alloc test:\n");

                if(init_BinaryHeap(&bheap,10))

                {

                printf("init_BinaryHeap() successed!\n");

                }

                if (alloc_BinaryHeap(&pheap,15));

                {

                printf("alloc_BInaryHeap() successed!\n");

                }

                printf("***insert test*****\n");

                for(; i < 10; ++ i)

                {

                if(!insert(&bheap,5 * i - rand()%20))

                {

                printf("i = %d:insert failed !!\n",i);

                }

                }

                for(i = 0; i < 15; ++ i)

                {

                if(!insert(pheap,i * 8 - rand()%20))

                {

                printf("i = %d:insert failed!!\n",i);

                }

                }

                print_binaryheap(&bheap);

                print_binaryheap(pheap);

                printf("****deleteMin test****\n");

                for(i = 0; i < 5; ++ i)

                {

                value = deleteMin(&bheap);

                printf("bheap deleted:%d\n",value);

                value = deleteMin(pheap);

                printf("pheap deleted:%d\n",value);

                }

                print_binaryheap(&bheap);

                print_binaryheap(pheap);

                printf("deleteMin test successed\n");

                printf("****delete and free test:*******\n");

                delete_BinaryHeap(&bheap);

                printf("Is the bheap empty ? %s\n",

                isEmpty(&bheap)?"Yes":"No");

                free_BinaryHeap(&pheap);

                printf("*********Test successed!***********\n");

                pheap = NULL;

                return 0;

                }

                測試結果:

                [gong@Gong-Computer c_binaryheap]$ ./testbinaryheap

                ********Test Binaryheap**************

                init and alloc test:

                init_BinaryHeap()

                alloc_BInaryHeap()

                ***insert test*****

                -11    -9    -9    14    15

                10    21    23    40    26

                -16    2    14    20    13

                21    33    49    61    67    76

                86    83    95    109

                ****deleteMin test****

                bheap deleted:-11

                pheap deleted:-16

                bheap deleted:-9

                pheap deleted:2

                bheap deleted:-9

                pheap deleted:13

                bheap deleted:10

                pheap deleted:14

                bheap deleted:14

                pheap deleted:20

                15    23    21    40    26

                21    49    21    61    67

                76    33    95    83    109

                deleteMin test successed

                ****delete and free test:*******

                Is the bheap empty ? Yes

                *********Test

                從上面的測試結果可知,基本上實現了二叉堆的基本插入、刪除操作。tbw代碼的關鍵點在于刪除中的下慮和插入過程中的上慮操作。以及如何判斷代碼是否存在右兒子,如何充分運用二叉堆的特性。

            posted @ 2012-09-22 17:58 tbwshc 閱讀(345) | 評論 (0)編輯 收藏

             一,static和extern:
               
                大工程下我們會碰到很多源文檔。
               
                文檔a.c
               
                static int i; //只在a文檔中用
               
                int j;    //在工程里用
               
                static void init()         //只在a文檔中用
               
                {
               
                }
               
                void callme()          //在工程中用
               
                {
               
                static int sum;
               
                }
               
                上面的全局i變量和init()函數只能用在a.c文檔中,全局變量sum的作用域只在callme里。變量j和函數callme()的全局限擴充到整個工程文檔。所以能夠在下面的b.c中用extern關鍵字調用。extern告訴編譯器這個變量或函數在其他文檔里已被定義了。
               
                文檔b.c
               
                extern int j;     //調用a文檔里的
               
                extern void callme();  //調用a文檔里的
               
                int main()
               
                {
               
                …
               
                }
               
                extern的另外用法是當C和C++混合編程時假如c++調用的是c源文檔定義的函數或變量,那么要加extern來告訴編譯器用c方式命名函數:
               
                文檔A.cpp調用a.c里面的變量i和函數callme()
               
                extern “C”  //在c++文檔里調用c文檔中的變量
               
                {
               
                int j;
               
                void callme();
               
                }
               
                int main()
               
                {
               
                callme();
               
                }
               
                二,static法則:
               
                A、若全局變量僅在單個C文檔中訪問,則能夠將這個變量修改為靜態全局變量,tbw以降低模塊間的耦合度;
               
                B、若全局變量僅由單個函數訪問,則能夠將這個變量改為該函數的靜態局部變量,以降低模塊間的耦合度;
               
                C、設計和使用訪問動態全局變量、靜態全局變量、靜態局部變量的函數時,需要考慮重入問題;
            posted @ 2012-09-22 17:56 tbwshc 閱讀(1427) | 評論 (0)編輯 收藏

                1、malloc函數:向系統申請分配指定size個字節的內存空間,分配成功后得到的是一個內存塊,即連續的空間
               
                2、malloc分配不一定成功,所以最好驗證一下:
               
                char *mallo;
               
                if ((mallo=(char *)malloc(36*sizeof(char)))==NULL)
               
                printf(“error in mallo!\n”);
               
                3、傳指針參數的原理在譚浩強書上已經講過,這里只是做傳指針后實際的賦值方式探討
               
                傳遞過來的參數:char *mallo
               
                3.1:mallo=“bag”;/*直接=不成功,調用后mallo只能在這個函數中打印出,調用這個函數的函數卻不能在調用后得到相應的賦值結果*/
               
                3.2:for(;i<36;i++)
               
                {
               
                *(mallo++)='a'+rand()%26;
               
                //mallo[i]='a'+rand()%26;/*這句和上句的效果相同*/
               
                }/*for循環可以成功:依次賦值隨進字母*/
               
                3.3:char *test=mallo;
               
                for(;i<36;i++)
               
                {
               
                *(test++)='a'+rand()%26;
               
                //test[i]='a'+rand()%26;
               
                }/*效果和3.2基本相同,只是讓思路更清晰的一種做法*/
               
                3.4:strcpy(mallo,“bag”);/*strcpy可以成功:strcpy會把“bag”中的三個字符和‘\0’一個一個的拷貝到mallo中,和上面的for循環類似*/
               
                一開始在Linux下這種方式并沒成功,在windows下添加#includes<string.h>后成功了(windows下沒有這個include會報錯),再回到Linux下也能賦值成功,估計可能是沒有#includes<string.h>的緣故,但
               
                奇怪的是,我再去掉#includes<string.h>,還是成功,原因便無從知曉了。
               
                4、源碼
               
                #include <stdio.h>
               
                #include <stdlib.h>
               
                #include <string.h>
               
                #include <memory.h>
               
                /*接受傳過來的指針,并通過幾種方式賦值*/
               
                void memtest(char *mallo)
               
                {
               
                int i=0;
               
                //char *test=mallo;
               
                printf(“===============================================================”);
               
                //printf(“\n*mallo:%s\n”,*mallo);
               
                printf(“\nmallo: %s\n”,mallo);
               
                /*for(;i<36;i++)
               
                {
               
                *(mallo++)='a'+rand()%26;
               
                mallo[i]='a'+rand()%26;
               
                }*//*for循環可以成功*/
               
                strcpy(mallo,“bag”);/*strcpy可以成功*/
               
                //mallo=“bag”;/*直接=不成功*/
               
                //printf(“test:%s\n”,test);
               
                printf(“\n\”bug\“ ->mallo: %s\n”,mallo);
               
                }
               
                void main()
               
                {
               
                char *mallo;
               
                if ((mallo=(char *)malloc(36*sizeof(char)))==NULL)/*申請空間*/
               
                printf(“error in mallo!\n”);
               
                //memset(mallo,1,sizeof(mallo));
               
                //mallo=“shanghaimizhuan”;
               
                printf(“mallo_main: %s\n”,mallo);/*打印申請空間內容,在windows下為亂碼,而Linux下不顯示*/
               
                /*以下打印數據在Linux和windows下數據不同,在賦值成功前windows已經會檢測上面分配的空間大小,Linux則不會:strlen(mallo)可以看出*/
               
                printf(“sizeof(mallo):%d--分割線--sizeof(*mallo):%d--分割線--strlen(mallo):%d\n”,sizeof(mallo),sizeof(*mallo),strlen(mallo));
               
                memtest(mallo);/*調用賦值函數*/
               
                printf(“===============================================================”);
               
                printf(“\nmallo_aftersetparam:%s\n”,mallo);/*tbw調用后輸出*/
               
                printf(“sizeof(mallo):%d--分割線--sizeof(*mallo):%d--分割線--strlen(mallo):%d\n”,sizeof(mallo),sizeof(*mallo),strlen(mallo));
               
                free(mallo);
               
                }
            posted @ 2012-09-16 14:10 tbwshc 閱讀(1601) | 評論 (1)編輯 收藏

                最近的幾次文章的評論中不少讀者提到文章的更新速度的更新量的問題,淺墨會逐漸重視起來,盡量在保證質量的基礎上,每周都拿出夠分量的內容。本周的文章算是近幾次更新量的一個彌補,這篇文章的字數達到了近一萬字。
               
                一、DirectX11的現有組件
               
                DirectX的API被分為頗多組件,每一組件都展現了系統不同方面的功能。其中的每一套API都能被獨立的使用,因此我們可以按照所需有選擇地自由添加我們游戲中需要的功能。在最新版本的DirectX中,不少組件迎來了更新,如Direct3D.其他的組件保持著現有的功能,當然,也有一些被棄用的組件面臨著被移除的命運。值得一提的是,DirectX中的各個內部組件可以獨立進行新功能的升級。
               
                下面進行分別介紹:
               
                1.Direct2D
               
                Direct2D用于Win32應用程序中2D圖形的繪制。Direct2D善于高性能矢量圖形的渲染。
               
                2. DirectWrite
               
                DirectWrite用于Direct2D應用程序中的字體和文字渲染。
               
                3 . DXGI
               
                DXGI(DirectX Graphics Infrastructure)即DirectX圖形基礎,用于
               
                Direct3D交換鏈(swap chains)和枚舉設備適配器(enumeration of deviceadapters)的創建。
               
                4 .Direct3D
               
                Direct3D用于DirectX中所有的與3D圖形相關的操作。Direct3D可謂DirectX中的大牌級API,受到了微軟最多的關懷與多次針對性的更新,它也最多被世人所熟知。這個專欄后續內容的大部分的篇幅將集中于講解Direct3D上。
               
                5. XAudio2
               
                XAudio2 是一款底層的音頻處理API,以前為XDK(Xbox Development Kit)的一部分,目前,隸屬于DIRECTXSDK.XAudio2替換了DirectSound.初始版本的XAudio用于的第一代Xbox游戲機。
               
                6. XACT3
               
                XACT3是一款建立在XAudio2之上的更高級別的音頻處理API.XACT3允許開發者在他們的應用中使用跨平臺音頻創作工具。若開發者希望從底層控制音頻系統或者希望創建自己的類型于XACT3的更高級別的音頻系統,可以運用XAdio2來完成各項功能。tbwXACT3,我們已經在附錄B中討論過,作為“DIRECTX中的聲音”從配套網站,是一款非常容易上手的游戲音頻制作工具。
               
                7. XInput
               
                XInput是XDK和DirectX SDK的負責輸入功能的 API,用于處理Xbox 360控制器輸入?;旧先魏慰梢栽赬box 360上可以使用的命令,都可以在PC上使用,而XInput就是幫助我們在這些設備上進行輸入相關操作的API.這些設備不僅包含Xbox手柄,也包含了其他很多設備。需要說明的是,XInput 替換了之前版本的DirectInput.
               
                注:XAudio是只能用于Xbox游戲機的音效API. XAudio2,其繼任者,可用于Xbox游戲機和基于Windows的PC.
               
                8 . XNAMath
               
                新出現的XNA Math 不是一款API,而是是一個數學庫,進行電子游戲中常見運算的優化工作。XNA Math采用了SIMD (Single Instruction Multiple Data單指令多數據)來執行多個操作的單指令調用。XNA Math庫適用于基于Windows的PC以及Xbox 360.相關內容我們將在后續內容繼續講解。
               
                注:XNA GameStudio為一款基于DirectX的游戲開發工具,可供我們使用C#和。NET編程語言來為Xbox360與Windows PC平臺編寫游戲。而XNA Math是一款DirectX SDK中數學庫的名字,可獨立于XNA Game Studio單獨使用。我們使用XNA Math不必下載XNA Game Studio SDK.


                
                9 . DirectCompute
               
                DirectCompute是一款DIRECTX 11中新加入的API,作用為支持GPU的通用多線程計算(general purpose multi threading computing)。GPU具有并行處理多任務的能力,如物理,視頻壓縮與視頻解壓,音頻處理等。并非所有的任務都適合GPU來完成,但是對于這些,由GPU來完成的可能性是巨大的(but for those that are, the possibilities are tremendous)。想了解DirectCompute的更多信息,可以查閱相關資料。
               
                10. DirectSetup
               
                當我們完成游戲開發的時候,我們理所當然地需要把完成品呈現給用戶。DirectSetup給我們提供了在用戶的電腦上安裝最新版本的DirectX的功能。DirectSetup也具有檢查已經安裝了的DirectX版本號的功能。
               
                11.Windows Games Explorer
               
                WindowsGames Explorer(游戲資源管理器)是Windows Vista與Windows 7中的新特性,可供游戲開發者在他們的操作系統上展示(測試)他們的游戲。比如游戲的顯示,標題,評級,描述,特定區域的風格框,評分內容(如M為成人,T為青少年等),游戲數據統計和通知,家長控制等。DirectX SDK中提供了大量如何使用自己的游戲的游戲資源管理器的教程,這對于發行一款游戲是非常有用的。下面的圖1是淺墨電腦上的Windows7游戲資源管理器的界面截圖

            posted @ 2012-09-16 14:09 tbwshc 閱讀(1877) | 評論 (1)編輯 收藏

            這里我們提出一種游戲循環的概念,游戲循環是將原先程序中的消息循環加以修改,方法是判斷其中的內容目前是否有要處理的消息,如果有則進行處理,否則按照設定的時間間隔來重繪畫面。下面是接下來一段游戲循環的程序代碼:
               
                //游戲循環
               
                while( msg.message!=WM_QUIT )               //注釋點1(詳細內容見下)
               
                {
               
                if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) )       //注釋點2(詳細內容見下)
               
                {
               
                TranslateMessage( &msg );
               
                DispatchMessage( &msg );
               
                }
               
                else
               
                {
               
                tNow = GetTickCount();                        //注釋點3
               
                if(tNow-tPre >= 100)                   //注釋點4
               
                MyPaint(hdc);
               
                }
               
                }
               
                我們來講解一下游戲循環片段中的幾個重點。
               
                <1>注釋點1:當收到的msg.message不是窗口結束消息WM_QUIT,則繼續運行循環,其中msg是一個MSG的消息結構,其結構成員message則是一個消息類型的代號。
               
                <2>注釋點2:使用PeekMessage()函數來檢測目前是否有需要處理的消息,若檢測到消息(包含WM_QUIT消息)則會返回一個非“0”值,否則返回“0”.因此在游戲循環中,若檢測到消息便進行消息的處理,否則運行else敘述之后的程序代碼。這里我們要注意的是,PeekMessage()函數不能用原先消息循環的條件GetMessage()取代,因為GetMessage()函數只有在取得WM_QUIT消息時才會返回“0”,其他時候則是返回非“0”值或“-1”(發生錯誤時)
               
                <3>注釋點3:GetTickCount()函數會取得系統開始運行到目前所經過的時間,單位是毫秒(milliseconds)。  之前我理解錯了,在這里感謝worldy的指出我的錯誤。
               
                DWORD GetTickCount()    //取得系統開始到目前經過的時間
               
                這里取得時間的目的主要是可以搭配接下來的判斷式,用來調整游戲運行的速度,使得游戲不會因為運行計算機速度的不同而跑得太快或者太慢。

                
                <4>注釋點4:if條件式中,“tPre”記錄前次繪圖的時間,而“tNow-tRre”則是計算上次繪圖到這次循環運行之間相差多少時間。這里設置為若相差40個單位時間以上則再次進行繪圖的操作,通過這個數值的控制可以調整游戲運行的速度。這里設定40個單位時間(微秒)的原因是,因為每隔40個單位進行一次繪圖的操作,那么1秒鐘大約重繪窗口1000/40=25次剛好可以達到期望值。
               
                由于循環的運行速度遠比定時器發出時間信號來得快,因此使用游戲循環可以更精準地控制程序運行速度并提高每秒鐘畫面重繪的次數。
               
                了解了游戲循環使用的基本概念之后,接下來的范例將以游戲循環的方法進行窗口的連續貼圖,更精確地制作游戲動畫效果。
               
                #include “stdafx.h”
               
                #include <stdio.h>
               
                //全局變量聲明
               
                HINSTANCE hInst;
               
                HBITMAP man[7];
               
                HDC  hdc,mdc;
               
                HWND    hWnd;
               
                DWORD   tPre,tNow,tCheck;                 //聲明三個函數來記錄時間,tPre記錄上一次繪圖的時間,tNow記錄此次準備繪圖的時間,tCheck記錄每秒開始的時間
               
                int  num,frame,fps;                    //num用來記錄圖號,frame用來累加每次畫面更新的次數,fps(frame per second)用來記錄每秒畫面更新的次數
               
                //全局函數的聲明
               
                ATOM     MyRegisterClass
               
                (HINSTANCE hInstance);
               
                BOOL     InitInstance
               
                (HINSTANCE, int);
               
                LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM,
               
                LPARAM);
               
                void     MyPaint(HDC hdc);
               
                //***WinMain函數,程序入口點函數**************************************
               
                int APIENTRY WinMain(HINSTANCE hInstance,
               
                HINSTANCE hPrevInstance,
               
                LPSTR     lpCmdLine,
               
                int       nCmdShow)
               
                {
               
                MSG msg;
               
                MyRegisterClass(hInstance);
               
                //運行初始化函數
               
                if (!InitInstance (hInstance, nCmdShow))
               
                {
               
                return FALSE;
               
                }
               
                GetMessage(&msg,NULL,NULL,NULL);   //感謝xiaoxiangp的提醒,需要在進入消息循環之前初始化msg,避免了死循環發生的可能性。
               
                //游戲循環
               
                while( msg.message!=WM_QUIT )
               
                {
               
                if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) )
               
                {
               
                TranslateMessage( &msg );
               
                DispatchMessage( &msg );
               
                }
               
                else
               
                {
               
                tNow = GetTickCount();
               
                if(tNow-tPre >= 100)        //當此次循環運行與上次繪圖時間相差0.1秒時再進行重繪操作
               
                MyPaint(hdc);
               
                }
               
                }
               
                return msg.wParam;
               
                }
               
                //****設計一個窗口類,類似填空題,使用窗口結構體*************************
               
                ATOM MyRegisterClass(HINSTANCE hInstance)
               
                {
               
                WNDCLASSEX wcex;
               
                wcex.cbSize = sizeof(WNDCLASSEX);
               
                wcex.style   = CS_HREDRAW |
               
                CS_VREDRAW;
               
                wcex.lpfnWndProc    = (WNDPROC)WndProc;
               
                wcex.cbClsExtra  = 0;
               
                wcex.cbWndExtra  = 0;
               
                wcex.hInstance   = hInstance;
               
                wcex.hIcon   = NULL;
               
                wcex.hCursor     = NULL;
               
                wcex.hCursor     = LoadCursor(NULL,
               
                IDC_ARROW);
               
                wcex.hbrBackground  = (HBRUSH)
               
                (COLOR_WINDOW+1);
               
                wcex.lpszMenuName   = NULL;
               
                wcex.lpszClassName  = “canvas”;
               
                wcex.hIconSm     = NULL;
               
                return RegisterClassEx(&wcex);
               
                }
               
                //****初始化函數*************************************
               
                // 從文件加載位圖
               
                BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
               
                {
               
                char filename[20] = “”;
               
                int i;
               
                hInst = hInstance;
               
                hWnd = CreateWindow(“canvas”, “動畫演示” ,
               
                WS_OVERLAPPEDWINDOW,
               
                CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
               
                NULL, NULL, hInstance, NULL);
               
                if (!hWnd)
               
                {
               
                return FALSE;
               
                }
               
                MoveWindow(hWnd,10,10,600,450,true);
               
                ShowWindow(hWnd, nCmdShow);
               
                UpdateWindow(hWnd);
               
                hdc = GetDC(hWnd);
               
                mdc = CreateCompatibleDC(hdc);
               
                //載入各個人物位圖
               
                for(i=0;i<7;i++)
               
                {
               
                sprintf(filename,“man%d.bmp”,i);
               
                man[i] = (HBITMAP)LoadImage
               
                (NULL,filename,IMAGE_BITMAP,640,480,LR_LOADFROMFILE);
               
                }
               
                num = 0;
               
                frame = 0;
               
                MyPaint(hdc);
               
                return TRUE;
               
                }
               
                //****自定義繪圖函數*********************************
               
                // 1.計算與顯示每秒畫面更新次數
               
                // 2.按照圖號順序進行窗口貼圖
               
                void MyPaint(HDC hdc)
               
                {
               
                char str[40] = “”;
               
                if(num == 7)
               
                num = 0;
               
                frame++;            //畫面更新次數加1
               
                if(tNow - tCheck >= 1000)               //tbw判斷此次繪圖時間由前一秒算起是否已經達到1秒鐘的時間間隔。若是,則將目前的‘frame’值賦給“fps”,表示這一秒內所更新的畫面次數,然后將“frame”值回0,并重設下次計算每秒畫面數的起始時間“iCheck”.
               
                {
               
                fps = frame;
               
                frame = 0;
               
                tCheck = tNow;
               
                }
               
                SelectObject(mdc,man[num]);         //選用要更新的圖案到mdc中,再輸出顯示每秒畫面更新次數的字符串到mdc上,最后將mdc的內容貼到窗口中。
               
                sprintf(str,“每秒顯示 %d個畫面”,fps);
               
                TextOut(mdc,0,0,str,strlen(str));
               
                BitBlt(hdc,0,0,600,450,mdc,0,0,SRCCOPY);
               
                tPre = GetTickCount();     //記錄此次繪圖時間,供下次游戲循環中判斷是否已經達到畫面更新操作設定的時間間隔。
               
                num++;
               
                }
               
                //******消息處理函數*********************************
               
                LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
               
                WPARAM wParam, LPARAM lParam)
               
                {
               
                int i;
               
                switch (message)
               
                {
               
                case WM_DESTROY:     //窗口結束消息
               
                DeleteDC(mdc);
               
                for(i=0;i<7;i++)
               
                DeleteObject(man[i]);
               
                ReleaseDC(hWnd,hdc);
               
                PostQuitMessage(0);
               
                break;
               
                default:     //其他消息
               
                return DefWindowProc(hWnd,
               
                message, wParam, lParam);
               
                }
               
                return 0;
               
                }
               
                程序的運行結果如下圖:
            posted @ 2012-09-16 14:07 tbwshc 閱讀(120) | 評論 (0)編輯 收藏

            dw_1.find()求符合條件的數據記錄,高手幫忙看下
            取值條件:
            工號= MZGHYYDJ.DJRY
            姓名= MZGHYYDJ.DJRYXM
            總預約數量=MZGHYYDJ 的記錄數
            有效預約數量=MZGHYYDJ.ZFRY IS NULL 的記錄數
            已取號數量= MZGHYYDJ.ZFRY IS NULL AND MZGHYYDJ.MZH IS NOT NUL

            代碼:
            For ll_i = 1 to ids_fdmcb.rowcount( )
            ls_userbz = ids_fdmcb.object.userbz[ll_i] + '.'
            ls_sql = " SELECT A.DJRY,A.DJRYXM,isnull(A.ZFRY,''), isnull(A.MZH,'')"
            ls_sql += " FROM "+ls_userbz+"MZGHYYDJ A "
            ls_sql += " GROUP BY A.DJRY ,A.DJRYXM"

            DECLARE c1 DYNAMIC CURSOR FOR SQLSA;
            PREPARE SQLSA FROM :ls_sql;
            OPEN DYNAMIC c1 USING :lde_minno,:lde_maxno;
            do while true 
            fetch c1 into :ls_djry,:ls_djryxm,:lde_zfry,:lde_mzh ;
            if sqlca.sqlcode<>0 then
            exit;
            end if
            ll_row = dw_1.find(" djry ='"+ls_djry+"' ",1, dw_1.rowcount( ) )
            ll_row1 = dw_1.find(" djry ='"+ls_djry+"' AND zfry='' ",1, dw_1.rowcount( ) )
            ll_row2 = dw_1.find(" djry ='"+ls_djry+"' AND zfry='' AND mzh<>'' ",1, dw_1.rowcount( ) )
            If ll_row <= 0 then
            ll_row = dw_1.insertrow(0)
            dw_1.object.djry[ll_row] = ls_djry
            dw_1.object.djryxm[ll_row] = ls_djryxm
            End If
            dw_1.object.zyy[ll_row] = dw_1.object.zyy[ll_row] + 1
            dw_1.object.yxyy[ll_row1] = dw_1.object.yxyy[ll_row1] + 1
            dw_1.object.yqh[ll_row2] = dw_1.object.yqh[ll_row2] + 1
            loop;
            close c1;
            Next

            ------解決方案--------------------------------------------------------
            太混亂了.
            ------解決方案--------------------------------------------------------
            沒看明白
            ------解決方案--------------------------------------------------------
            每個人的解題思路都不太一樣,理解別人思路有時候比自己寫還難

            本身你交待的問題不夠明確,要想實現的目的也沒有明確,一般是不愿意也沒時間去仔細分析的

            最好你把要求、目的和遇到的問題寫清楚,這樣別人也容易幫忙

            有時候你在標明語句的用途時,tb自己就能找出問題的所在
            ------解決方案--------------------------------------------------------
            dw_1.object.zyy[ll_row] = dw_1.object.zyy[ll_row] + 1

            這種寫法,在多人并行運行的時候會出現問題的
            ------解決方案--------------------------------------------------------
            自己的業務邏輯思路沒想好。
            ------解決方案--------------------------------------------------------
            工號= MZGHYYDJ.DJRY
            姓名= MZGHYYDJ.DJRYXM
            總預約數量=MZGHYYDJ 的記錄數
            有效預約數量=MZGHYYDJ.ZFRY IS NULL 的記錄數
            已取號數量= MZGHYYDJ.ZFRY IS NULL AND MZGHYYDJ.MZH IS NOT NUL


            樓主 到底想干嘛。。??吹暮锖堪?。。。

            如果只是需要查詢 上面 這些 數據。。那從 sql 里面直接查詢不就是了??算法你基本已明確了。。。
            干嘛 在 那里 繞圈。。。又是游標 又是 dw的。。。。

            如果你想實現 查詢每個員工的 工號,姓名,總預約數量,有效預約數量,已取號數量 就使用子查詢。。在 sql里面。。。

            select a.工號,a.姓名,a.總預約數量,b.有效預約數量,c.已取號數量
            from 
            (select MZGHYYDJ.DJRY 工號,MZGHYYDJ.DJRYXM 姓名,count(*) 總預約數量
            from MZGHYYDJ
            group by DJRY,DJRYXM) a
             left join 
            (select MZGHYYDJ.DJRY 工號,MZGHYYDJ.DJRYXM 姓名,count(*) 有效預約數量
            from MZGHYYDJ
            and MZGHYYDJ.ZFRY IS NULL
            group by DJRY,DJRYXM) b
            on a.DJRY=b.DJRY and a.DJRYXM=b.DJRYXM
             left join 
            (select MZGHYYDJ.DJRY 工號,MZGHYYDJ.DJRYXM 姓名,count(*) 已取號數量
            from MZGHYYDJ
            and MZGHYYDJ.ZFRY IS NULL AND MZGHYYDJ.MZH IS NOT NUL
            group by DJRY,DJRYXM) c
            on a.DJRY=c.DJRY and a.DJRYXM=c.DJRYXM


            ------解決方案--------------------------------------------------------
            確實沒看明白。。加點注釋吧。。
            posted @ 2012-09-08 13:34 tbwshc 閱讀(480) | 評論 (0)編輯 收藏

            僅列出標題
            共10頁: 1 2 3 4 5 6 7 8 9 Last 
            久久国产乱子伦精品免费强| 一本久久a久久精品亚洲| 久久一区二区三区免费| 亚洲午夜福利精品久久| 国产精品99精品久久免费| 久久综合综合久久综合| 性做久久久久久久久老女人| 久久久久人妻一区二区三区vr| 久久综合亚洲色HEZYO国产 | 久久精品国产亚洲麻豆| 久久久久亚洲AV无码专区桃色| 色欲综合久久中文字幕网| 久久夜色精品国产www| 中文字幕乱码人妻无码久久| 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲 | 日韩电影久久久被窝网| 精品久久久久久无码中文字幕一区| 久久精品无码免费不卡| 99久久精品免费国产大片| 波多野结衣中文字幕久久 | 五月丁香综合激情六月久久| 国产精品99久久不卡| 久久亚洲日韩精品一区二区三区| 久久久久久噜噜精品免费直播| 国产精品对白刺激久久久| 亚洲国产精品18久久久久久| 日韩欧美亚洲综合久久影院Ds| 亚洲国产成人久久综合碰碰动漫3d| 久久久国产精华液| 久久久久久久女国产乱让韩| 久久天天躁狠狠躁夜夜2020老熟妇 | 久久综合丝袜日本网| 88久久精品无码一区二区毛片 | 久久影院综合精品| 久久无码AV中文出轨人妻| 久久人人爽人人精品视频| 丰满少妇人妻久久久久久4| 国内精品久久久久久麻豆| 日韩十八禁一区二区久久 | 久久66热人妻偷产精品9| 久久这里只有精品18|