【问题标题】:How to print the char, integer, float and double values without using format specifiers in c如何在不使用 c 中的格式说明符的情况下打印 char、integer、float 和 double 值
【发布时间】:2013-12-05 07:46:23
【问题描述】:

我想在我的 c 程序中不使用格式说明符来打印 char、int、float 和 double 值。 我可以使用以下代码打印字符串:

char s[] = "Hello\n";
fprintf(stdout, s);

如何打印其他数据类型的值?

【问题讨论】:

  • 你可以在c++中使用cout 。
  • 为什么世界上会有人想要这样做?
  • 在 C 中,这是打印不同数据类型的方式。 C 库就是这样编写的,因此,您可以根据需要从头开始编写自己的库!
  • 为什么我需要重新发明?
  • OP 在他的帖子中明确表示“不使用格式说明符”。

标签: c


【解决方案1】:

要打印char,请使用:

fputc(c, stream)

(如果流是stdout,可以使用putchar(c)。)

要打印int

  • 如果int 是否定的,打印“-”。
  • 计算整数的各个数字。这可以通过从最低有效位到最高有效位计算数字并将它们保存在要以相反顺序打印的缓冲区中来完成,或者通过确定最高有效位在哪里然后从最高有效位到最低有效位计算数字来完成。您可以使用余数运算(例如 x % 10)来计算数字的最低有效位,也可以使用除法(例如 x / 10)来删除该数字。
  • 需要注意的是,如果原始数字为负数,则必须小心计算其位数。 % 运算符将返回负值。有些人试图通过否定整数来解决这个问题,如果它是负数。但是,如果数字是最小可能的int,这可能会溢出。例如,在许多 C 实现中,最小的 int 值是 -2,147,483,648,但它不能被否定,因为最大的 int 是 2,147,483,647。
  • 任何数字形式的数字(0 到 10)都可以通过添加'0' 转换为字符(“0”到“9”),例如int d = x % 10; char c = d + '0';。 C 标准保证这会在 c 中生成适当的字符。
  • 从数字中获取字符后,打印出来。

要打印floatdouble

  • 完全正确地做到这一点很困难,尽管这是一个已解决的问题。它的经典参考是Correctly Rounded Binary-Decimal and Decimal-Binary Conversions by David M. Gay
  • 如果您只是想要一个适合学习练习的简单实现,那么您可以像格式化整数一样格式化浮点值:单独计算数字。您还需要决定是打印定点计数法还是科学计数法(或其他)。
  • 要打印定点表示法,打印上面值的整数部分,对于整数类型。然后打印一个“.”以及值的小数部分的一些数字。
  • 要打印科学计数法,请计算指数部分的值(例如,将 12345789 表示为“1.23456789e7”,指数为 7,即 107。将值除以 10该指数的幂并将结果值打印为定点数(因此,在本例中,您打印“1.23456789”),然后打印“e”,即打印指数部分。
  • 上面会出现浮点舍入错误,因此仅适用于学习练习,不适用于优质产品。

以上内容应该足以让您入门。这显然不是完整的代码。

【讨论】:

  • Minor: "数字形式的数字(0到10)可以转换为字符(“0”到“9”)” --> “”数字形式的数字(0到9) ...”
【解决方案2】:

只是一个想法,不是很理想:

int myvalue = 12345;
char buffer[100];
size_t index = 0;

while (myvalue) {
  buffer[index] = '0' + myvalue % 10;
  myvalue = myvalue / 10;
  index++;
}
buffer[index] = '\0';

reverse(buffer);
fprintf(stdout, buffer);

你必须考虑负号。以及缓冲区的大小(100 是一个非常糟糕的猜测)。

【讨论】:

  • 模运算符只适用于整数类型,用户也想用浮点数来做,但聪明的尝试解决可能是一个愚蠢的问题
  • 使用浮点数可以进行其他数字运算算法(使用对数 f.e.)
  • 没错,但您将根据数据类型选择算法,而 OP 似乎在寻求一种无需指定数据类型的方法。
【解决方案3】:

要将char 打印为字符,请使用fputc()


要以十进制形式打印整数(包括char),请调用print_unsigned()print_signed(),具体取决于它是有符号整数还是无符号整数。

下面使用递归首先打印最高有效数字。

对于有符号整数,它将正数翻转为负数,避免 -INT_MIN 的未定义行为。

int print_unsigned(uintmax_t x) {
  if (x >= 10) {
    if (print_unsigned(x / 10) == EOF) return EOF;
  }
  return fputc('0' + x % 10, stdout);
}

static int print_signed_helper(intmax_t x) {
  if (x <= -10) {
    if (print_signed_helper(x / 10) == EOF) return EOF;
  }
  return fputc('0' - x % 10, stdout);
}

int print_signed(intmax_t x) {
  if (x < 0) {
    if (fputc('-', stdout) == EOF) return EOF;
  } else {
    x = -x; // overflow not possible
  }
  return print_signed_helper(x);
}

如果输出导致输出错误,上述操作会提前停止。 EOF 很少从 fputc() 返回。


打印floatdouble:待定代码。

【讨论】:

    【解决方案4】:

    简短的回答是,虽然有可能一起破解一些东西,从而做一些你想要的事情(按照 Peter Miehle 在另一个答案中发布的解决方案),但基本上 C 不是为这种功能而设计的,并且该语言不支持它。你想要的是函数重载,这是 C++ 和许多其他高级语言提供的。

    即使是 Peter Miehle 的解决方案也不能实现为函数(在 C 中),因为函数需要什么样的参数?要么它被传递一个类型,在这种情况下我们知道类型并且可以使用printf,或者它被传递例如一个void指针,在这种情况下,如何在不知道指针指向的底层数据类型的情况下实现算术运算符?

    【讨论】:

    • 这个答案误解了这个问题。这个问题可以通过将 C 类型(例如 intfloat)格式化为包含数字的字符串的算法来回答。不需要提供多态性或函数重载。
    猜你喜欢
    • 2021-07-13
    • 1970-01-01
    • 2018-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多