变长参数表:<stdarg.h>介绍及在iOS中应用


头文件<stdarg.h>提供了遍历未知数目和类型的喊出参数表的功能。

假定函数f带有可变数目的实际参数,lastar=g是他的最后一个命名的形式参数,那么,在函数f内声明一个类型为va_list的变量ap,它将以此指向每个实际参数:

va_list  ap;

在访问任何未命名的参数前,必须用va_start宏宏初始化ap一次:

va_start(va_list ap, lastarg);

此后,每次执行宏va_arg都将产生一个与下一个未命名的参数具有相同类型和数值的值,它同时还修改ap,以使得下一次执行va_arg时返回下一个参数:

type va_arg(va_list ap,type);

在所有参数处理完毕后,且在退出函数f之前,必须调用宏va_end以此,如下所示

void  va_end(va_list ap);


其实va_list类型用于声明一个变量,该变量将以此引用各参数,

va_start用于将ap初始化为指向第一个无名参数的指针,在使用ap之前,该宏必须被调用一次。

参数表必须至少包含一个有名参数,va_start将最后一个有名参数作为起点

每次调用va_arg,该函数都将返回一个参数,并将ap指向下一个参数。va_arg使用一个类型名来决定返回的对象类型,指针移动的步长,最后,必须在函数返回之前调用va_end,以完成一些必要的清理工作。

现在我们实现一个简化的printf。


void minprintf(char *fmt,...)

{

 va_list ap;//points to each unnamed arg in turn

char *p,*sval;

int ival;

double dval;

va_start(ap,fmt);

for(p=fmt;*p;p++){

  if(*p!='%'){

   putchar(*p);

   continue;

}

switch (*++p){

case 'd':

ival=va_arg(ap,int);

printf("%d",ival);

break;

case 'f':

dval=va_arg(ap,int);

printf("%f",dval);

case 's':

for(sval=va_arg(ap,char*);*sval;sval++)

putchar(*sval);

break;

default:

putchar(*p);

break;

}

}

var_end(ap);


下面看下在OC中的应用

先写个show方法

void show(id formatstring,...)

{

   va_list arglist;

   if (!formatstring) {

       return;

    }

   va_start(arglist, formatstring);

   id outString=[[NSStringalloc]initWithFormat:formatstringarguments:arglist];

   va_end(arglist);

    

    UIAlertView *alert=[[UIAlertViewalloc]initWithTitle:@"test"message:outString delegate:nilcancelButtonTitle:@"OK"otherButtonTitles:@"Cancel",nil];

    [alertshow];



}

在viewdidLoad中

    show(@"Test on va_list,va_start,va_end");


接着深入

 textView=[[UITextViewalloc]initWithFrame:self.view.frame];

    textView.text=@"";

    textView.editable=NO;

    [self.viewaddSubview:textView];

    self.navigationItem.rightBarButtonItem=[[UIBarButtonItemalloc]initWithTitle:@"Test"style:UIBarButtonItemStylePlaintarget:selfaction:@selector(runTests)];


-(void)runTests

{

    [[[NSOperationQueuealloc]init]addOperationWithBlock:^{

      

        [selflog:@"\n\nReachability Tests"];

        [selflog:@"hostName:%@",[selfhostname]];

        [selflog:@"wifiIP:%@",[selfgetWifiIPAddress]];

    }];

   //或者

//    dispatch_async(dispatch_get_global_queue(0, 0), ^{

//    

//        [self log:@"\n\nReachability Tests"];

//        [self log:@"hostName:%@",[self hostname]];

//        [self log:@"wifiIP:%@",[self getWifiIPAddress]];

//    });



}


-(void)log:(id)formatstring,...

{

   va_list arglist;

   if (!formatstring) {

       return;

    }

   va_start(arglist, formatstring);

   NSString *outString=[[NSStringalloc]initWithFormat:formatstringarguments:arglist];

   NSLog(@"--%@--",outString);

   va_end(arglist);

    dispatch_async(dispatch_get_main_queue(), ^{

       NSString *newString=[NSStringstringWithFormat:@"%@\n%@:%@",textView.text,[NSDatedate],outString];

       textView.text=newString;

//        [textView scrollRangeToVisible:NSMakeRange(newString.length, 1)];

    

    });

   //或者

//    [[NSOperationQueue mainQueue]addOperationWithBlock:^{

//    

//        NSString *newString=[NSString stringWithFormat:@"%@\n%@:%@",textView.text,[NSDate date],outString];

//        textView.text=newString;

//    

//    }];


}

-(NSString *)hostname

{

   char baseHostName[256];

   int  success=gethostname(baseHostName,255);

   if (success!=0) {

       return nil;

    }

    baseHostName[255]='\0';

#if TARGET_IPHONE_SIMULATOR

   return [NSStringstringWithFormat:@"%s",baseHostName];

#else

   return [NSString stringWithFormat:@"%s.local",baseHostName];

#endif


}

-(NSString*)getWifiIPAddress

{

   BOOL success;

   struct ifaddrs*addr=NULL;

   const  structifaddrs *cursor=NULL;

    success=getifaddrs(&addr)==0;

   if (success) {

         //Loop through linked list of interfaces

        cursor=addr;

       while (cursor!=NULL) {

            

           if (cursor->ifa_addr->sa_family==AF_INET&&(cursor->ifa_flags&IFF_LOOPBACK)==0) {

               NSString *name=[NSStringstringWithUTF8String:cursor->ifa_name];

                

               if ([name hasPrefix:@"en0"]||[namehasPrefix:@"bridge0"])

                   return [NSStringstringWithUTF8String:inet_ntoa(((structsockaddr_in *)cursor->ifa_addr)->sin_addr)];

            }

                cursor=cursor->ifa_next;

        }

       freeifaddrs(addr);

     

      

    }

    return nil;

}


效图如下




                           

参考书籍 The C Programming Language

        iPhone开发秘籍


关于获取hostName和IP address可以去这里获取   https://github.com/ytdxxt10/shareTools
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值