C++ 如何在Arduino上格式化长分隔符

C++ 如何在Arduino上格式化长分隔符,c++,c,formatting,arduino,long-integer,C++,C,Formatting,Arduino,Long Integer,我正在Arduino上开发一个项目,它解析来自远程web API的一些JSON数据,并在16x2 LCD上显示这些数据 我想通过添加千位分隔符(逗号分隔符就可以了)来格式化一个长解析文件 简而言之,如何对formatLong函数进行编码 long longToBeFormatted = 32432423; formattedLong = formatLong(longToBeFormatted); //How to implement this? lcd.print(formattedLon

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

我想通过添加千位分隔符(逗号分隔符就可以了)来格式化一个长解析文件

简而言之,如何对
formatLong
函数进行编码

long longToBeFormatted = 32432423;

formattedLong = formatLong(longToBeFormatted); //How to implement this?

lcd.print(formattedLong) // formattedLong is a string

也许不是最好的算法,但下面是一个实现示例(标准C):


您可以尝试以下方法:

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();
}
std::字符串格式长(长l){
整数幂=0;
而(l/(pow(1000,power)){power+=1;}
功率-=1;
std::strings;
while(电源){

s我不确定Arduino上使用了什么工具集。有时库将支持非标准的“千人分组”标志-单引号字符是典型的扩展:

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;
}
#包括
#包括
#包括
#包括
#包括
大小strlcpy(char*dest,char const*src,size\t dest\u size);
大小\u t格式\u长(长x,字符*buf,大小\u t bufsize)
{
//此代码假定为32位长,是
//关于Arduino的案例?修改它以便能够
//处理64位长(或不关心)应该是
//如果有必要的话,非常简单。
字符划痕[sizeof(“-2147483648”);
char*p=scratch+sizeof(scratch);//从缓冲区末尾开始工作
int-neg=(x<0);
//处理一些特殊情况
如果(x==0){
返回strlcpy(buf,“0”,bufsize);
}
如果(x==INT\u MIN){
//处理这种特殊情况的懒散方法
返回strlcpy(buf,“-2147483648”,bufsize);
}
//从现在开始用积极的价值观工作
如果(x<0)x=-x;
int group_计数器=3;
*(-p)=0;//Null终止暂存缓冲区
而(x!=0){
整数位数=x%10;
x=x/10;
断言(p!=&scratch[0]);
*(-p)=“0123456789”[位数];
如果((x!=0)和(-group_计数器==0)){
断言(p!=&scratch[0]);
*(-p)=',';
组计数器=3;
}
}
如果(负){
断言(p!=&scratch[0]);
*(-p)='-';
}
返回strlcpy(buf、p、bufsize);
}
/*
帮助复制字符串的非最佳strlcpy()实现
没有缓冲区溢出的危险。
这只是在您没有实现的情况下提供的
因此,上面的代码将实际编译并运行。
*/
大小strlcpy(char*dest,char const*src,size\t dest\u size)
{
尺寸长度=标准长度(src);
如果(目标大小==0){
//无需复制-只需返回缓冲区的长度
//(请注意,返回值不包括null终止符)
回程透镜;
}
size\u t tocopy=(dest\u size也许可以帮助您。。
我用这个草图在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);
        }
    }
    }
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//TULISAN DENGAN SPARATOR BELI BBM
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
void TulisanDesimalBeli(字符customKey,字符串DataStr)
{
c=DataStr.length();

如果(cIf)有人提供了更短/更快的算法,请发布!我已经尝试过了,它似乎在某种程度上起作用。我在最后一个数字上有问题;通过函数打印15195会返回15,19ç,其中最后一个字符肯定是假的。在x86中工作正常。您可以尝试替代
final[final_pos-->=buffer[buff_pos-->]
带有一个memcpy()…谢谢你的帮助。分组不起作用,我也用gcc 4.0在我的Mac电脑上本地试用了,但没有成功,你知道关于该标志的任何文档吗?。
format_long
函数工作得很好,无需使用
strlcpy
本地函数。Arduino上的long类型为32位,因此你的函数非常适合。1 m还有一个问题:
format\u long
函数为什么需要一个
bufsize
参数?我非常喜欢让调用者指定缓冲区大小,这样函数就可以避免缓冲区结束时溢出(这就是为什么我使用
strlcpy()
)。另一种方法是让函数动态分配所需大小的缓冲区,并将其返回给调用者。但在涉及arduino等小型设备的项目中,动态内存通常是不可接受的。当然,这实际上取决于特定项目的要求。数千分组标志是mentio当然,您的arduino目标可能没有完整的
libc
实现。
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//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);
        }
    }
    }
if ((customKey<='9')&&(customKey>='0'))
    { 
      DataStr+=customKey;
      TulisanDesimalBeli(customKey,DataStr);
      a=(int)customKey&0x0F;
      HarBel=HarBel*10;
      HarBel=HarBel+a;
     }