久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

C語言可變參數(shù)函數(shù)的使用及相關(guān)函數(shù)介紹

 CodeNutter 2016-06-16

            By qianghaohao(Xqiang)

       在C語言中當(dāng)一個(gè)函數(shù)參數(shù)無法列舉出來,或者參數(shù)個(gè)數(shù)
 不確定,這時(shí)我們將函數(shù)聲明為可變參數(shù)的形式,根據(jù)需
 要傳適當(dāng)個(gè)數(shù)的參數(shù).舉例如下:
int fun(char *fmt, ...);
... 表示此函數(shù)fmt后面可以傳任意數(shù)目的參數(shù).
我們所熟悉的printf函數(shù)便是利用了這一特性,printf
函數(shù)聲明如下:
int printf(const char *, ...);
以下介紹如何利用此類函數(shù)打印函數(shù)的所有參數(shù),總共
介紹了三種方法:

以此函數(shù)聲明為例:int fun(char *fmt, ...);
在介紹之前得先搞清楚以下相關(guān)的函數(shù)(在stdarg.h中聲明):
1.va_list
  定義一個(gè)va_list變量,后面的操作都和此變量有關(guān).
  ex: va_list ap;
2.va_start
  初始化va_list變量,讓ap指向可變參數(shù)表的第一個(gè)參數(shù),即
  ...參數(shù)中的第一個(gè)參數(shù).此函數(shù)第一個(gè)參數(shù)為ap,第二個(gè)參
  數(shù)為第一個(gè)可變參數(shù)的前一個(gè)參數(shù),即...前的那一個(gè)參數(shù).
  ex: va_start(ap, fmt);
3.va_arg
  獲取可變參數(shù),此函數(shù)第一個(gè)參數(shù)為ap,第二個(gè)參數(shù)為要獲取
  的類型.返回指定類型的的變量,然后讓ap指向可變參數(shù)表的
  下一個(gè)參數(shù).
  ex: va_arg(ap, char *);
4.va_end
  使用完后釋放ap變量
  ex: va_end(ap);
5. int vsprintf(char *string, char *format, va_list param);
   按照format格式化輸出參數(shù)到string,format類似于printf的
   格式化串,param是va_list變量.
   ex: ---摘自百度百科
    #include <stdarg.h>
    #include<stdio.h>
    char buffer[80];
    int vspf(char *fmt, ...)
    {
        va_list argptr;
        int cnt;
        va_start(argptr, fmt);
        cnt = vsprintf(buffer, fmt, argptr);
        va_end(argptr);
        return(cnt);
    }
    int main(void)
    {
        int inumber = 30;
        float fnumber = 90.0;
        char string[4] = "abc";
        vspf("%d %f %s", inumber, fnumber, string);
        printf("%s\n", buffer);
        return 0;
    }

 好了,現(xiàn)在有了前面的知識,現(xiàn)在正式開始介紹如何打印出可變參數(shù)函數(shù)的所有參數(shù):
 一.第一種方法(比較笨的一種方法,我不推薦這么做,除非有特殊需求吧):
      通過va_arg函數(shù)循環(huán)取出參數(shù)列表中的參數(shù)并打印,這種方法要求在
      最后傳一個(gè)結(jié)束標(biāo)志,比如"",代表空串.
      示例代碼如下:
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <stdarg.h>  
  4.   
  5. void Manue (char* msg, ...) {  
  6.     va_list argp;  
  7.     char* para;  
  8.     printf("%s", msg);  
  9.     va_start(argp,msg);  
  10.   
  11.     while(1) {  
  12.         para = va_arg(argp, char *);  
  13.         if(strcmp(para, "")==0)  
  14.             break;  
  15.         printf("%s ", para);  
  16.     }  
  17.     va_end(argp);  
  18. }  
  19.   
  20. int main() {  
  21.   Manue("usage:", "file1", " file2", "");  
  22.   return 0;  
  23. }  
二.第二種方法(有局限性,不過可以打印各種類型的參數(shù)):
    通過vsprintf函數(shù)格式化輸出各個(gè)參數(shù)到緩沖字符串.
   示例代碼如下:
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <stdarg.h>  
  4. void PrintFError ( const char * format, ... )  
  5. {  
  6.   char buffer[256];  
  7.   va_list args;  
  8.   va_start (args, format);  
  9.   vsprintf (buffer,format, args);  
  10.   printf("%s\n", buffer);  
  11.   va_end (args);  
  12. }  
  13.   
  14. int main ()  
  15. {  
  16.   PrintFError ("%s%s%s", "usage:", "file1", " file2");  
  17.   return 0;  
  18. }  
三.第三種方法(這種方法能打印同種類型的任意多個(gè)參數(shù)):
    以下示例代碼摘自W. Richard Stevens的<<TCP/IP詳解>>中使用
