c# 不使用stdarg. h库在C中创建简单的printf函数

k97glaaz  于 2023-03-21  发布在  C#
关注(0)|答案(4)|浏览(241)

我一直在用c语言编写一个非常简单的printf函数,它可以完成以下任务:它打印字符串、有符号整数、无符号整数和%符号。我检查过的每个实现都使用stdarg. h库。然而,我正在尝试不用它。问题是我不确定如何在printf中实现可变数量的参数。到目前为止,我想到的唯一方法是使用参数指针并尝试递增它们。这种方法不“It“似乎行不通。
下面是我目前拥有的代码:

#include <stdio.h>

void print_int(int n) {
    if (n < 0) {
        putchar('-');
        n = -n;
    }
    if (n / 10)
        print_int(n / 10);
    putchar(n % 10 + '0');
}

void print_uint(unsigned int n) {
    if (n / 10)
        print_uint(n / 10);
    putchar(n % 10 + '0');
}

void print_string(char *s) {
    while (*s)
        putchar(*s++);
}

void my_printf(char *format, ...) {
    void **arg = (void **) &format + 1;

    for (char *p = format; *p; p++) {
        if (*p != '%') {
            putchar(*p);
            continue;
        }

        switch (*++p) {
            case 'd':
                print_int(*(int *) arg++);
                break;
            case 'u':
                print_uint(*(unsigned int *) arg++);
                break;
            case 's':
                print_string(*(char **) arg++);
                break;
            case '%':
                putchar('%');
                break;
            default:
                putchar(*p);
                break;
        }
    }
}

int main() {
    int x = 42;
    unsigned int y = 1234567890;
    char *s = "Hello, world!";

    my_printf("Testing my_printf:\n");
    my_printf("Signed integer: %d\n", x);
    my_printf("Unsigned integer: %u\n", y);
    my_printf("String: %s\n", s);
    my_printf("Percent sign: %%\n");

    return 0;
}

运行此命令后得到的输出是:

Testing my_printf:
Signed integer: 849754744
Unsigned integer: 849754744
String: Y�Ź�U
Percent sign: %```

How can I fix this?
inn6fuwd

inn6fuwd1#

在C语言中,访问变量的方式是通过<stdarg.h>
如果您不愿意使用<stdarg.h>

  • 再想想
  • 再考虑一次
  • 不断反思,直到头脑清醒;
  • 如果您的课程作业要求您不要使用<stdarg.h>,请说明;
  • 您将进入一个充满伤害的世界,并且您的解决方案将被绑定到您开发代码的特定平台,至少在您将其移植到其他所有ABI(应用程序二进制接口)之前是这样。

除非你无法说服你的导师,否则不要这样做。如果你必须这样做,用并行但不同的名称(用于头文件和其中定义的类型、宏和函数)对<stdarg.h>进行最小限度的重新实现。现在比30年前要难得多。

blmhpbnm

blmhpbnm2#

如何读取传递给函数的可变参数的细节是高度特定于实现的。

    • 唯一**可移植地实现带有可变参数的函数的方法是通过stdargs.h中定义的函数。
ztyzrc3y

ztyzrc3y3#

<stdarg.h>可以是这样的:

// Personally I abhor '#pragma once' but I do not want to get
// into a discussion about what include guard name would be
// appropriate

#pragma once

typedef __builtin_va_list va_list;
#define va_arg( ap, type ) ( __builtin_va_arg( ap, type ) )
#define va_copy( dest, src ) ( __builtin_va_copy( dest, src ) )
#define va_end( ap ) ( __builtin_va_end( ap ) )
#define va_start( ap, parmN ) ( __builtin_va_start( ap, parmN ) )

......因为,基本上,* 只有编译器实际上知道 * 可变参数列表 * 实际上 * 如何在您选定的平台上工作,给定您选定的编译器选项等。
因此,您可以将上述内容写入您自己的<stdarg.h>--它可能与您正在使用/未使用的标准头文件一致,也可能不一致--或者您可以做明智的事情并且只使用您的环境所提供的<stdarg.h>

yduiuuwa

yduiuuwa4#

既然我不能发表评论:/我将在这里分享我的想法。
对我来说,代码可以工作,所以这可能是编译器的问题。我使用的是默认编译器Dev-C++,它是tdm-gcc 4.9.2 64位。
也有可能是你没有声明正确的编译器标志,我把标志-std=c11

相关问题