Преобразовать целое число в строку без доступа к библиотекам

c string int type-conversion itoa

26880 просмотра

10 ответа

Я недавно прочитал пример вопроса о собеседовании:

Напишите функцию для преобразования целого числа в строку. Предположим, у вас нет доступа к библиотечным функциям, например, itoa () и т. Д.

Как бы вы пошли об этом?

Автор: Nick Sinas Источник Размещён: 12.11.2019 09:33

Ответы (10)


11 плюса

Решение

быстрый удар по нему: (отредактировано для обработки отрицательных чисел)

int n = INT_MIN;
char buffer[50];
int i = 0;

bool isNeg = n<0;

unsigned int n1 = isNeg ? -n : n;

while(n1!=0)
{
    buffer[i++] = n1%10+'0';
    n1=n1/10;
}

if(isNeg)
    buffer[i++] = '-';

buffer[i] = '\0';

for(int t = 0; t < i/2; t++)
{
    buffer[t] ^= buffer[i-t-1];
    buffer[i-t-1] ^= buffer[t];
    buffer[t] ^= buffer[i-t-1];
}

if(n == 0)
{
    buffer[0] = '0';
    buffer[1] = '\0';
}   

printf(buffer);
Автор: John Boker Размещён: 20.10.2010 09:17

7 плюса

Алгоритм легко увидеть на английском языке.

Дано целое число, например 123

  1. разделить на 10 => 123/10. Уступая, результат = 12 и остаток = 3

  2. добавьте 30h к 3 и добавьте стек (добавление 30h преобразует 3 в представление ASCII)

  3. повторите шаг 1, пока результат <10

  4. добавьте 30h к результату и сохраните в стеке

  5. стек содержит число в порядке | 1 | 2 | 3 | ...

Автор: dnbwise Размещён: 20.10.2010 10:01

6 плюса

Посмотрите в интернете реализацию itoa, и вы получите хорошие примеры. Вот один из них, избегая перевернуть строку в конце. Он опирается на статический буфер, поэтому будьте осторожны, если вы повторно используете его для других значений.

char* itoa(int val, int base){

    static char buf[32] = {0};

    int i = 30;

    for(; val && i ; --i, val /= base)

        buf[i] = "0123456789abcdef"[val % base];

    return &buf[i+1];

}
Автор: Benoit Thiery Размещён: 21.10.2010 01:11

1 плюс

Я хотел бы иметь в виду, что все символы в порядке возрастания в наборе символов ASCII и между ними нет других символов.

Я бы также использовал операторы /and %несколько раз.

То, как я получу память для строки, зависит от информации, которую вы не предоставили.

Автор: nategoose Размещён: 20.10.2010 09:14

1 плюс

Предполагая, что это в десятичном виде, то вот так:

   int num = ...;
   char res[MaxDigitCount];
   int len = 0;
   for(; num > 0; ++len)
   {
      res[len] = num%10+'0';
      num/=10; 
   }
   res[len] = 0; //null-terminating

   //now we need to reverse res
   for(int i = 0; i < len/2; ++i)
   {
       char c = res[i]; res[i] = res[len-i-1]; res[len-i-1] = c;
   }   
Автор: Armen Tsirunyan Размещён: 20.10.2010 09:15

1 плюс

