目标C:在每个索引位置具有不同对象的漂亮打印NSArray

时间:2013-03-22 15:39:12

标签: nsarray objective-c++ nslog

我有一个不同对象的NSArray,例如NSString和NSNumber整数。

我有一个特定的格式字符串,我想用它来打印对象内容,而不仅仅是使用

@"%@|%@" 

但是,例如

@"%-13s|%010d"

我已经实现了以下功能来执行我在StackOverflow和其他地方找到的@“%@ |%@”类型打印:

@implementation NSString (NSArrayFormatExtension)

+ (id) stringWithFormatFromNSArray: (NSString *) format array: (NSArray*) args;
{
  id *argList = malloc( sizeof( id )  * [args count] );
  [ args getObjects: argList ];

  NSString* result = [ [ [ NSString alloc ] initWithFormat: format arguments: (va_list) argList ] autorelease ];

  free(argList);

  return result; 
}

@end

调用然后打印如下:

NSString *printstring = [ NSString stringWithFormatFromNSArray: nsFormatString array: nsarray_of_objects ]

允许类型为@“%@%@”的nsFormatStrings打印对象内容,但不打印@“%s%d”类型格式以打印具有更详细格式的基础C类型。

我对解决方案有两个问题和想法,但不想在这里重新发明轮子。

1。)我可以使用从className派生的类型切换来重复NSArray项目 - 确定 - 但我想知道是否有标准的方法来执行此操作。

这也意味着将格式字符串解构为单独的%实体(或将 it 作为数组传递并通过它 - 不是很干净,以及需要保留任何其他非格式化条目,如上面的管道分隔符。)

2。)使用@“%@ |%@”的上述代码在32位Linux上使用gcc / objc / objc ++ 4.6.X及以上版本,但64位Linux上的段错误,我需要有它同时致力于两者。

从我读过的内容来看,这似乎是某些Linux系统上64位va_list实现的一个相当普遍的问题。

即使我满足于对象格式化,也不满足特定的C类型格式,但这仍然存在。有人有解决方法吗?似乎它倾向于强制实施解决方案1.)在每个实例中都是可移植的,但那是

a。)代码和时间耗时 b。)效率不高。

我真的需要能够进行详细的格式化以及从命令行程序打印这些结果需要由完全不同的系统作为CSV文件或管道等读取。

我可能也希望在字段之间使用不同的分隔符 - 例如

....|....;....,....#....^....

如果我能这样做,我会嵌入我的格式字符串中。

因此,使用单个“加入”分隔符的任何格式都不是答案。

Soooooo在Perl中更容易做这种事情;-) - 但是 - 这个特定的软件是用Objc ++编写的(用C ++ lib链接)。

您的想法和建议表示赞赏。

1 个答案:

答案 0 :(得分:1)

您的程序在某些平台上不起作用的原因是它使用了非可移植行为 - 将id的C样式数组转换为va_list并不能保证工作:

(va_list) argList

这就是为什么基本%010d行的基元格式不起作用的原因:NSArray不能包含基元,因此int由{{1}表示内部有一个NSNumber

通常,C(以及扩展,Objective C)不支持动态创建变量参数列表。这就是为什么你不能使用需要变量参数列表的格式化方法。

不幸的是,您最好的选择需要大量编码。制作一个这样的方法:

int

此代码假定第一个参数是数组,而不是字符串。每个元素必须包含相应参数的格式。数字格式将传递给+ (id) stringWithFormatsFromNSArray: (NSArray*) formats array: (NSArray*) args { // verify that formats and args have the same number of entries NSMutableString *res = [NSMutableString string]; for (int i = 0 ; i != args.count ; i++) { id arg = [args objectAtIndex:i]; id fmt = [formats objectAtIndex:i]; if ([arg isKindOfClass:[NSNumber class]]) { // Apply fmt to NSNumberFormatter NSNumberFormatter *nf = [[NSNumberFormatter alloc] init]; [nf setFormat:fmt]; [res appendString:[nf stringFromNumber:arg]]; } else { [res appendFormat:fmt, arg]; } } return [res copy]; } ,它允许您格式化表示数字的非基本对象。所有其他格式将传递给NSNumberFormatter。请注意,分隔符必须包含在相应对象的格式字符串中。您可以在除初始对象之外的所有对象之前添加分隔符,也可以在除尾随之外的所有对象之后添加分隔符。