Как преобразовать int в серию символов - PullRequest
2 голосов
/ 14 июля 2011

Я пытаюсь разбить целое число с C на 8-разрядном микроконтроллере (PIC) на эквивалентные ему символы ASCII.

Например: преобразовать 982 в '9', '8','2'

Все, что я до сих пор придумал, кажется довольно грубой силой.Это основная идея того, что я в основном делаю сейчас:

if( (10 <= n) && (n < 100) ) {
// isolate and update the first order of magnitude
digit_0 = (n % 10);
// isolate and update the second order of magnitude
switch( n - (n % 10) ) {
  case 0:
    digit_1 = 0;
    break;
  case 10:
    digit_1 = 1;
    break;

...

И затем у меня есть другая функция, чтобы просто добавить 0b00110000 (48decimal) к каждому из моихцифры.

У меня возникли проблемы с поиском какой-либо функции C, которая бы делала это для меня или делала это хорошо сама.

Заранее благодарим за любую помощь!

Ответы [ 4 ]

4 голосов
/ 14 июля 2011

Если sprintf по какой-то причине не подходит, подойдет что-то простое:

char digits[MAX_DIGITS];
int count = 0;
do {
    digits[count++] = n % 10;
    n /= 10;
} while (n > 0);

Там будет count цифр, причем digits[0] будет наименее значимым.

1 голос
/ 14 июля 2011

Я давно отвечал на такой вопрос.

Реализация ftoa

Надеюсь, это поможет.Это относится как к целым числам, так и к числам с плавающей запятой.Концепция проста.

  1. Определить количество цифр (для базы 10 вы используете базу 10 журналов)
  2. Получить цифру msb, взяв слово (num / digit_weight)
  3. Вычесть цифру * вес из числа и уменьшить вес на 1
  4. Повторять до числа == 0 для целых чисел или num> 0 + допуск для чисел fp

Поскольку алгоритм обрабатывает цифру при каждой итерации, его время O (logn), так что это вполне разумно.

1 голос
/ 14 июля 2011

Если вы совместимы с PIC16 RISC ассемблером, то это очень просто, быстро, коротко и эффективно. Здесь у вас есть 16-битное беззнаковое 16-битное деление на 10 рутин, чтобы увидеть, как это сделать.

Чтобы получить первый младший символ числа в WREG, поместите 16-битное число без знака в Reg1 и Reg2 и вызовите рутину. Чтобы получить следующий символ, снова вызовите рутин и так далее, пока Reg1 и Reg2 не станут равны 0.

RegAE       res 1
RegA0       res 1
RegA1       res 1
RegA2       res 1



    divR16by_c10
    ;{
    ;//Input: 16 bit unsigned number as RegA1,2 (RegA2 low byte, RegA1 High byte)
    ;//Division result: Reg1 and Reg2 and reminder as char in WREG
            clrf    RegA0
            movlw   16             ;//init loop counter
            movwf   RegAE
            lslf    RegA2, f
    divI16by_c10_        
            rlf     RegA1, f
            rlf     RegA0, f       
            movlw   10
            subwf   RegA0, f
            btfsc   Carry
            bra     divI16by_c10_OK
            addwfc  RegA0, f
            bcf     Carry
    divI16by_c10_OK        
            rlf     RegA2, f
            decfsz  RegAE, f
            bra     divI16by_c10_
    ;//result= W from 0..9
            addlw   0x30        ;//convert to char
            return 
    ;}

EDIT:

Если вы хотите преобразовать значение со знаком 16 бит, то сначала проверьте 15-й бит, чтобы определить номер знака. Если отрицательный, чем написать - подпишите и отрицайте число в RegA1,2. После этого процедура та же для положительного числа. Для отрицания числа вы можете использовать следующую asm rutine:

             comf    RegA2, f
             comf    RegA1, f
             movlw   0
             bsf     STATUS, 0      ;//set carry flag
             addwfc  RegA2, f
             addwfc  RegA1, f 
1 голос
/ 14 июля 2011

Чтобы сделать это самостоятельно, вам нужно выполнить операции, которые демонстрируются с помощью приведенного ниже примера кода:

#include <stdio.h>

int main (void)
{
  unsigned int x = 512;
  int base_val = 10, digit, i = 0, n = 0;
  char x_str[32], t;

  printf ("\nEnter an unsigned number: ");
  scanf ("%u", &x);

  printf ("\nEnter base: ");
  scanf ("%d", &base_val);

  /* Chop the digits in reverse order and store in `x_arr`
   * the interpretation of the digits are made in base value
   * denoted by `base_val`
   */

  while (x)
  {
    digit = x % base_val;
    x /= base_val;
    if (digit < 10)
      x_str[n++] = digit + '0';
    else
      x_str[n++] = digit + 'A' - 10;  /* handle base > 9 */
  }

  /* Terminate string */
  x_str[n] = '\0';

  /* Reverse string */
  for (i=0; i<n/2; i++)
  {
    t = x_str[i];
    x_str[i] = x_str[n-i-1];
    x_str[n-i-1] = t;
  }
  printf ("\n%s\n", x_str);

  return 0;
}

Цикл while будет отбирать цифры из целого числа в заданной базе и подавать цифры в обратном порядке в массиве. Внутренний if - else обрабатывает основание больше 9 и помещает прописные алфавиты, когда значение цифры больше 10. Цикл for переворачивает строку и возвращает прерванное число в строку в прямом порядке.

Вам необходимо настроить размер массива x_str в соответствии с вашими максимальными возможностями. Определите макрос для него. Обратите внимание, что приведенный выше код предназначен только для целых чисел без знака. Для целых чисел со знаком вам нужно сначала проверить, что оно меньше 0, затем добавить знак «-» в x_str и затем вывести величину т.е. примените приведенный выше код с -x. Это также можно сделать, проверив бит знака, маскируя, но сделав процесс зависимым от хранения целого числа.

base_val - это база, в которой вы хотите интерпретировать числа.

...