今天在微博上有一小伙伴说去京东面试了一下下,答得不如意,希望笔者能提供更详细的参考答案。出于笔者未挑战过京东的笔试题,自然也想看看究竟有多难。那么,本篇文章就有笔者针对题目给出笔者的参考答案,不具有答案代表性,只具备一定的参考价值。
int a[5] = {1, 2, 3, 4, 5}; int *ptr = (int *)(&a + 1); printf("%d, %d", *(a + 1), *(ptr + 1));
参考答案:2, 随机值
这种类型题好像挺常见的。考的就是C语言上的指针的理解和数组的理解。
分析:
a代表有5个元素的数组的首地址,a[5]的元素分别是1,2,3,4,5。接下来,a + 1表示数据首地址加1,那么就是a[1],也就是对应于值为2.但是,这里是&a + 1,因为a代表的是整个数组,它的空间大小为5 * sizeof(int),因此&a + 1就是a+5。a是个常量指针,指向当前数组的首地址,指针+1就是移动sizeof(int)个字节。
因此,ptr是指向int *类型的指针,而ptr指向的就是a + 5,那么ptr + 1也相当于a + 6,所以最后的*(ptr + 1)就是一个随机值了。而*(ptr – 1)就相当于a + 4,对应的值就是5。
int array[5] = {1, 2, 3, 4, 5}; int *p = &array[0]; int max = Max(*p++, 1); printf("%d %d", max, *p);
#define Max(X, Y) ((X) > (Y) ? (X) : (Y))
当看到宏时,就会想到宏定义所带来的副作用。对于++、–,在宏当中使用是最容易产生副作用的,因此要慎用。
分析:
p指针指向了数组array的首地址,也就是第一个元素对应的地址,其值为1.
宏定义时一定要注意每个地方要加上圆括号
*p++相当于*p, p++,所以Max(*p++, 1)相当于:
(*p++) > (1) ? (*p++) : (1) => (1) > (1) ? (*p++) : (1) => 第一个*p++的结果是,p所指向的值变成了2,但是1 > 1为値,所以最终max的值就是1。而后面的(*p++)也就不会执行,因此p所指向的地址对应的值就是2,而不是3.
扩展:如果上面的*p++改成*(++p)如何?
分析:
(*++p) > (1) ? (*++p) : (1) => (2) > (1) ? (*++p) : (1) => max = *++p; => *p = 3,max = 3;
object;和name=@
object有什么不同
这是老生常谈的话题了,实质上就是问setter方法赋值与成员变量赋值有什么不同。通过点语法self.name实质上就是[self setName:@ object
];。而name这里是成员变量,直接赋值。
一般来说,在对象的方法里成员变量和方法都是可以访问的,我们通常会重写Setter方法来执行某些额外的工作。比如说,外部传一个模型过来,那么我会直接重写Setter方法,当模型传过来时,也就是意味着数据发生了变化,那么视图也需要更新显示,则在赋值新模型的同时也去刷新UI。这样也不用再额外提供其他方法了。
- (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelectorwithObject:(id)object; - (id)performSelector:(SEL)aSelectorwithObject:(id)object1withObject:(id)object2;
因为系统提供的performSelector的api中,并没有提供三个参数。因此,我们只能传数组或者字典,但是数组或者字典只有存入对象类型,而结构体并不是对象类型,那么怎么办呢?
没有办法,我们只能通过对象放入结构作为属性来传过去了:
typedef struct HYBStruct { int a; int b; } *my_struct; @interfaceHYBObject: NSObject @property (nonatomic, assign) my_structarg3; @property (nonatomic, copy) NSString *arg1; @property (nonatomic, copy) NSString *arg2; @end @implementation HYBObject // 在堆上分配的内存,我们要手动释放掉 - (void)dealloc { free(self.arg3); } @end
测试:
my_structstr = (my_struct)(malloc(sizeof(my_struct))); str->a = 1; str->b = 2; HYBObject *obj = [[HYBObject alloc]init]; obj.arg1 = @"arg1"; obj.arg2 = @"arg2"; obj.arg3 = str; [selfperformSelector:@selector(call:)withObject:obj]; // 在回调时得到正确的数据的 - (void)call:(HYBObject *)obj { NSLog(@"%d %d", obj.arg3->a, obj.arg3->b); }
这是否刷新取决于timer加入到Run Loop中的Mode是什么。Mode主要是用来指定事件在运行循环中的优先级的,分为:
苹果公开提供的Mode有两个:
如果我们把一个NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环中的时候, ScrollView滚动过程中会因为mode的切换,而导致NSTimer将不再被调度。当我们滚动的时候,也希望不调度,那就应该使用默认模式。但是,如果希望在滚动时,定时器也要回调,那就应该使用common mode。
对于这道题,如果要cell滚动过程中定时器正常回调,UI正常刷新,那么要将timer放入到CommonModes下,因为是NSDefaultRunLoopMode,只有在空闲状态下才会回调。
dispatch_queue_tqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_tgroup = dispatch_group_create(); dispatch_group_async(group, queue, ^{ /*任务a */ }); dispatch_group_async(group, queue, ^{ /*任务b */ }); dispatch_group_async(group, queue, ^{ /*任务c */ }); dispatch_group_async(group, queue, ^{ /*任务d */ }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 在a、b、c、d异步执行完成后,会回调这里 });
当然,我们还可以使用非常老套的方法来处理,通过四个变量来标识a、b、c、d四个任务是否完成,然后在runloop中让其等待,当完成时才退出run loop。但是这样做会让后面的代码得不到执行,直到Run loop执行完毕。
说到block的好处,最直接的就是代码紧凑,传值、回调都很方便,省去了写代理的很多代码。
对于这里根本没有必要使用block来刷新UILabel显示,因为都是直接赋值。当然,笔者觉得这是在考验应聘者如何将NSTimer写成一个通用用的Block版本。
代码放到了这里:NSTimer封装成Block版
使用起来像这样:
NSTimer *timer = [NSTimerscheduledTimerWithTimeInterval:1.0 repeats:YES callback:^() { weakSelf.secondsLabel.text = ... } [[NSRunLoop currentRunLoop]addTimer:timerforMode:NSRunLoopCommonModes];
这个问题有很多种方式,而且不同的使用场景也不一样的。比如说:
这是优化tableview的相关专题,如果只是处理图片加载问题,那可以通过异步读取图片然后刷新UI。当然,我们也可以在取数据时,在模型中提前准备好需要显示的图片资源,这样在cell只就不需要操作图片读取,而是直接显示。
如果想要更深入地优化,学习以下知识点:
如果只是判断整个表达式是否有错误,然后去掉里面的圆括号,那么一个循环就可以了。不过我们只需要加两个变量分别来记录左圆括号和右圆括号的个数。这里假设逗号总是正确的情况下,伪代码如下:
left = 0; rigt = 0; for i = 0; i < str.length; ++i { if 是左括号 { left++; continue; } if 是右括号 { right++; // 处理(1,)这样的结构 if 前一个是逗号 { error; } continue; } [newStrappend:str[i]]; } if left != right { error; }
这里只能提供一种参考,大家根据自己的想法尝试去实现一下,然后再评论中回复即可。
从这里看,似乎JingDong更偏向C语言的笔试题,所以大家还是要好好准备准备好C语言的基础知识。本篇文章所提供的所有参考答案均是笔者个人想法,请大家发现有什么不对的地方时,及时评论。
这里是面试、笔试题的收集整理的总入口,这里提供了所有的参考答案,持续更新!
关注 | 账号 | 备注 |
---|---|---|
标哥博客iOS交流群一 | 324400294(满) | 群一若已满,请申请群二 |
标哥博客iOS交流群二 | 494669518(满) | 群二若已满,请申请群三 |
标哥博客iOS交流群三 | 461252383(满) | 群三若已满,请申请群四 |
标哥博客iOS交流群四 | 250351140 | 群四若已满,会有提示信息 |
关注微信公众号 | iOSDevShares | 关注微信公众号,会定期地推送好文章 |
关注新浪微博账号 | 标哥的技术博客 | 关注微博,每次发布文章都会分享到新浪微博 |
关注标哥的GitHub | CoderJackyHuang | 这里有很多的Demo和开源组件 |
关于我 | 进一步了解标哥 | 如果觉得文章对您很有帮助,可捐助我! |