【问题标题】:Printf/scanf replacement methods: some feedback/advice neededPrintf/scanf 替换方法:需要一些反馈/建议
【发布时间】:2010-08-08 21:25:31
【问题描述】:

我最近一直在编写一些基本的命令行程序(我想在整个夏天保持我的技能),但是printfscanf 已经开始让我烦恼了。我不是一个出色的 C 程序员,不得不陷入 printf/scanf 和他们的不稳定性(或者更糟糕的是,fgets 和他们的同类)并不完全让我处于一个舒适的环境中(出于这个原因确切地说,我喜欢NSLog,它具有令人欣慰的默认命名空间和自动的NSStringNSObject 解析)。

但令我失望的是,NSLog 没有对应的函数,并且会打印很多额外的“垃圾”(时间、函数名等,以及末尾的换行符),这让很多人失望我使用它的目的。所以我决定坐下来进行另一种编程练习,并编写函数来替换 printf 和 scanf 以满足我的需求。

瞧,我想出了自己的 NSInput.h 文件,其中包含两个函数:NSPrint()NSScan()。这两个函数非常模仿 printf 和 scanf,但也处理 NSString 的。我知道我在这里踩到了神圣的命名空间,但我无法抗拒(IFPrintIFScan 听起来很糟糕!)。

现在,虽然我很高兴我有工作代码(您可以找到源代码 here),但我知道它效率不高(但令我惊讶的是,NSPrint 是其数倍比 Xcode 4 中的 LLDB 下的 printf 更有效,但这不是重点)。我需要一些关于如何使功能更好、更高效的建议。例如,NSScan 将接收到的va_list 转换为NSPointerArray,并使用NSScanner 扫描格式和输入字符串,所以我知道还有很大的改进空间。

基本上,我想知道的是,我犯了哪些明显的错误可以而且应该改正?有什么我错过的大事吗?我应该被称为被宠坏并重新使用printfscanf吗?请告诉我,我在这里寻找输入(双关语不是故意的!)...

提前致谢!

【问题讨论】:

  • 您在 [NSString stringWithFormat:] 无法获得的类似 printf 的函数中寻找什么?
  • 我注意到一个明显的遗漏是缺少测试套件。
  • @Seamus:如果您查看源代码,那正是我所做的。 @Greg:实际上我以前从未做过测试套件,所以我想现在是尝试的好时机,对吧?感谢您的回复!
  • 哎呀。我的大脑在思考 sprintf,我试图弄清楚你为什么要重新发明轮子,作为现有轮子的薄包装。 :)
  • 不要称它们为 NSPrint 和 NSScan。不,只是不要!

标签: objective-c printf scanf xcode4


【解决方案1】:

我的想法:

  • 不要称它们为 NSxxxxx,NS 是为 Cocoa 和 Foundation 保留的。
  • 应修改这两个函数以接受FILE*,即您应该对fprintf()fscanf() 的接口进行建模以获得更大的灵活性。
  • 如果您使用fputs(),您的 printf 函数可能会更好

例如

void NSFPrint (FILE* fp, NSString *format, ...) 
{
    // Create the variable argument list.
    va_list args;
    va_start(args, format);

    // Using NSString, parse the argument list and convert it to a C string.
    fputs([[[[NSString alloc] initWithFormat:format arguments:args] autorelease] UTF8String], fp);
     va_end(args);
}
  • 考虑在 UTF-8 以外的编码中添加对输入和输出的支持。
  • 您的 scanf 替换在标准输入上混合了 C 缓冲 IO 和 Unix 无缓冲 IO。这可能很糟糕。
  • 即使不需要,您的 scanf 替换也会读取到行尾。我没有仔细检查,但如果扫描格式没有消耗整行,看起来你正在丢弃输入。这可能很糟糕。

【讨论】:

  • 感谢您的建议!我将尽快实施它们。不过,只有一个问题。我同时使用 C 缓冲 IO 和 Unix 非缓冲 IO 是什么意思,或者至少,我怎样才能避免这个问题?
  • 我已经稍微更新了我的代码 (snipt.org/XmL) 以反映您的建议(我已重命名函数 IFPrintIFScan,它们现在将文件指针作为参数,@987654330 @ 现在使用 fputs,而我已将 read(0, NULL, 1) 替换为 fgetc - 这就是缓冲/非缓冲 IO 的意思吗?)。希望我正朝着正确的方向前进。
  • 是的。 read() 函数调用是一个 Unix 系统调用,它直接从文件描述符中读取,只使用 Unix IO 调用。 fgets() 是一个在 FILE* 上运行的 C 库函数。文件指针。文件指针维护一个缓冲区,并且 fgets 仅在此缓冲区耗尽时从物理文件中读取。当它读取时,它会读取一个大块。这样,fgetc() 并没有你想象的那么低效,因为大多数时候它从内部缓冲区获取字符。
  • 现在,这个怎么样:pastie.org/1081717?我意识到,如果我不得不使用IFPrint 写入文件,我将更有可能使用NSFileHandle 而不是FILE *,所以我相应地工作。 IFPrint 将保持与以前相同的高效代码(打印到stdout),而IFFPrint 将使用 NSFileHandle 进行打印。我以相同的方式拆分IFScan,让用户扫描具有给定偏移量的NSFileHandle。你认为这值得付出努力,还是我只是在浪费时间?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-16
  • 1970-01-01
  • 2012-05-07
  • 2022-08-08
  • 2017-09-28
  • 1970-01-01
  • 2011-04-25
相关资源
最近更新 更多