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

时间:2011-08-18 07:51:47

标签: c++ c formatting arduino long-integer

我正在开发一个关于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

4 个答案:

答案 0 :(得分:4)

我不确定在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;
}

答案 1 :(得分:1)

也许不是最佳算法,但这是一个实现示例(标准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;
}

答案 2 :(得分:0)

您可以尝试以下方法:

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();
}

代码是时髦的镜头,但这个想法应该有用。

答案 3 :(得分:0)

也许可以帮助您。 我用这个草图在arduino LCD上制作了数千个分隔符。

  int n;
  n = 0;
  char number[9];
  sscanf(buffer, " %8[0-9] %n", number, &n);
  if (n == 0) return fail; // no digits
  if (buf[n]) return fail; // junk after the digits
  if (strlen(buf) != 7) return fail; // not 7 digits
  Success();
}

此草图称为子例程(void TulisanDesimaBeli)

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//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);
        }
    }
    }

对不起,我的英语不好,您可以在https://youtu.be/baYdiqqfr3c分钟1.30观看

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

访问我的网站

升级。