青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

tbwshc

tbw

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

常用鏈接

留言簿(4)

我參與的團隊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

#

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

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

 public Node(int no){
  this. no=no
 }
 }
public static void main(String[]args)  {
      SCanner scanner=new Scanner(System.in);
      System.out.print('out. print("請輸入總?cè)藬?shù):");
      int totalNum=scanner. nextInt);
      System.out.print("請輸入報數(shù)的大小:");
      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;
//初始化環(huán)形鏈表結(jié)束
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 閱讀(956) | 評論 (-1)編輯 收藏

  在JAVA平臺,實現(xiàn)異步調(diào)用的角色有如下三個角色:調(diào)用者 提貨單 真實數(shù)據(jù)一個調(diào)用者在調(diào)用耗時操作,不能立即返回數(shù)據(jù)時,先返回一個提貨單.然后在過一斷時間后憑提貨單來獲取真正的數(shù)據(jù).去蛋糕店買蛋糕,不需要等蛋糕做出來(假設現(xiàn)做要很長時間),只需要領(lǐng)個提貨單就可以了(去干別的事情),等到蛋糕做好了,再拿提貨單取蛋糕就可以了。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就相當于“蛋糕店”,顧客向“蛋糕店”定蛋糕就相當于“發(fā)請求request”,返回的數(shù)據(jù)data是FutureData的實例,就相當于提貨單,而不是真正的“蛋糕”。在過一段時間后(sleep一段時間后),調(diào)用data1.getContent(),也就是tb拿提貨單獲取執(zhí)行結(jié)果。

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

  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() {

  //在匿名內(nèi)部類中使用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,而不是蛋糕。當?shù)案庾龊煤螅案鈳煾挡拍芙o對應的“提貨單”蛋糕,也就是future.setRealData(realdata)。

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

  建立一個字符串,包含count個c字符,為了表現(xiàn)出犯法需要花費一些時間,使用了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;

  }

  }

  現(xiàn)在來看看“提貨單”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被調(diào)用兩次以上。

  }

  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); 執(zhí)行以后,顧客才能拿走蛋糕。

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

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

 

