0

printf()の簡略化されたバージョンを作成しようとしていますが、va_list、va_start、va_arg、va_endを使用していません。

私の最初のアイデアは次のとおりです。

void my_printf(char * format、...);

次に、形式を確認し、%(引数)の数を数えて、関数に渡された変数の数を調べます。そこから、引数の数に基づいてバッファーを作成し、それを組み合わせて、write()を使用して最終的にそれらを出力することを考えていました。

この問題に取り組むためのより良い方法はありますか?計画で問題が発生しますか?

どんな助けでも大歓迎です。

私のブレーンストーミングコードのいくつかは次のとおりです。

// Count arguments
int cnt_s, cnt_c, cnt_d, cnt_u, cnt_x;
for (; *format; format++) {
    switch(format[0]) {
        case '%':
            switch(format[1]) {
                case 'd':
                    cnt_d++;
            }
    }
}
4

2 に答える 2

4

、、、で指定された引数にアクセスするには、、、が必要です va_listva_startva_argva_end...

あなたが使用したいのでなければvoid*、組合----- UGH!

于 2013-03-14T21:06:15.223 に答える
3

これを行うために私が考えることができる最善の方法 (注: これは安全でない可能性があります) は、フォーマット文字列のアドレスを取得し、そこからインクリメントして引数を見つけることです。

一緒にハッキングした実際の例を次に示します(他の印刷機能の実装を想定しています)

int my_printf(char *format, ...) {
    void *beg = &format;
    int i;
    beg += sizeof(char*);
    for (i = 0; i < strlen(format); i++) {
        if (format[i] == '%') {
            switch (format[i+1]) {
                case 's':
                    print_s(*((char**)beg)); 
                    beg += sizeof(char*);
                    break;
                case 'd':
                    print_d(*((int*)beg)); 
                    beg += sizeof(int);
                    break;
                case 'f':
                    print_f(*((float*)beg)); 
                    beg += sizeof(float);
                    break;
            }
            i++;
        } else {
            putchar(format[i]);
        }
    }
}

十分な引数を指定しないと、意図しない副作用が発生する可能性があり、微調整が必​​要になる場合があります。しかし、それはアイデアです。

説明: すべての関数引数が順番にスタックにプッシュされるため、これが機能します。したがって、最初の引数 (フォーマット文字列) があるので、そのアドレスを取得し、目的の引数に従ってインクリメントして、VA_ARGS マジックなしでスタック上の引数に直接アクセスできます。

于 2014-02-28T00:34:47.357 に答える