Функция itoa в C++: из числа в строку

Привет! В данном уроке мы поговорим о полезной C++ функции itoa. Данная функция позволяет нам конвертировать число в строку. Начнем мы с примера использования данной функции, после чего попробуем реализовать данную функцию самостоятельно. В конце статьи вы найдете упражнения, которые помогут вам закрепить изученный материал.

itoa - это сокращение от “Int TO Ascii“.

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

Иллюстрация itoa в C++

Как сконвертировать число в строку

Чтобы сконвертировать число в строку можно воспользоваться функцией itoa. Данная функция имеет следующий вид:

char *  itoa ( int value, char * str, int base );
  • Первым аргументом функция принимает число, которое мы хотим сконвертировать в строку.
  • Вторым аргументом нужно передать указатель на массив символов, в который будет записан результат конвертации.
  • Третьим аргументом мы указываем основание, которое нужно использовать при конвертации. Например, если нам нужно число в привычной десятеричной системе, то нужно передать 10. Если же мы хотим получить строку в двоичной системе, то нужно передать 2.
  • Функция возвращает указатель на строку, в которую был записан результат конвертации (второй аргумент: buffer).

Теперь давайте попробуем сконвертировать несколько чисел, чтобы лучше понять как работает itoa:

#include <iostream>
using namespace std;

int main() {
  // объявляем массив символов, в который мы будем записывать результат
  // конвертации чисел
  char buffer[33];

  cout << "itoa(123, buffer, 10) = " << itoa(123, buffer, 10) << endl;
  cout << "itoa(-321, buffer, 10) = " << itoa(-321, buffer, 10) << endl;
  cout << "itoa(6, buffer, 2) = " << itoa(6, buffer, 2) << endl;
  cout << "itoa(123, buffer, 7) = " << itoa(123, buffer, 7) << endl;
  cout << "itoa(11184810, buffer, 16) = " << itoa(11184810, buffer, 16) << endl;

  return 0;
}

Вывод данной программы:

itoa(123, buffer, 10) = 123
itoa(-321, buffer, 10) = -321
itoa(6, buffer, 2) = 110
itoa(123, buffer, 7) = 234
itoa(11184810, buffer, 16) = AAAAAA

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

Буфер для хранения строки имеет размер 33. Такое количество элементов выбрано, потому что это максимальное количество символов, которое может потребоваться для числа int в двоичной системе после конвертации (32 бита) + символ \0 для окончания строки.

itoa добавляет знак - только для отрицательных чисел в десятеричной системе. Для двоичных чисел результат для отрицательного числа не будет отличаться от положительного.

Что будет выведено на экран:

char buffer[33];
cout << itoa(-6, buffer, 2) << endl;
-110
110
-6
6

Как реализовать itoa самому

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

#include <iostream>
using namespace std;

// вспомогательная функция, которая разворачивает массив
char* reverse(char* buffer, int i, int j) {
  while (i < j) {
    char t = buffer[i];
    buffer[i++] = buffer[j];
    buffer[j--] = t;
  }

  return buffer;
}

// сама функция itoa
char* itoa(int value, char* buffer, int base) {
  // мы поддерживаем только основания от 2 до 32
  if (base < 2 || base > 32) return NULL;

  // абсолютное значение числа
  int n = abs(value);
  int i = 0;

  // вычисляем цифры числа с конца, пока число не равно нулю
  do {
    // вычисляем очередную цифру в нужной степени
    int r = n % base;
    // записываем символ, который соответствует текущей цифре
    buffer[i++] = (r < 10) ? (r + '0') : (r - 10 + 'A');
    // переходим к следующему числу
    n /= base;
  } while (n);

  // для отрицательных чисел в десятеричной системе
  // нужно добавить минус
  if (value < 0 && base == 10) buffer[i++] = '-';
  buffer[i] = '\0';

  // поскольку мы вычисляли цифры с конца, нужно перевернуть массив
  return reverse(buffer, 0, i - 1);
}

int main() {
  char buffer[33];

  cout << "itoa(123, buffer, 10) = " << itoa(123, buffer, 10) << endl;
  cout << "itoa(-321, buffer, 10) = " << itoa(-321, buffer, 10) << endl;
  cout << "itoa(6, buffer, 2) = " << itoa(6, buffer, 2) << endl;
  cout << "itoa(123, buffer, 7) = " << itoa(123, buffer, 7) << endl;
  cout << "itoa(11184810, buffer, 16) = " << itoa(11184810, buffer, 16) << endl;

  return 0;
}

И вывод программы:

itoa(123, buffer, 10) = 123
itoa(-321, buffer, 10) = -321
itoa(6, buffer, 2) = 110
itoa(123, buffer, 7) = 234
itoa(11184810, buffer, 16) = AAAAAA

Как видите, наша функция работает аналогично встроенной itoa.

Упражнения

  1. Использование itoa:
    Напишите программу на C++, которая запрашивает у пользователя целое число, его основание и конвертирует это число в строку, используя функцию itoa. Ваша программа должна также выводить исходное число пользователя и результат конвертации.

  2. Своей версия itoa:
    Напишите свою версию функции itoa. Ваша функция должна принимать три параметра: целое значение, указатель на строку и основание. Функция должна конвертировать число в строку с учетом указанного основания и возвращать указатель на строку. Проверьте работу вашей функции, используя различные числа и основания.

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

Обсуждение