如何在Arduino上格式化长添加数千分隔符

How to format a long adding thousands separator on Arduino

本文关键字:添加 分隔符 格式化 Arduino      更新时间:2023-10-16

我正在开发Arduino上的一个项目,该项目解析来自远程web API的一些JSON数据,将其显示在16x2 LCD上。

我想格式化一个长解析与TextFinder添加千位分隔符(逗号分隔符将是好的)。

简而言之,我如何编写formatLong函数?

long longToBeFormatted = 32432423;
formattedLong = formatLong(longToBeFormatted); //How to implement this?
lcd.print(formattedLong) // formattedLong is a string

我不确定在Arduino上使用什么工具集。有时库会支持一个非标准的'thousand grouping'标志——单引号字符是典型的扩展名:

printf("%'ld",long_val);

如果您的库不支持此操作,可以使用下面的代码:

#include <stddef.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include <assert.h>
size_t strlcpy( char* dest, char const* src, size_t dest_size);
size_t format_long( long x, char* buf, size_t bufsize)
{
    // This code assumes 32-bit long, is that the
    // case on Arduino?  Modifying it to be able to
    // handle 64-bit longs (or to not care) should be
    // pretty straightforward if that's necessary.
    char scratch[sizeof("-2,147,483,648")];
    char* p = scratch + sizeof(scratch);    // Work from end of buffer
    int neg = (x < 0);
    // Handle a couple special cases
    if (x == 0) {
        return strlcpy( buf, "0", bufsize);
    }
    if (x == INT_MIN) {
        // Lazy way of handling this special case
        return strlcpy( buf, "-2,147,483,648", bufsize);
    }
    // Work with positive values from here on
    if (x < 0) x = -x;
    int group_counter = 3;
    *(--p) = 0; // Null terminate the scratch buffer
    while (x != 0) {
        int digit = x % 10;
        x = x / 10;
        assert( p != &scratch[0]);
        *(--p) = "0123456789"[digit];
        if ((x != 0) && (--group_counter == 0)) {
            assert( p != &scratch[0]);
            *(--p) = ',';
            group_counter = 3;
        }
    }
    if (neg) {
        assert( p != &scratch[0]);
        *(--p) = '-';
    }
    return strlcpy(buf, p, bufsize);
}

/*
    A non-optimal strlcpy() implementation that helps copying string
    without danger of buffer overflow.
    This is provided just in case you don't have an implementation
    so the code above will actually compile and run.
*/
size_t strlcpy( char* dest, char const* src, size_t dest_size)
{
    size_t len = strlen(src);
    if (dest_size == 0) {
        // nothing to copy - just return how long the buffer should be
        //  (note that the return value doens't include the null terminator)
        return len;
    }
    size_t tocopy = (dest_size <= len) ? dest_size-1 : len;
    memmove( dest, src, tocopy);
    dest[tocopy] = 0;
    return len;
}

可能不是最好的算法,但这里有一个实现示例(标准C):

char* formatLong(long toBeFormatted)
{
    // Get the string representation as is
    char* buffer = (char*) malloc(sizeof(long));
    ltoa(toBeFormatted, buffer, 10);
    // Calculate how much commas there will be
    unsigned int buff_length = strlen(buffer);
    unsigned int num_commas = buff_length / 3;
    unsigned int digits_left = buff_length % 3;
    if (digits_left == 0)
    {
        num_commas--;
    }
    // Allocate space for final string representation
    unsigned int final_length = buff_length + num_commas + 1;
    char* final = (char*) malloc(final_length);
    memset(final, 0, final_length);
    // Parse strings from last to first to count positions
    int final_pos = final_length - 2;
    int buff_pos = buff_length - 1;
    int i = 0;
    while(final_pos >= 0)
    {
        final[final_pos--] = buffer[buff_pos--];
        i++;
        if (i % 3 == 0)
        {
            final[final_pos--] = ',';
        }
    }
    // Free obsolete memory and return buffer
    free(buffer);
    return final;
}

您可以尝试以下操作:

std::string formatLong(long l) {
    int power = 0;
    while (l / (pow(1000, power)) { power += 1; }
    power -= 1;
    std::stringstream s;
    while (power) {
         s <<  l / pow(1000, power);
         s << ",";
         l % (pow(1000, power));
         power -= 1;
    }
    return s->str();
}

也许我能帮你…我用这个草图在arduino LCD上制作了千位分隔符。

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//TULISAN DENGAN SPARATOR BELI BBM
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    void TulisanDesimalBeli(char customKey, String DataStr)
{
  c=DataStr.length();
    if (c<=7)
    {
      if (c<4)
       {
       lcd.print(customKey);
       }  
       else if (c==4)
       {
        DataStr1=DataStr;
        DataStr.remove(c-3);
        DataStr1.remove(0,(c-3));
        DataStr+="." + DataStr1;
        lcd.setCursor(0,1);
        lcd.print("Jml:Rp.");
        lcd.print(DataStr);
        }
        else if ((c>4)&&(c<=6))
        {
        DataStr1=DataStr;
        DataStr.remove(c-3);
        DataStr1.remove(0,(c-3));
        DataStr+="." + DataStr1;
        lcd.setCursor(0,1);
        lcd.print("Jml:Rp.");
        lcd.print(DataStr);
        }
        else if (c>6)
        {
        DataStr1=DataStr;
        DataStr.remove(c-3);
        DataStr1.remove(0,(c-3));
        DataStr+="." + DataStr1;
        DataStr1=DataStr;
        DataStr.remove((c-6));
        DataStr1.remove(0,(c-6));
        DataStr+="." + DataStr1;
        lcd.setCursor(0,1);
        lcd.print("Jml:Rp.");
        lcd.print(DataStr);
        }
    }
    }

这个草图被称为子程序(void TulisanDesimaBeli)

if ((customKey<='9')&&(customKey>='0'))
    { 
      DataStr+=customKey;
      TulisanDesimalBeli(customKey,DataStr);
      a=(int)customKey&0x0F;
      HarBel=HarBel*10;
      HarBel=HarBel+a;
     }

对不起,我的英语最差,你可以看https://youtu.be/baYdiqqfr3c分钟1.30

或访问我的网站http://www.radixrobotic.id/project/arduino-tiket-printer-epson-tm-u220/

独立。