设置字符串格式以插入小数点

Formatting a string to insert a decimal point

提问人:Mumbai Verve 提问时间:10/1/2023 最后编辑:Mumbai Verve 更新时间:10/2/2023 访问量:179

问:

我有一个 4 位数宽的整数,我使用 sprintf 将其转换为字符串。 这个字符串数组应该表示一个十进制数 XX.XX。 例如。

uint16_t Value;
char buff [10];
Value = 1234;
sprintf(buff,"%04d", (unsigned int)Value);

我希望在 LCD 或 UART 上将其显示为 12.34。 最简单(粗略)的方法是逐个元素解析和输出数组,插入十进制句点,然后输出数组的其余部分。 有没有更优雅的方法可以做到这一点?

编辑:我想我有点过于简单了。要打印的数字可以是 00.00 到 99.99 之间的任何值。

sprintf(buff,“%04d”, (无符号整数)值);

我认为这会在需要时用前导 0 填充。 这种编码扭曲的主要原因是避免浮点运算和 printf 的使用。我将向一个函数传递一个字符串指针,该函数将逐个字符显示。

数组 C 字符串格式

评论

2赞 pmg 10/1/2023
你也许可以做printf("%u.%02u", (unsigned)Value / 100, (unsigned)Value % 100);
0赞 Jeff Holt 10/1/2023
@pmg,如果即使小于 1000 也总是应该打印前导“0”,那么格式不应该是吗?Value%02.%02u
0赞 pmg 10/1/2023
是的,@JeffHolt......或者,如果 OP 希望数字与空格右对齐,则正确的格式将是"%2u.%02u"
0赞 chux - Reinstate Monica 10/1/2023
@JeffHolt 我猜你的意思是.%02.%02u%02u.%02u
0赞 chux - Reinstate Monica 10/1/2023
@pmg,可以通过 : 来避免投射。100uprintf("%u.%02u", Value / 100u, Value % 100u);

答:

3赞 Mehdi Charife 10/1/2023 #1

如果您只使用 4 位宽的整数,一个简单的解决方案可能是:

#include <stdio.h>

int main() {
    int number = 1234;
    char buffer[200];
    sprintf(buffer, "%.2f", number/100.0);
    printf("%s\n", buffer);

    return 0;
}

评论

1赞 Serpent7776 10/1/2023
请注意,在 UNIX 系统上,根据 sprintf 手册页,这可能不会产生点,具体取决于当前的语言环境 linux.die.net/man/3/sprintf
0赞 chux - Reinstate Monica 10/1/2023
给定 OP 想要 “XX.XX”,当 时,输出只有 3 位数字。number = 123"%.2f"
0赞 Mehdi Charife 10/1/2023
@chux-ReinstateMonica OP 表示他们正在处理四位数宽的整数。 宽度为 3 位。123
1赞 chux - Reinstate Monica 10/1/2023
公平点.,,,,,,
0赞 Serpent7776 10/1/2023 #2

如果您知道总是有 4 位数字,则无需进行任何额外的算术运算即可执行此操作:

int main(void)
{
    int number = 2500;
    int bufsize = 64;
    char buf[bufsize];
    snprintf(buf, bufsize, "%d", number);
    printf("%c%c.%c%c\n", buf[0], buf[1], buf[2], buf[3]);
    return 0;
}

输出:25.00

0赞 chux - Reinstate Monica 10/1/2023 #3

表示十进制数 XX.XX

一个简单的方法是将值转换为浮点数,然后打印。

// 0 to '0' pad as needed
// 5 for minimum text width as in XX.XX
// .2 for always 2 digits after the '.'
sprintf(buff,"%05.2f", (double)Value / 100.0);

如果要避免浮点数学运算,请将整体和分数打印为 2 个部分。

sprintf(buff,"%02u.%02u", Value/100u, Value%100u);  // Note the u in 100u

请注意,这是一个无符号类型。对于有符号类型,我们需要避免分数中的 aValue'-'

sprintf(buff,"%02d.%02d", iValue/100, abs(iValue%100));

在所有情况下,16 位的值都可能超出 1000-9999 范围(“我有一个整数 4 位”),因此 OP 需要定义超出该范围的所需输出。uint16_t

一种简单的技术,即使我们“知道”不应该是 5 位数字,也可以确保:Value < 10000Value

Value %= 10000u;
sprintf(...
0赞 Fe2O3 10/1/2023 #4

注意:这两种方法都不构成以 null 结尾的 C 字符串。通常,LCD 显示器的 API 提供了一个更简单(更快)的选项,用于将“n”个字符写入显示器。

如果这是针对微控制器的,并且您不想要所有(笨重且可能未使用)的机器,则有以下几点:printf()

void cnvrt( unsigned val, char buf[5] ) {
    buf[4] = '0' + (val % 10); val /= 10; // Least Significant Digit
    buf[3] = '0' + (val % 10); val /= 10;
    buf[2] = '.'; // separator
    buf[1] = '0' + (val % 10); val /= 10;
    buf[0] = '0' + (val % 10); // MSD
}

如果 或 ,这仍然有效。val < 1000val > 9999


或者,也许您希望它作为一个循环:

void cnvrt( unsigned val, char buf[5] ) {
    for( unsigned i = 5; i--; ) {
        if( i == 2 ) buf[ i-- ] = '.';
        buf[ i ] = '0' + (val % 10);
        val /= 10;
    }
}

评论

0赞 Mumbai Verve 10/2/2023
您的示例 1 与我正在做的事情类似。示例 2 是一个更好的实现,我认为它适用于 00.00 到 99.99。