Как отформатировать длинный разделитель тысяч на Arduino - PullRequest
4 голосов
/ 18 августа 2011

Я разрабатываю проект на Arduino, который анализирует некоторые данные JSON из удаленного веб-API и отображает их на ЖК-дисплее 16x2.

Я хотел бы отформатировать длинный анализ с помощью TextFinder добавление разделителя тысяч (хорошо бы использовать разделитель запятых).

В двух словах, как мне кодировать функцию formatLong?

long longToBeFormatted = 32432423;

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

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

Ответы [ 4 ]

4 голосов
/ 18 августа 2011

Я не уверен, какой набор инструментов используется в 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;
}
2 голосов
/ 18 августа 2011

Возможно, не лучший алгоритм, но вот пример реализации (стандарт 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;
}
0 голосов
/ 30 марта 2019

может быть, может помочь вам .. я использую этот эскиз, чтобы сделать разделитель тысяч на 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/

regrad.

0 голосов
/ 18 августа 2011

Вы можете попробовать следующее:

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

Код - выстрел из бедра, но идея должна работать.

...