【问题标题】:Objective C - #define using __VA_ARGS__Objective C - #define 使用 __VA_ARGS__
【发布时间】:2014-02-12 13:48:50
【问题描述】:

我正在学习如何使用宏,但现在对宏感到困惑。

我正在尝试创建一个 NSString 连接,它只会将每个参数附加到彼此。

例如:concatOP(@"hey",@"Jude",@"Don't") 将返回一个 NSString,其中包含:@"heyJudeDon't"

我实际上编写了一些代码(一些在这里也可以找到)来获取参数的数量,但我没有成功完成工作的第二部分。

#define NUMARGS(...)        ( sizeof((int[]){__VA_ARGS__}) / sizeof(int) )
#define concatOP(...)       NSMutableString *format = [[NSMutableString alloc] init];\
                            for( int i = 0; i < NUMARGS(__VA_ARGS__); i++){\
                            [format appendString:@"%@"];}\
                            [[NSString alloc] initWithFormat:format, __VA_ARGS__]

我实际上得到了很多错误,告诉我格式不存在或者我错过了一些“;”或其他结束标签。

【问题讨论】:

  • 我不知道这是一个随意的例子还是您要解决的真正问题,但人们经常使用NSArray 方法componentsJoinedByString 进行这种连接。所以NSString *result = [@[@"Hey",@"Jude",@"Don't"] componentsJoinedByString:@""];.
  • 为什么我得到了 -1 ? ://
  • 它可能被否决了,因为提议的宏遇到了这样的基本问题(正如 Cy-4AH 的扩展所示,虽然你的意图很明确,但提议的执行没有任何意义),即使确实如此,我不确定这首先是一个非常好的宏应用程序。不过,我不确定它是否值得投反对票(它让我在可变参数宏中四处挖掘,所以我学到了一些东西)。我不会为反对票而汗流浃背。
  • 这个网站的目的是帮助人们,所以也许这个问题对某些人来说似乎很容易,但当我们遇到一些关于可变参数和预处理器指令的问题时,它并不明显......很抱歉不知道一切这是我最大的错误:/ 我仍然认为我的问题仍然值得,因为我学到了一些东西,而且我确信我不是唯一的。
  • 对不起,这不是给你的 ;) 谢谢你的解释 :)

标签: ios objective-c c-preprocessor variadic-macros variadic-functions


【解决方案1】:

这是你的宏:

#define concatOP(...) [@[__VA_ARGS__] componentsJoinedByString:@""]

编辑: 如果你放松你的宏NSString* result = concatOP(@"hey",@"Jude",@"Don't"); 你会得到:

NSString* result = NSMutableString *format = [[NSMutableString alloc] init]; for( int i = 0; i < NUMARGS(@"hey",@"Jude",@"Don't"); i++){ format = [format appendString:@"%@"];} [[NSString alloc] initWithFormat:format, @"hey",@"Jude",@"Don't"];

看起来很奇怪。

【讨论】:

  • 这实际上就像一个魅力,但我仍然不明白为什么我的代码不起作用(即使你更好,因为方式更简单)。你对此有什么想法吗?
  • @CladClad 你用你的宏找不到__VA_ARGS__s 的参数数量。看这个:stackoverflow.com/questions/2124339/…
  • NUMARGS 工作是为了找到我尝试过的参数数量;)它实际上来自您刚刚给出的帖子;)
  • 我对@9​​87654326@ 不好,这是一个旧测试。实际上,我只是想获取输出的格式,如果有 2 个 args 等,则类似于 @"%@%@" 但也许这是一种愚蠢的做法^^
【解决方案2】:

这并不能完全回答您的问题,但 NSString 文字由编译器连接,就像它们的 C 对应物一样,因此此代码开箱即用:

NSString *str = @"Hey" @"Jude" @"Don't";

等同于:

NSString *str = @"HeyJudeDon't";

这通常用于在源文件的多行中拆分长字符串文字。

底线;你不需要所有那些凌乱的宏和无意义的方法来做到这一点。

【讨论】:

  • 真的 :'( 谢谢你,感谢你,我学到了一些非常有用的东西。我想我会永远记住它 :s 非常感谢 ;)
  • @CladClad 它只适用于 literals,这限制了它们将长字符串拆分为多行。我个人从未将这个(或他们的 C 对应物)用于其他任何事情。
  • 是的,但仍然很高兴知道,我以前从未在任何地方见过它:s 这两种方式实际上都很好知道 ;)
  • +1 我发现这种语法非常适合长 SQL 语句,我想将它分成多行以使其更具可读性。不过,我不会在字符串的后续部分使用文字,例如我总是做类似NSString *str = @"Hey" "Jude" "Don't"; 的事情(只有一个字符串文字@)。我不确定是否有一种令人信服的论点。
【解决方案3】:

我不知道如何使用宏来做到这一点。

你可以在 Objective C 中这样做:

实现如下方法:

- (NSString *)concateStrings:(NSString *)firstArg, ...
{
    NSMutableString *concatString = [[NSMutableString alloc] init];
    va_list args;
    va_start(args, firstArg);
    for (NSString *arg = firstArg; arg != nil; arg = va_arg(args, NSString*))
    {
        [concatString appendString:arg];
    }
    va_end(args);

    return concatString;
}

你可以这样调用这个方法:

NSLog(@"%@",[self concateStrings:@"hey",@"Jude",@"Don't",nil]) ;

输出:

heyJudeDon't

确保最后传递nil

【讨论】:

  • 是的,实际上我绝对想把它放在一个宏中,谢谢你的回答,但不是我想要的:)
  • @CladClad:感谢您的评论,我也知道如何使用宏来做到这一点。谢谢你的问题:)
  • 很高兴知道其他人也不知道如何将其设为宏。 ;)
猜你喜欢
  • 2014-08-11
  • 1970-01-01
  • 1970-01-01
  • 2012-06-24
  • 2011-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多