posted @ 2012-09-26 11:55 tbwshc 閱讀(696) | 評論 (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.

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

 

出現(xiàn)原因:

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

解決辦法:

  重啟業(yè)務系統(tǒng),重新獲得Oracle Session。

避免方案:

  不要在系統(tǒng)運行過程中,對Package重新編譯。



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

C語言宏定義技巧(常用宏定義)
   
    寫好C語言,漂亮的宏定義很重要,使用宏定義可以防止出錯,提高可移植性,可讀性,方便性 等等。下面列舉一些成熟軟件中常用得宏定義……
   
    CODE:
   
    1,防止一個頭文件被重復包含
   
    #ifndef COMDEF_H
   
    #define COMDEF_H
   
    //頭文件內(nèi)容
   
    #endif
   
    2,重新定義一些類型,防止由于各種平臺和編譯器的不同tb ,而產(chǎn)生的類型字節(jié)數(shù)差異,方便移植。
   
    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,得到指定地址上的一個字節(jié)或字
   
    #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在結(jié)構(gòu)體(struct)中的偏移量
   
    #define FPOS( type, field ) \
   
    /*lint -e545 */ ( (dword) &(( type *) 0)-> field ) /*lint +e545 */
   
    6,得到一個結(jié)構(gòu)體中field所占用的字節(jié)數(shù)
   
    #define FSIZ( type, field ) sizeof( ((type *) 0)->field )
   
    7,按照LSB格式把兩個字節(jié)轉(zhuǎn)化為一個Word
   
    #define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )
   
    8,按照LSB格式把一個Word轉(zhuǎn)化為兩個字節(jié)
   
    #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,得到一個字的高位和低位字節(jié)
   
    #define WORD_LO(xxx) ((byte) ((word)(xxx) & 255))
   
    #define WORD_HI(xxx) ((byte) ((word)(xxx) 》 8))
   
    11,返回一個比X大的最接近的8的倍數(shù)
   
    #define RND8( x )     ((((x) + 7) / 8 ) * 8 )
   
    12,將一個字母轉(zhuǎn)換為大寫
   
    #define UPCASE( c ) ( ((c) >= 'a' && (c) <= 'z‘) ? ((c) - 0x20) : (c) )
   
    13,判斷字符是不是10進值的數(shù)字
   
    #define DECCHK( c ) ((c) >= '0' && (c) <= '9’)
   
    14,判斷字符是不是16進值的數(shù)字
   
    #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,返回數(shù)組元素的個數(shù)
   
    #define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
   
    17,返回一個無符號數(shù)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空間映射在存儲空間的結(jié)構(gòu),輸入輸出處理
   
    #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,使用一些宏跟蹤調(diào)試
   
    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 _宏指令在有關(guān)# l i n e的部分中已討論,這里討論其余的宏名。
   
    _ D AT E _宏指令含有形式為月/日/年的串,表示源文件被翻譯到代碼時的日期。
   
    源代碼翻譯到目標代碼的時間作為串包含在_ T I M E _中。串形式為時:分:秒。
   
    如果實現(xiàn)是標準的,則宏_ S T D C _含有十進制常量1.如果它含有任何其它數(shù),則實現(xiàn)是
   
    非標準的。
   
    可以定義宏,例如:
   
    當定義了_DEBUG,輸出數(shù)據(jù)信息和所在文件所在行
   
    #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); //產(chǎn)生錯誤
   
    else
   
    解決方法: #difne DO(a,b) do{a+b;\
   
    a++;}while(0)
   
    宏中“#”和“##”的用法
   
    一、一般用法
   
    我們使用#把宏參數(shù)變?yōu)橐粋€字符串,用##把兩個宏參數(shù)貼合在一起。
   
    用法:
   
    #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;
   
    }
   
    二、當宏參數(shù)是另一個宏的時候
   
    需要注意的是凡宏定義里有用'#’或‘##’的地方宏參數(shù)是不會再展開。
   
    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里的參數(shù)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都不會再被展開, 然而解決這個問題的方法很簡單。 加多一層中間轉(zhuǎn)換宏。
   
    加這層宏的用意是把所有宏的參數(shù)在這層里全部展開, 那么在轉(zhuǎn)換宏里的那一個宏(_STR)就能得到正確的宏參數(shù)。
   
    #define A       (2)
   
    #define _STR(s)   #s
   
    #define STR(s)     _STR(s)       // 轉(zhuǎn)換宏
   
    #define _CONS(a,b) int(a##e##b)
   
    #define CONS(a,b)   _CONS(a,b)     // 轉(zhuǎn)換宏
   
    printf(“int max: %s\n”, STR(INT_MAX));       // INT_MAX,int型的最大值,為一個變量 #include<climits>
   
    輸出為: int max: 0x7fffffff
   
    STR(INT_MAX) --> _STR(0x7fffffff) 然后再轉(zhuǎn)換成字符串;
   
    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、填充結(jié)構(gòu)
   
    #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、得到一個數(shù)值類型所對應的字符串緩沖大小
   
    #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 閱讀(226) | 評論 (0)編輯 收藏

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

    二叉堆是非常有特點的數(shù)據(jù)結(jié)構(gòu),可以采用簡單的數(shù)組就能實現(xiàn),當然鏈表的實現(xiàn)也是沒有問題的,畢竟是一個二叉樹問題,當然可以采用鏈表實現(xiàn)。采用數(shù)組實現(xiàn)時,可以找到兩個特別明顯的規(guī)律:

    左兒子:L_Son = Parent * 2;

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

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

    具體的實現(xiàn)如下:

    結(jié)構(gòu)體:

    #ifndef __BINARYHEAP_H_H_

    #define __BINARYHEAP_H_H_

    #include <stdlib.h>

    #include <assert.h>

    #define bool int

    #define true 1

    #define false 0

    /*打算采用數(shù)組的方式實現(xiàn)完全二叉堆*/

    typedef struct _binaryheap

    {

    /*因為需要動態(tài)擴展,

    *采用靜態(tài)數(shù)組不方便*/

    int * parray;

    /*目前存在的結(jié)點*/

    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

    實現(xiàn)的接口函數(shù)如下:

    #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,主要是為了使得數(shù)組從下標1開始計算*/

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

    if(parray == NULL)

    return false;

    (*heap)->parray = parray;

    (*heap)->capacity = capacity;

    (*heap)->currentSize = 0;

    return true;

    }

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

    * 采用上慮法實現(xiàn)數(shù)據(jù)的插入操作

    * 上慮法的實現(xiàn)方式比較簡單,首先創(chuàng)建一個空節(jié)點

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

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

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

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

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

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

    bool insert(BinaryHeap_handle_t heap, int value)

    {

    int index = 0;

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

    return false;

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

    index = ++heap->currentSize;

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

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

    {

    /*將父結(jié)點保存到當前結(jié)點處*/

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

    /*得到父結(jié)點的空穴位置*/

    index /= 2;

    }

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

    heap->parray[index] = value;

    return true;

    }

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

    * 下慮法實現(xiàn)數(shù)據(jù)的重排序操作

    * 實現(xiàn)的方式,將子結(jié)點的兩個兒子進行比較,將小的提升

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

    * 實現(xiàn)的方式主要是利用了二叉堆的特性:

    * 2*pare = L_child

    * 2*pare + 1 = R_child;

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

    static void presort_BinaryHeap(BinaryHeap_handle_t heap,int hole)

    {

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

    int child = hole * 2;

    /*保存當前數(shù)據(jù)操作*/

    int tmp = 0;

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

    tmp = heap->parray[hole];

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

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

    {

    child = hole * 2;

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

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

    *并確定了那個子結(jié)點提升的問題

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

    if((child != heap->currentSize)

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

    child ++;

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

    {

    /*將子結(jié)點提升為父結(jié)點*/

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

    }

    }

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

    heap->parray[hole] = tmp;

    }

    /*實現(xiàn)數(shù)據(jù)的下慮法實現(xiàn)數(shù)據(jù)的刪除操作*/

    int deleteMin(BinaryHeap_handle_t heap)

    {

    int ret = 0;

    int index = 0;

    assert(!isEmpty(heap));

    /*需要返回的值*/

    ret = heap->parray[1];

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

    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;

    }

    測試結(jié)果:

    [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

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

    二叉堆是非常有特點的數(shù)據(jù)結(jié)構(gòu),可以采用簡單的數(shù)組就能實現(xiàn),當然鏈表的實現(xiàn)也是沒有問題的,畢竟是一個二叉樹問題,當然可以采用鏈表實現(xiàn)。采用數(shù)組實現(xiàn)時,可以找到兩個特別明顯的規(guī)律:

    左兒子:L_Son = Parent * 2;

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

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

    具體的實現(xiàn)如下:

    結(jié)構(gòu)體:

    #ifndef __BINARYHEAP_H_H_

    #define __BINARYHEAP_H_H_

    #include <stdlib.h>

    #include <assert.h>

    #define bool int

    #define true 1

    #define false 0

    /*打算采用數(shù)組的方式實現(xiàn)完全二叉堆*/

    typedef struct _binaryheap

    {

    /*因為需要動態(tài)擴展,

    *采用靜態(tài)數(shù)組不方便*/

    int * parray;

    /*目前存在的結(jié)點*/

    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

    實現(xiàn)的接口函數(shù)如下:

    #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,主要是為了使得數(shù)組從下標1開始計算*/

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

    if(parray == NULL)

    return false;

    (*heap)->parray = parray;

    (*heap)->capacity = capacity;

    (*heap)->currentSize = 0;

    return true;

    }

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

    * 采用上慮法實現(xiàn)數(shù)據(jù)的插入操作

    * 上慮法的實現(xiàn)方式比較簡單,首先創(chuàng)建一個空節(jié)點

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

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

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

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

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

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

    bool insert(BinaryHeap_handle_t heap, int value)

    {

    int index = 0;

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

    return false;

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

    index = ++heap->currentSize;

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


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

    {

    /*將父結(jié)點保存到當前結(jié)點處*/

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

    /*得到父結(jié)點的空穴位置*/

    index /= 2;

    }

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

    heap->parray[index] = value;

    return true;

    }

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

    * 下慮法實現(xiàn)數(shù)據(jù)的重排序操作

    * 實現(xiàn)的方式,將子結(jié)點的兩個兒子進行比較tbw,將小的提升

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

    * 實現(xiàn)的方式主要是利用了二叉堆的特性:

    * 2*pare = L_child

    * 2*pare + 1 = R_child;

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

    static void presort_BinaryHeap(BinaryHeap_handle_t heap,int hole)

    {

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

    int child = hole * 2;

    /*保存當前數(shù)據(jù)操作*/

    int tmp = 0;

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

    tmp = heap->parray[hole];

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

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

    {

    child = hole * 2;

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

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

    *并確定了那個子結(jié)點提升的問題

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

    if((child != heap->currentSize)

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

    child ++;

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

    {

    /*將子結(jié)點提升為父結(jié)點*/

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

    }

    }

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

    heap->parray[hole] = tmp;

    }

    /*實現(xiàn)數(shù)據(jù)的下慮法實現(xiàn)數(shù)據(jù)的刪除操作*/

    int deleteMin(BinaryHeap_handle_t heap)

    {

    int ret = 0;

    int index = 0;

    assert(!isEmpty(heap));

    /*需要返回的值*/

    ret = heap->parray[1];

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

    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;

    }

    測試結(jié)果:

    [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

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

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

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

    1、malloc函數(shù):向系統(tǒng)申請分配指定size個字節(jié)的內(nèi)存空間,分配成功后得到的是一個內(nèi)存塊,即連續(xù)的空間
   
    2、malloc分配不一定成功,所以最好驗證一下:
   
    char *mallo;
   
    if ((mallo=(char *)malloc(36*sizeof(char)))==NULL)
   
    printf(“error in mallo!\n”);
   
    3、傳指針參數(shù)的原理在譚浩強書上已經(jīng)講過,這里只是做傳指針后實際的賦值方式探討
   
    傳遞過來的參數(shù):char *mallo
   
    3.1:mallo=“bag”;/*直接=不成功,調(diào)用后mallo只能在這個函數(shù)中打印出,調(diào)用這個函數(shù)的函數(shù)卻不能在調(diào)用后得到相應的賦值結(jié)果*/
   
    3.2:for(;i<36;i++)
   
    {
   
    *(mallo++)='a'+rand()%26;
   
    //mallo[i]='a'+rand()%26;/*這句和上句的效果相同*/
   
    }/*for循環(huán)可以成功:依次賦值隨進字母*/
   
    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循環(huán)類似*/
   
    一開始在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循環(huán)可以成功*/
   
    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);/*打印申請空間內(nèi)容,在windows下為亂碼,而Linux下不顯示*/
   
    /*以下打印數(shù)據(jù)在Linux和windows下數(shù)據(jù)不同,在賦值成功前windows已經(jīng)會檢測上面分配的空間大小,Linux則不會:strlen(mallo)可以看出*/
   
    printf(“sizeof(mallo):%d--分割線--sizeof(*mallo):%d--分割線--strlen(mallo):%d\n”,sizeof(mallo),sizeof(*mallo),strlen(mallo));
   
    memtest(mallo);/*調(diào)用賦值函數(shù)*/
   
    printf(“===============================================================”);
   
    printf(“\nmallo_aftersetparam:%s\n”,mallo);/*tbw調(diào)用后輸出*/
   
    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 閱讀(1611) | 評論 (1)編輯 收藏

    最近的幾次文章的評論中不少讀者提到文章的更新速度的更新量的問題,淺墨會逐漸重視起來,盡量在保證質(zhì)量的基礎上,每周都拿出夠分量的內(nèi)容。本周的文章算是近幾次更新量的一個彌補,這篇文章的字數(shù)達到了近一萬字。
   
    一、DirectX11的現(xiàn)有組件
   
    DirectX的API被分為頗多組件,每一組件都展現(xiàn)了系統(tǒng)不同方面的功能。其中的每一套API都能被獨立的使用,因此我們可以按照所需有選擇地自由添加我們游戲中需要的功能。在最新版本的DirectX中,不少組件迎來了更新,如Direct3D.其他的組件保持著現(xiàn)有的功能,當然,也有一些被棄用的組件面臨著被移除的命運。值得一提的是,DirectX中的各個內(nèi)部組件可以獨立進行新功能的升級。
   
    下面進行分別介紹:
   
    1.Direct2D
   
    Direct2D用于Win32應用程序中2D圖形的繪制。Direct2D善于高性能矢量圖形的渲染。
   
    2. DirectWrite
   
    DirectWrite用于Direct2D應用程序中的字體和文字渲染。
   
    3 . DXGI
   
    DXGI(DirectX Graphics Infrastructure)即DirectX圖形基礎,用于
   
    Direct3D交換鏈(swap chains)和枚舉設備適配器(enumeration of deviceadapters)的創(chuàng)建。
   
    4 .Direct3D
   
    Direct3D用于DirectX中所有的與3D圖形相關(guān)的操作。Direct3D可謂DirectX中的大牌級API,受到了微軟最多的關(guān)懷與多次針對性的更新,它也最多被世人所熟知。這個專欄后續(xù)內(nèi)容的大部分的篇幅將集中于講解Direct3D上。
   
    5. XAudio2
   
    XAudio2 是一款底層的音頻處理API,以前為XDK(Xbox Development Kit)的一部分,目前,隸屬于DIRECTXSDK.XAudio2替換了DirectSound.初始版本的XAudio用于的第一代Xbox游戲機。
   
    6. XACT3
   
    XACT3是一款建立在XAudio2之上的更高級別的音頻處理API.XACT3允許開發(fā)者在他們的應用中使用跨平臺音頻創(chuàng)作工具。若開發(fā)者希望從底層控制音頻系統(tǒng)或者希望創(chuàng)建自己的類型于XACT3的更高級別的音頻系統(tǒng),可以運用XAdio2來完成各項功能。tbwXACT3,我們已經(jīng)在附錄B中討論過,作為“DIRECTX中的聲音”從配套網(wǎng)站,是一款非常容易上手的游戲音頻制作工具。
   
    7. XInput
   
    XInput是XDK和DirectX SDK的負責輸入功能的 API,用于處理Xbox 360控制器輸入。基本上任何可以在Xbox 360上可以使用的命令,都可以在PC上使用,而XInput就是幫助我們在這些設備上進行輸入相關(guān)操作的API.這些設備不僅包含Xbox手柄,也包含了其他很多設備。需要說明的是,XInput 替換了之前版本的DirectInput.
   
    注:XAudio是只能用于Xbox游戲機的音效API. XAudio2,其繼任者,可用于Xbox游戲機和基于Windows的PC.
   
    8 . XNAMath
   
    新出現(xiàn)的XNA Math 不是一款API,而是是一個數(shù)學庫,進行電子游戲中常見運算的優(yōu)化工作。XNA Math采用了SIMD (Single Instruction Multiple Data單指令多數(shù)據(jù))來執(zhí)行多個操作的單指令調(diào)用。XNA Math庫適用于基于Windows的PC以及Xbox 360.相關(guān)內(nèi)容我們將在后續(xù)內(nèi)容繼續(xù)講解。
   
    注:XNA GameStudio為一款基于DirectX的游戲開發(fā)工具,可供我們使用C#和。NET編程語言來為Xbox360與Windows PC平臺編寫游戲。而XNA Math是一款DirectX SDK中數(shù)學庫的名字,可獨立于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的更多信息,可以查閱相關(guān)資料。
   
    10. DirectSetup
   
    當我們完成游戲開發(fā)的時候,我們理所當然地需要把完成品呈現(xiàn)給用戶。DirectSetup給我們提供了在用戶的電腦上安裝最新版本的DirectX的功能。DirectSetup也具有檢查已經(jīng)安裝了的DirectX版本號的功能。
   
    11.Windows Games Explorer
   
    WindowsGames Explorer(游戲資源管理器)是Windows Vista與Windows 7中的新特性,可供游戲開發(fā)者在他們的操作系統(tǒng)上展示(測試)他們的游戲。比如游戲的顯示,標題,評級,描述,特定區(qū)域的風格框,評分內(nèi)容(如M為成人,T為青少年等),游戲數(shù)據(jù)統(tǒng)計和通知,家長控制等。DirectX SDK中提供了大量如何使用自己的游戲的游戲資源管理器的教程,這對于發(fā)行一款游戲是非常有用的。下面的圖1是淺墨電腦上的Windows7游戲資源管理器的界面截圖

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

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

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

PB9開發(fā)的程序,用PB11.5打開過后,再用PB9就打不開了
PB9開發(fā)的程序,用PB11.5打開過后,再用PB9就打不開了,添加目標時提示 could not add target because of a bad application library in "g:\11\tv_prg.pbt",怎辦才能用PB9重新打開呢?

------解決方案--------------------------------------------------------
這個恐怕不行了。
那個項目已經(jīng)被遷移成了 PB11.5 的版本了。

像這樣的操作應該事件tb做備份的。
------解決方案--------------------------------------------------------
高的能兼容低的,低的不能兼容高的
------解決方案--------------------------------------------------------
如果你沒有備份的話 那你悲劇了
------解決方案--------------------------------------------------------
找一以前的備份,用備份吧

如果沒有備份,你真的悲劇了
------解決方案--------------------------------------------------------
試試 Regenerate
posted @ 2012-09-08 13:34 tbwshc| 編輯 收藏

僅列出標題
共10頁: 1 2 3 4 5 6 7 8 9 Last 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            麻豆精品视频| 中国女人久久久| 亚洲精品视频二区| 亚洲国产另类久久久精品极度| 欧美在线观看一二区| 久久久综合视频| 国产综合在线看| 久久久久久香蕉网| 欧美国产第一页| 亚洲一区二区三| 国产日韩精品一区| 久久精品国产一区二区电影| 亚洲第一色在线| 亚洲精品一区二区三区不| 欧美高清在线观看| 亚洲国产日韩欧美在线99 | 国产精品久久久久影院亚瑟| 一区二区三区视频在线播放| 久久久久久久综合| 亚洲人线精品午夜| 国产欧美日韩综合一区在线观看| 久久精品盗摄| 亚洲一区二区少妇| 亚洲国产精品激情在线观看| 亚洲综合国产精品| 亚洲免费激情| 一区二区三区自拍| 国产精品丝袜xxxxxxx| 欧美寡妇偷汉性猛交| 久久精品国产精品亚洲| 一区二区不卡在线视频 午夜欧美不卡'| 久久精品国产综合| 午夜精品成人在线| 亚洲欧美在线x视频| 妖精视频成人观看www| 亚洲精品国精品久久99热一| 激情文学一区| 国产一区三区三区| 国产精品无人区| 欧美日韩国产亚洲一区| 欧美精品三区| 欧美日本国产在线| 欧美日韩国产小视频在线观看| 免费久久精品视频| 欧美国产欧美亚洲国产日韩mv天天看完整 | 国产精品无人区| 国产精品福利影院| 国产伦精品一区二区三区在线观看| 欧美国产成人在线| 欧美四级在线观看| 国产精品日韩精品| 国模私拍一区二区三区| 亚洲高清久久网| 一本色道久久88精品综合| 亚洲天堂网站在线观看视频| 午夜视频久久久久久| 久久久福利视频| 欧美顶级大胆免费视频| 一区二区欧美日韩| 久久精品色图| 欧美日韩美女在线| 免费成人小视频| 日韩午夜中文字幕| 小黄鸭精品aⅴ导航网站入口 | 欧美日韩国产色视频| 国产麻豆午夜三级精品| 在线观看国产精品网站| 亚洲少妇自拍| 女仆av观看一区| 亚洲欧美精品伊人久久| 免费视频久久| 国产偷国产偷亚洲高清97cao| 亚洲日本aⅴ片在线观看香蕉| 亚洲女与黑人做爰| 亚洲国产精品一区二区www在线| 亚洲欧美日韩另类| 欧美日韩不卡一区| 在线观看免费视频综合| 久久黄金**| 亚洲欧美日韩综合| 国产毛片一区二区| 羞羞漫画18久久大片| 亚洲国产综合91精品麻豆| 欧美在线视频免费播放| 国产一区91精品张津瑜| 国产精品视频xxx| 亚洲欧美日韩一区| 欧美一级成年大片在线观看| 夜夜嗨av一区二区三区四季av| 久热精品视频在线观看一区| 亚洲国产精品久久久| 亚洲国产你懂的| 欧美日韩一级黄| 亚洲一区一卡| 午夜精品久久久久久久| 国产亚洲日本欧美韩国| 久热精品视频在线| 欧美激情亚洲自拍| 亚洲午夜激情免费视频| 欧美一级视频精品观看| 亚洲国产你懂的| 一区二区三区黄色| 国产一区视频在线看| 欧美激情欧美激情在线五月| 欧美日韩国产不卡| 久久人人九九| 久久伊人一区二区| 免费在线国产精品| 欧美一区二视频| 免费不卡在线观看| 久久福利电影| 欧美全黄视频| 麻豆国产精品777777在线 | 国产精品日韩欧美一区| 国产精品三区www17con| 激情一区二区三区| 亚洲精华国产欧美| 亚洲美女精品成人在线视频| 欧美激情久久久久| 亚洲精品美女在线| 亚洲在线视频一区| 国产一区二区三区精品欧美日韩一区二区三区 | 亚洲视频图片小说| 免费久久精品视频| 欧美va天堂在线| 在线观看日韩专区| 国产免费成人在线视频| 日韩视频免费在线观看| 99天天综合性| 欧美大片免费| 日韩午夜电影av| 亚洲已满18点击进入久久 | 亚洲精品久久久久久久久久久久久 | 国产日韩综合| 亚洲欧美日韩综合| 久久视频国产精品免费视频在线| 国产揄拍国内精品对白| 亚洲精品国产无天堂网2021| 亚洲一卡二卡三卡四卡五卡| 国产亚洲精品福利| 欧美黄色免费网站| 久久国产精品久久久久久久久久| 久久亚洲精品中文字幕冲田杏梨| 黄色资源网久久资源365| 久久久久国色av免费观看性色| 久久久久九九九| 狠狠色丁香久久婷婷综合丁香 | 久久野战av| 亚洲黑丝在线| 国产伪娘ts一区| 开元免费观看欧美电视剧网站| 另类人畜视频在线| 亚洲精品中文字幕女同| 国产精品igao视频网网址不卡日韩| 亚洲社区在线观看| 亚洲人成网站影音先锋播放| 亚洲男人av电影| 在线看欧美日韩| 欧美日一区二区三区在线观看国产免 | 午夜精品久久久久| 国语对白精品一区二区| 免费看亚洲片| 亚洲一级在线| 亚洲综合首页| 中文av字幕一区| 亚洲成色最大综合在线| 欧美日韩国产影片| 亚洲成色精品| 国产手机视频一区二区| 国产精品久久久久久久久搜平片 | 国内精品视频在线观看| 国产在线播放一区二区三区| 国产精品美女xx| 欧美日韩三级视频| 亚洲成人在线视频播放| 久久亚洲午夜电影| 新67194成人永久网站| 亚洲乱亚洲高清| 欧美在线999| 久久久久久网址| 久久精品二区三区| 久久精品欧美| 欧美精品一区二区三区在线看午夜| 久久久久国产精品一区三寸| 久久久久中文| 日韩一级精品视频在线观看| 亚洲午夜免费视频| 亚洲午夜精品福利| 欧美一区二区精品久久911| 亚洲精品一区二区在线| 日韩午夜精品| 亚洲自拍另类| 久久亚洲春色中文字幕| 欧美日韩国产片| 国产欧美精品一区二区三区介绍 | 女人天堂亚洲aⅴ在线观看| 欧美在线观看一区| 亚洲精品美女久久7777777| 亚洲国产二区| 午夜精品久久久久久久久|