Внедрение itoa()функции кажется легкой задачей, но на самом деле вам нужно позаботиться о многих аспектах, связанных с вашими потребностями. Я предполагаю, что в интервью вы должны будете рассказать некоторые подробности о вашем пути к решению, а не копировать решение, которое можно найти в Google ( http://en.wikipedia.org/wiki/Itoa )

Вот некоторые вопросы, которые вы можете задать себе или интервьюеру:

  • Где должна находиться строка (malloced? Передано пользователем? Static variable?)
  • Должен ли я поддерживать подписанные номера?
  • Должен ли я поддерживать с плавающей запятой?
  • Должен ли я поддерживать другие базы, а не 10?
  • Нужна ли нам проверка входных данных?
  • Выходная строка ограничена в длине?

И так далее.

Автор: eyalm Размещён: 20.10.2010 09:22

1 плюс

Преобразовать целое число в строку без доступа к библиотекам

Сначала преобразуйте младшую цифру в символ, а затем перейдите к более старшей цифре.


Обычно я сдвигаю результирующую строку на место, но рекурсия позволяет пропустить этот шаг с некоторым трудным кодом.

Использование neg_aв myitoa_helper()позволяет избежать неопределенного поведения с INT_MIN.

// Return character one past end of character digits.
static char *myitoa_helper(char *dest, int neg_a) {
  if (neg_a <= -10) {
    dest = myitoa_helper(dest, neg_a / 10);
  }
  *dest = (char) ('0' - neg_a % 10);
  return dest + 1;
}

char *myitoa(char *dest, int a) {
  if (a >= 0) {
    *myitoa_helper(dest, -a) = '\0';
  } else {
    *dest = '-';
    *myitoa_helper(dest + 1, a) = '\0';
  }
  return dest;
}

void myitoa_test(int a) {
  char s[100];
  memset(s, 'x', sizeof s);
  printf("%11d <%s>\n", a, myitoa(s, a));
}

Тестовый код и вывод

#include "limits.h"
#include "stdio.h"

int main(void) {
  const int a[] = {INT_MIN, INT_MIN + 1, -42, -1, 0, 1, 2, 9, 10, 99, 100,
      INT_MAX - 1, INT_MAX};
  for (unsigned i = 0; i < sizeof a / sizeof a[0]; i++) {
    myitoa_test(a[i]);
  }
  return 0;
}

-2147483648 <-2147483648>
-2147483647 <-2147483647>
        -42 <-42>
         -1 <-1>
          0 <0>
          1 <1>
          2 <2>
          9 <9>
         10 <10>
         99 <99>
        100 <100>
 2147483646 <2147483646>
 2147483647 <2147483647>
Автор: chux - Reinstate Monica Размещён: 20.03.2019 03:14

0 плюса

Вот простой подход, но я подозреваю, что если вы включите это как есть, не понимая и не перефразируя его, ваш учитель будет знать, что вы только что скопировали его из сети:

char *pru(unsigned x, char *eob)
{
    do { *--eob = x%10; } while (x/=10);
    return eob;
}

char *pri(int x, char *eob)
{
    eob = fmtu(x<0?-x:x, eob);
    if (x<0) *--eob='-';
    return eob;
}

Возможны различные улучшения, особенно если вы хотите эффективно поддерживать целочисленные размеры больше, чем слово intmax_t. Я оставлю это вам, чтобы выяснить, как эти функции предназначены для вызова.

Автор: R.. Размещён: 20.10.2010 09:43

0 плюса

Чуть дольше, чем решение:

static char*
itoa(int n, char s[])
{
    int i, sign;

    if ((sign = n) < 0)  
        n = -n;        

    i = 0;

    do 
    {      
        s[i++] = n % 10 + '0';  
    } while ((n /= 10) > 0);   

    if (sign < 0)
        s[i++] = '-';

    s[i] = '\0';
    reverse(s);

    return s;
} 

Задний ход:

int strlen(const char* str)
{
   int i = 0;
   while (str != '\0')
   {
       i++;
       str++;
   }

   return i;
}

static void
reverse(char s[])
{
    int i, j;
    char c;

    for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

И хотя решение давольно давно здесь есть несколько полезных функций для начинающих. Я надеюсь, что вы будете полезны.

Автор: 0xAX Размещён: 21.10.2010 01:19

0 плюса

Чем быстрее тем лучше?

unsigned int findDigits(long long x)
{
    int i = 1;
    while ((x /= 10) && ++i);
    return i;
}
// return the number of digits in x.
unsigned int digits(long long x)
{
    x < 0 ? x = -x : 0;
    return x < 10 ? 1 :
        x < 100 ? 2 :
        x < 1000 ? 3 :
        x < 10000 ? 4 :
        x < 100000 ? 5 :
        x < 1000000 ? 6 :
        x < 10000000 ? 7 :
        x < 100000000 ? 8 :
        x < 1000000000 ? 9 :
        x < 10000000000 ? 10 : findDigits(x);
}


char tochar(unsigned short from)
{
    return from == 0 ? '0' :
        from == 1 ? '1' : from == 1 ? '1' : from == 2 ? '2' :
        from == 3 ? '3' : from == 4 ? '4' : from == 5 ? '5' :
        from == 6 ? '6' : from == 7 ? '7' : from == 8 ? '8' :
        from == 9 ? '9' : '\0';
}

char * tostring(long long from)
{
    unsigned char negative = from < 0;
    unsigned int i = digits(from);
    char* to = (char*)calloc(1, i + negative);
    if (negative && (*to = '-') & (from = -from) & i++);
    *(to + i) = 0;
    while ((i>0+negative) && (*(to + (--i)) = tochar(((from) % 10))) | (from /= 10));
    return to;
}

Если вы хотите выполнить отладку, вы можете разбить условия (инструкции) на
строки кода внутри областей while {}.

Автор: X Stylish Размещён: 17.05.2018 10:46
Вопросы из категории :
32x32