你将如何在 obj-c 中定义一个简单的“min”方法
Posted
技术标签:
【中文标题】你将如何在 obj-c 中定义一个简单的“min”方法【英文标题】:How would you define a simple "min" method in obj-c 【发布时间】:2011-01-08 16:02:30 【问题描述】:我想在 Utils 类中定义一个 min 和 max 方法。
@interface Utils
int min(int a, int b);
int max(int a, int b);
@end
但我不想有命名参数。这将是一个太重的符号。我想使用 C 风格的定义。但是然后[Utils min(a, b)]
作为电话不起作用。我的问题是什么?
提前感谢您的帮助
【问题讨论】:
嘿 Fred,如果你想使用 Object-C 来做,那么使用语言语法,如果你对此不满意,使用纯 C/C++,那会做你想做的,以你想要的方式。干杯, 那么为什么会有 MIN 和 MAX 宏以及一些平台呢? 注意:当前接受的答案被认为是不安全的。 (见我的评论/答案) 注意:“不安全”的 Objective-C 代码可能会导致 [self mutilate]。 【参考方案1】:它已经被定义为宏。
MIN(a, b)
MAX(a, b)
你不需要重新定义这些。
【讨论】:
正要指出这一点。既然已经在 obj-c 运行时实现了,为什么还要自己编写呢。 是在 obj-c 运行时还是在 MacOS 中。我正在使用 gcc-objective-c,但无法使用这些宏。 在 NSObjCRuntime.h 中定义,很多不在 gcc-objective-c 包含文件中。 @FredPolack,如果您没有使用 OS X,请尝试使用 C99 与标题math.h
中的宏 fmin( x, y )
。它是一个调用函数的宏,因此它适用于具有副作用的参数(与 Brandon 提供的不同)。【参考方案2】:
Brandon Bodnár 发布的解决方案存在严重问题(在撰写本文时已被标记为有效解决方案)。
此处描述的问题:http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Min-and-Max.html 以及(有效且安全的)解决方案:http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Typeof.html
自己去看看:
#include <stdio.h>
#define NAIVE_MAX(a,b) (a > b ? a : b)
#define NAIVE_MIN(a,b) (a < b ? a : b)
#if !defined MAX
#define MAX(a,b) \
( __typeof__ (a) __a = (a); \
__typeof__ (b) __b = (b); \
__a > __b ? __a : __b; )
#endif
#if !defined MIN
#define MIN(a,b) \
( __typeof__ (a) __a = (a); \
__typeof__ (b) __b = (b); \
__a < __b ? __a : __b; )
#endif
int main (int argc, const char * argv[])
int a = 3;
int b = 5;
#pragma mark NON-FATAL CASES:
printf("NAIVE_MAX(%d, %d) => %d\n", a, b, NAIVE_MAX(a, b));
printf("NAIVE_MIN(%d, %d) => %d\n", a, b, NAIVE_MIN(a, b));
printf("MAX(%d, %d) => %d\n", a, b, MAX(a, b));
printf("MIN(%d, %d) => %d\n", a, b, MIN(a, b));
printf("\nEverything fine so far...\n\n");
#pragma mark FATAL CASES:
//cache:
int _a = a;
int _b = b;
printf("NAIVE_MAX(%d++, %d++) => %d\n", _a, _b, NAIVE_MAX(a++, b++));
//reset:
a = _a;
b = _b;
printf("NAIVE_MIN(%d++, %d++) => %d\n", _a, _b, NAIVE_MIN(a++, b++));
//reset:
a = _a;
b = _b;
printf("NAIVE_MAX(++%d, ++%d) => %d\n", _a, _b, NAIVE_MAX(++a, ++b));
//reset:
a = _a;
b = _b;
printf("NAIVE_MIN(++%d, ++%d) => %d\n", _a, _b, NAIVE_MIN(++a, ++b));
printf("\nOuch, this doesn't look right at all!\n\n");
#pragma mark NON-FATAL CASES:
//reset:
a = _a;
b = _b;
printf("MAX(%d++, %d++) => %d\n", _a, _b, MAX(a++, b++));
//reset:
a = _a;
b = _b;
printf("MIN(%d++, %d++) => %d\n", _a, _b, MIN(a++, b++));
//reset:
a = _a;
b = _b;
printf("MAX(++%d, ++%d) => %d\n", _a, _b, MAX(++a, ++b));
//reset:
a = _a;
b = _b;
printf("MIN(++%d, ++%d) => %d\n", _a, _b, MIN(++a, ++b));
printf("\nAh, much better now.\n\n");
return 0;
控制台日志:
NAIVE_MAX(3, 5) => 5
NAIVE_MIN(3, 5) => 3
MAX(3, 5) => 5
MIN(3, 5) => 3
Everything fine so far...
NAIVE_MAX(3++, 5++) => 6
NAIVE_MIN(3++, 5++) => 4
NAIVE_MAX(++3, ++5) => 7
NAIVE_MIN(++3, ++5) => 5
Ouch, this doesn't look right at all!
MAX(3++, 5++) => 5
MIN(3++, 5++) => 3
MAX(++3, ++5) => 6
MIN(++3, ++5) => 4
Ah, much better now.
所以永远不要使用上面代码中看到的幼稚实现(正如 Brandon Bodnár 所建议的,对不起,伙计;))如果你想避免这样的最坏情况。
【讨论】:
【参考方案3】:由于您没有使用 OS X 的 Objective-c 实现,您可能无法访问预定义的 MIN 和 MAX 宏。
你可以自己定义这些
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
可能有更好的方法来定义它们,但它们会创建简单的宏供您使用。您可以将它们添加到您的类通常共享的任何通用 .h 文件中。
【讨论】:
这些要与一粒盐一起使用。例如 MIN(i++, j++) 不会产生预期的结果。有关详细信息和解决方案,请参阅我的答案。【参考方案4】:对于这个特定的应用程序来说,这可能不是一个好主意,但是可能编写带有“无名称”参数的 Objective-C 方法,或者更确切地说是使用零长度名称:
+ min:(int)a :(int)b;
...
[Utils min:a :b]
(选择器将是@selector(min::)
。)
【讨论】:
【参考方案5】:Objective-C 类方法使用命名参数,句号。就是这样。
为什么不让它成为一个全局的、免费的函数呢?你不应该为这种事情需要一个 Utils 类。
如果您不想弄乱全局命名空间,可以使用 Objective-C++(将所有 .m 文件重命名为 .mm)并将其放入命名空间中。
【讨论】:
【参考方案6】:在名为“XXIntegerMath.h”的模板文件中删除这个...
#import <Foundation/Foundation.h>
static inline NSInteger imax(NSInteger a, NSInteger b)
return a > b ? a : b;
static inline NSInteger imin(NSInteger a, NSInteger b)
return a < b ? a : b;
然后在你的objective-c类中......
#import "XXIntegerMath.h"
NSInteger minValue = imin(someValue, someOtherValue);
它没有遇到 Regexident 描述的问题。
【讨论】:
【参考方案7】:这是我为 multi-max 和 multi-min 创建的宏,它允许超过 2 个输入。
float a = MMAX(1,2,9.33,2.5); //a = 9.33
内部机制使用 long double,您只需将输出转换为您正在使用的任何变量。我更喜欢使用 typeof 的解决方案,但无法根据每个参数在__VA_ARGS__
上弄清楚如何做到这一点,也许比我更精通 C 语言的人可以弄清楚并发表评论?无论如何,这是宏定义:
#define MMAX(...) (\
long double __inputs[(sizeof((long double[])__VA_ARGS__)/sizeof(long double))] = __VA_ARGS__;\
long double __maxValue = __inputs[0];\
for (int __i = 0; __i < (sizeof((long double[])__VA_ARGS__)/sizeof(long double)); ++__i) \
long double __inputValue = __inputs[__i];\
__maxValue = __maxValue>__inputValue?__maxValue:__inputValue;\
\
__maxValue;\
)
#define MMIN(...) (\
long double __inputs[(sizeof((long double[])__VA_ARGS__)/sizeof(long double))] = __VA_ARGS__;\
long double __minValue = __inputs[0];\
for (int __i = 0; __i < (sizeof((long double[])__VA_ARGS__)/sizeof(long double)); ++__i) \
long double __inputValue = __inputs[__i];\
__minValue = __minValue<__inputValue?__minValue:__inputValue;\
\
__minValue;\
)
【讨论】:
以上是关于你将如何在 obj-c 中定义一个简单的“min”方法的主要内容,如果未能解决你的问题,请参考以下文章
ios如何将自定义控制器重定向obj-c代码放在自定义视图中
如何在 iPad 上使用 JavaScript/Obj-C 将图像保存到照片库?
Obj-C, UINavigationControllers inside a UITabbarController,简单解释一下?