printf 格式化 (备忘)

来源:互联网 发布:淘宝用imei找到手机 编辑:程序博客网 时间:2024/06/06 10:57

man 3 printf 中间的一段, 介绍 format 参数 int printf(const char *format, ...);


   Format of the format string       The format string is a character string, beginning and ending in its initial shift state, if any.  The format string is composed of zero or more directives: ordinary  characters       (not  %),  which  are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments.  Each conversion       specification is introduced by the character %, and ends with a conversion specifier.  In between there may be (in this order) zero or more  flags,  an  optional  minimum  field       width, an optional precision and an optional length modifier.
就是说有两类, 1类是普通的, 原封不动的输出。 1类是有其他意思的: conversion specifications,  开始是  %,结束是 [conversion specifier]。 中间有其他修饰的, 可选minimum  field width, 最小字段宽度  printf ("float 2: %2.3f\n", (float) 2);precision  精度  printf ("float 2: %2.3f\n", (float) 2);length modifier.  printf ("size_t 2: %zi\n", (size_t) 2);

测试下解析参数


#include <assert.h>#include <printf.h>#include <stdarg.h>#include <stdio.h>#define ARG_MAX_LEN 1000void info () {    printf ("PA_FLAG_MASK\t\t %04hx\n", PA_FLAG_MASK);    printf ("~PA_FLAG_MASK\t\t %04hx\n", ~PA_FLAG_MASK);    printf ("conversion specifier\t args & ~PA_FLAG_MASK\n");    printf ("flags\t\t\t arg & PA_FLAG_MASK\n");    printf ("PA_INT\t\t\t %04hx\n", PA_INT);    printf ("PA_CHAR\t\t\t %04hx\n", PA_CHAR);    printf ("PA_STRING\t\t %04hx\n", PA_STRING);    printf ("PA_POINTER\t\t %04hx\n", PA_POINTER);    printf ("PA_FLOAT\t\t %04hx\n", PA_FLOAT);    printf ("PA_DOUBLE\t\t %04hx\n", PA_DOUBLE);    printf ("PA_FLAG_LONG_LONG\t %04hx\n", PA_FLAG_LONG_LONG);    printf ("PA_FLAG_LONG\t\t %04hx\n", PA_FLAG_LONG);    printf ("\n\n");}short int get_conversion_specifier (short pa) {    return pa & ~PA_FLAG_MASK;}short int get_flag (short pa) {    return pa & PA_FLAG_MASK;}void test_print_format (const char *fmt) {    printf ("test format [%s]\n", fmt);    int args[ARG_MAX_LEN];    int arg_no = parse_printf_format (fmt, ARG_MAX_LEN, args);    for (int i = 0; i < arg_no; ++i)        printf ("\t%d arg: %x\n", i, args[i]);}void skip_args_impl (const char *first_arg, va_list al) {    const char *fmt = first_arg;    do {        int args[ARG_MAX_LEN];        int arg_no = parse_printf_format (fmt, ARG_MAX_LEN, args);        if (arg_no == 0) break;        test_print_format (fmt);        for (int i = 0; i < arg_no; ++i) {            short int type = get_conversion_specifier (args[i]);            short int flag = get_flag (args[i]);            printf ("type %hx, flag %hx\n", type, flag);            switch (type) {            case PA_INT:                if (flag == PA_FLAG_LONG_LONG)                    (void) va_arg (al, long long);                else if (flag == PA_FLAG_LONG)                    (void) va_arg (al, long);                else                    (void) va_arg (al, int);                break;            case PA_CHAR:                (void) va_arg (al, int);                break;            case PA_STRING:                (void) va_arg (al, char *);                break;            case PA_POINTER:                (void) va_arg (al, void *);                break;            case PA_FLAG_LONG_LONG:                (void) va_arg (al, long long);                break;            case PA_FLOAT:                // FALLTHROUGH            case PA_DOUBLE:                 (void) va_arg (al, double);                break;            default:                printf ("unsupport type\n");                assert (0);            }        }        fmt = va_arg (al, char *);    } while (1);}void skip_args (const char *fmt, ...) {    va_list al;    va_start (al, fmt);    printf ("call skip_args_impl\n");    skip_args_impl (fmt, al);    va_end (al);}int main () {    info ();    test_print_format ("%2.3f");    test_print_format ("%2.3d");    test_print_format ("%s");    test_print_format ("%2.3f %2d %s %lld %2u");    skip_args ("%2.3f %2d %s %lld %2u",               (float) 2, (int) 2, "hello", (long long) 2, (unsigned) 2,               "%2.3f %2d %s %lld %2u",               (float) 2, (int) 2, "hello", (long long) 2, (unsigned) 2);    return 0;}

运行结果

PA_FLAG_MASK ff00~PA_FLAG_MASK 00ffconversion specifier args & ~PA_FLAG_MASKflags arg & PA_FLAG_MASKPA_INT 0000PA_CHAR 0001PA_STRING 0003PA_POINTER 0005PA_FLOAT 0006PA_DOUBLE 0007PA_FLAG_LONG_LONG 0100PA_FLAG_LONG 0200test format [%2.3f]0 arg: 7test format [%2.3d]0 arg: 0test format [%s]0 arg: 3test format [%2.3f %2d %s %lld %2u]0 arg: 71 arg: 02 arg: 33 arg: 1004 arg: 0call skip_args_impltest format [%2.3f %2d %s %lld %2u]0 arg: 71 arg: 02 arg: 33 arg: 1004 arg: 0type 7, flag 0type 0, flag 0type 3, flag 0type 0, flag 100type 0, flag 0test format [%2.3f %2d %s %lld %2u]0 arg: 71 arg: 02 arg: 33 arg: 1004 arg: 0type 7, flag 0type 0, flag 0type 3, flag 0type 0, flag 100type 0, flag 0


参考: http://www.gnu.org/savannah-checkouts/gnu/libc/manual/html_node/Parsing-a-Template-String.html#Parsing-a-Template-String

0 0
原创粉丝点击