的sock程序的代碼.巧妙地利用了這一點(diǎn)打印錯誤提示信息.
    代碼如下(為了演示,代碼略有修改):
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <stdarg.h>  
  4. static void  
  5. err_doit(int errnoflag, const char *fmt, va_list ap)  
  6. {  
  7.     int     errno_save;  
  8.     char    buf[4096];  
  9.   
  10.     errno_save = errno;     /* value caller might want printed */  
  11.     vsprintf(buf, fmt, ap);  
  12.   
  13.     strcat(buf, "\n");  
  14.     fflush(stdout);     /* in case stdout and stderr are the same */  
  15.     fputs(buf, stderr);  
  16.     fflush(stderr);     /* SunOS 4.1.* doesn't grok NULL argument */  
  17.     return;  
  18. }  
  19.   
  20. void  
  21. /* $f err_msg $ */  
  22. err_msg(const char *fmt, ...)  
  23. {  
  24.     va_list     ap;  
  25.   
  26.     va_start(ap, fmt);  
  27.     err_doit(0, fmt, ap);  
  28.     va_end(ap);  
  29.     return;  
  30. }  
  31.   
  32. int main() {  
  33.     err_msg(  
  34. "usage: sock [ options ] <host> <port>              (for client; default)\n"  
  35. "       sock [ options ] -s [ <IPaddr> ] <port>     (for server)\n"  
  36. "       sock [ options ] -i <host> <port>           (for \"source\" client)\n"  
  37. "       sock [ options ] -i -s [ <IPaddr> ] <port>  (for \"sink\" server)\n"  
  38. "options: -b n  bind n as client's local port number\n"  
  39. "         -c    convert newline to CR/LF & vice versa\n"  
  40. "         -f a.b.c.d.p  foreign IP address = a.b.c.d, foreign port# = p\n"  
  41. "         -g a.b.c.d  loose source route\n"  
  42. "         -h    issue TCP half close on standard input EOF\n"  
  43. "         -i    \"source\" data to socket, \"sink\" data from socket (w/-s)\n"  
  44. #ifdef  IP_ADD_MEMBERSHIP  
  45. "         -j a.b.c.d  join multicast group\n"  
  46. #endif  
  47. "         -k    write or writev in chunks\n"  
  48. "         -l a.b.c.d.p  client's local IP address = a.b.c.d, local port# = p\n"  
  49. "         -n n  #buffers to write for \"source\" client (default 1024)\n"  
  50. "         -o    do NOT connect UDP client\n"  
  51. "         -p n  #ms to pause before each read or write (source/sink)\n"  
  52. "         -q n  size of listen queue for TCP server (default 5)\n"  
  53. "         -r n  #bytes per read() for \"sink\" server (default 1024)\n"  
  54. "         -s    operate as server instead of client\n"  
  55. #ifdef  IP_MULTICAST_TTL  
  56. "         -t n  set multicast ttl\n"  
  57. #endif  
  58. "         -u    use UDP instead of TCP\n"  
  59. "         -v    verbose\n"  
  60. "         -w n  #bytes per write() for \"source\" client (default 1024)\n"  
  61. "         -x n  #ms for SO_RCVTIMEO (receive timeout)\n"  
  62. "         -y n  #ms for SO_SNDTIMEO (send timeout)\n"  
  63. "         -A    SO_REUSEADDR option\n"  
  64. "         -B    SO_BROADCAST option\n"  
  65. "         -C    set terminal to cbreak mode\n"  
  66. "         -D    SO_DEBUG option\n"  
  67. "         -E    IP_RECVDSTADDR option\n"  
  68. "         -F    fork after connection accepted (TCP concurrent server)\n"  
  69. "         -G a.b.c.d  strict source route\n"  
  70. #ifdef  IP_TOS  
  71. "         -H n  IP_TOS option (16=min del, 8=max thru, 4=max rel, 2=min$)\n"  
  72. #endif  
  73. "         -I    SIGIO signal\n"  
  74. #ifdef  IP_TTL  
  75. "         -J n  IP_TTL option\n"  
  76. #endif  
  77. "         -K    SO_KEEPALIVE option\n"  
  78. "         -L n  SO_LINGER option, n = linger time\n"  
  79. "         -N    TCP_NODELAY option\n"  
  80. "         -O n  #ms to pause after listen, but before first accept\n"  
  81. "         -P n  #ms to pause before first read or write (source/sink)\n"  
  82. "         -Q n  #ms to pause after receiving FIN, but before close\n"  
  83. "         -R n  SO_RCVBUF option\n"  
  84. "         -S n  SO_SNDBUF option\n"  
  85. #ifdef  SO_REUSEPORT  
  86. "         -T    SO_REUSEPORT option\n"  
  87. #endif  
  88. "         -U n  enter urgent mode before write number n (source only)\n"  
  89. "         -V    use writev() instead of write(); enables -k too\n"  
  90. "         -W    ignore write errors for sink client\n"  
  91. "         -X n  TCP_MAXSEG option (set MSS)\n"  
  92. "         -Y    SO_DONTROUTE option\n"  
  93. "         -Z    MSG_PEEK\n"  
  94. #ifdef  IP_ONESBCAST  
  95. "         -2    IP_ONESBCAST option (255.255.255.255 for broadcast\n"  
  96. #endif  
  97. );  
  98.   return 0;  
  99. }  
 總結(jié):
    掌握了以上函數(shù)的用法后今后在寫程序中處理提示信息及幫助菜單的時(shí)候就可以直接運(yùn)用,,而不需要
手動調(diào)用一堆printf函數(shù)打印.當(dāng)然還有更多的好處,比如第三中方法中的條件編譯導(dǎo)致參數(shù)的不確定性,這
樣就可以直接用可變參數(shù)函數(shù)了.

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多