免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3724 | 回复: 11
打印 上一主题 下一主题

[C] [请教]可以自己定义如下格式的printf的控制符号吗? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-21 14:47 |只看该作者 |倒序浏览
5可用积分
可以自己定义中间有空格的控制符吗?
比如定义 "%a %b"为一种格式而不是两种

在标准C和GNU C中,存在这样类型的格式控制符吗?

谢谢!

论坛徽章:
223
2022北京冬奥会纪念版徽章
日期:2015-08-10 16:30:32操作系统版块每日发帖之星
日期:2016-05-10 19:22:58操作系统版块每日发帖之星
日期:2016-02-18 06:20:00操作系统版块每日发帖之星
日期:2016-03-01 06:20:00操作系统版块每日发帖之星
日期:2016-03-02 06:20:0015-16赛季CBA联赛之上海
日期:2019-09-20 12:29:3219周年集字徽章-周
日期:2019-10-01 20:47:4815-16赛季CBA联赛之八一
日期:2020-10-23 18:30:5320周年集字徽章-20	
日期:2020-10-28 14:14:2615-16赛季CBA联赛之广夏
日期:2023-02-25 16:26:26CU十四周年纪念徽章
日期:2023-04-13 12:23:10操作系统版块每日发帖之星
日期:2016-05-10 19:22:58
2 [报告]
发表于 2009-04-21 14:52 |只看该作者
一个字,宏,

[ 本帖最后由 action08 于 2009-4-21 14:54 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2009-04-21 14:56 |只看该作者
原帖由 action08 于 2009-4-21 14:52 发表
一个字,宏,

抱歉,不能用宏
因为要测到如下的所有分支
88:      if ((size_t) spec.data_arg < n)
89:        switch (spec.ndata_args)
90:          {
91:          case 0:               /* No arguments.  */
92:            break;
93:          case 1:               /* One argument; we already have the type.  */
94:            argtypes[spec.data_arg] = spec.data_arg_type;
95:            break;
96:          default:
97:            /* We have more than one argument for this format spec.  We must
98:               call the arginfo function again to determine all the types.  */
99:            (void) (*__printf_arginfo_table[spec.info.spec])
100:              (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg]);
101:            break;
102:          }

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
4 [报告]
发表于 2009-04-21 14:58 |只看该作者
原帖由 flyingbox 于 2009-4-21 14:47 发表
可以自己定义中间有空格的控制符吗?
比如定义 "%a %b"为一种格式而不是两种

在标准C和GNU C中,存在这样类型的格式控制符吗?

谢谢!


好像没有现成的功能。
而且, 最终你想实现的控制符, 是printf带有的? 还是printf不带的?

如果printf本身具有这个功能, 再传递给printf之前, 把格式化字符串自己替换一下?
如果printf本身没有这个功能, 自己实现my_printf可以吗?

论坛徽章:
0
5 [报告]
发表于 2009-04-21 15:00 |只看该作者
自己封装一个?

论坛徽章:
0
6 [报告]
发表于 2009-04-21 15:02 |只看该作者
原帖由 OwnWaterloo 于 2009-4-21 14:58 发表


好像没有现成的功能。
而且, 最终你想实现的控制符, 是printf带有的? 还是printf不带的?

如果printf本身具有这个功能, 再传递给printf之前, 把格式化字符串自己替换一下?
如果printf本身没有这 ...


现在要测试parse_printf_format函数,其中有几句
96:          default:
97:            /* We have more than one argument for this format spec.  We must
98:               call the arginfo function again to determine all the types.  */
99:            (void) (*__printf_arginfo_table[spec.info.spec])
100:              (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg]);
101:            break;
走不到
看字面的意思是需要在写格式控制符的时候,多个符号代表一种格式。是不是我理解错误,还是这样的条件根本不可能实现?

论坛徽章:
223
2022北京冬奥会纪念版徽章
日期:2015-08-10 16:30:32操作系统版块每日发帖之星
日期:2016-05-10 19:22:58操作系统版块每日发帖之星
日期:2016-02-18 06:20:00操作系统版块每日发帖之星
日期:2016-03-01 06:20:00操作系统版块每日发帖之星
日期:2016-03-02 06:20:0015-16赛季CBA联赛之上海
日期:2019-09-20 12:29:3219周年集字徽章-周
日期:2019-10-01 20:47:4815-16赛季CBA联赛之八一
日期:2020-10-23 18:30:5320周年集字徽章-20	
日期:2020-10-28 14:14:2615-16赛季CBA联赛之广夏
日期:2023-02-25 16:26:26CU十四周年纪念徽章
日期:2023-04-13 12:23:10操作系统版块每日发帖之星
日期:2016-05-10 19:22:58
7 [报告]
发表于 2009-04-21 15:08 |只看该作者
就是用宏,

外加sprintf(),然后自己再封装一个sprintTT()


---
宏是关键

[ 本帖最后由 action08 于 2009-4-21 15:10 编辑 ]

论坛徽章:
223
2022北京冬奥会纪念版徽章
日期:2015-08-10 16:30:32操作系统版块每日发帖之星
日期:2016-05-10 19:22:58操作系统版块每日发帖之星
日期:2016-02-18 06:20:00操作系统版块每日发帖之星
日期:2016-03-01 06:20:00操作系统版块每日发帖之星
日期:2016-03-02 06:20:0015-16赛季CBA联赛之上海
日期:2019-09-20 12:29:3219周年集字徽章-周
日期:2019-10-01 20:47:4815-16赛季CBA联赛之八一
日期:2020-10-23 18:30:5320周年集字徽章-20	
日期:2020-10-28 14:14:2615-16赛季CBA联赛之广夏
日期:2023-02-25 16:26:26CU十四周年纪念徽章
日期:2023-04-13 12:23:10操作系统版块每日发帖之星
日期:2016-05-10 19:22:58
8 [报告]
发表于 2009-04-21 15:11 |只看该作者
对了,我在UNIX6代码中看到的,printf家族函数都是调用的putchar系列,

论坛徽章:
0
9 [报告]
发表于 2009-04-21 15:12 |只看该作者
原帖由 action08 于 2009-4-21 15:08 发表
就是用宏,

外加sprintf(),然后自己再封装一个sprintTT()


---
宏是关键


抱歉不是你说的那样。宏会被先展开,仍然不满足条件。
还是谢谢你

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
10 [报告]
发表于 2009-04-21 15:18 |只看该作者
原帖由 flyingbox 于 2009-4-21 15:02 发表


现在要测试parse_printf_format函数,其中有几句
96:          default:
97:            /* We have more than one argument for this format spec.  We must
98:               call the arginfo funct ...


抱歉 ……  真的没看懂那段代码 ……

如果需要自己实现格式控制, 可以使用 stdarg.h 中提供的类型与宏。

声明:
int sum(int count, ... );

实现:
#include <stdarg.h>

int sum(int count, ... ) {
    va_list ap; // 实际参数指针
    va_start(ap, count);  // 初始化, ap将指向count后的参数。
    int result = 0;
    for (int i=0;i<count;++i ) {
        int arg = va_arg(ap,int); // 取出一个int参数。
        result += arg;
    }
    va_end(ap); // 释放ap
    return result;
}


那么, 就可以使用这个带有变长参数列表的sum函数了:

int s1 = sum(3,1,2,3);
assert(s1==6);

int s2 = sum(0);
assert(s2==0);


可以通过同样的方式实现 my_printf。
按你的需要, 解析const char* fmt, 并提取参数。


需要注意:
va_end 是必须调用的。
va_arg(ap, type);  type不能是 char, signed char, unsigned char, short, unsigned short, float.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP