Преобразуем целые числа в строки с C++
newbie
Опубликован: | 2019-06-16T07:14:11.656383Z |
Отредактирован: | 2019-07-12T15:56:59.317176Z |
В предыдущем выпуске блога я продемонстрировал один из возможных вариантов преобразования содержащих только цифры строк в целые числа с использованием стандартных процедур. Мне интересно рассмотреть процесс обратного преобразования без использования соответствующих функций стандартной библиотеки. Об этом и пойдёт речь далее...
Условия задачи следующие:
Дано целое число - 54709879023, необходимо написать программу, которая выведет на экран монитора само число, а затем с новой строки каждую цифру числа в порядке следования через пробел. По условиям задачи не допускается преобразование числа в строку с помощью соответствующей функции стандартной библиотеки.
В сущности, для решения этой задачи не обязательно преобразовывать число в строку. Но поскольку мне интересен процесс преобразования, я представлю слегка избыточное решение задачи. Решать задачу я буду как обычно на базе операционной системы Debian buster. Запускаю Geany и создаю новый файл, в котором будет храниться исходный код программы.
cd ~/workspace geany fromint.cpp &
Для решения задачи мне потребуются три модуля стандартной библиотеки.
#include <iostream> #include <string> #include <cmath>
Чтобы вывести на экран каждую цифру, составляющую заданное целое число, мне необходимо определить количество разрядов в числе. Для решения этой микрозадачи я разработаю функцию find_o.
int find_o(const unsigned long n);
Функция find_o принимает в качестве аргумента заданное целое, и возвращает целое int, выражающее разрядность заданного числа, то есть количество знаков в числе.
Для преобразования числа в строку я разработаю функцию conv_n.
std::string conv_n(const unsigned long n);
В данном случае я передаю функции conv_n в качестве аргумента заданное целое число, в результате преобразования conv_n должна вернуть строку.
Начнём с расчёта разрядности.
int main() { unsigned long num = 54709879023UL; std::cout << num << std::endl; int order = find_o(num); std::cout << order << std::endl; return 0; }
Чтобы посчитать количество знаков в целом числе, достаточно посчитать количество шагов в простом цикле и добавить к нему единицу.
int find_o(const unsigned long n) { using std::pow; int order = 0; while (!(n / pow(10, order) >= 1 and n / pow(10, order) <=9)) order += 1; return order + 1; }
Пишу код в файл и сохраняю его.
Пробую скомпилировать полученную программу и исполнить её.
g++ fromint.cpp -o exe ./exe
Отлично, программа вывела на экран терминала само заданное число и его разрядность. Имея разрядность числа, его достаточно просто преобразовать в строку, для этого я создам пустую строку.
using std::pow; using std::string; string r = "";
Для преобразования числа в строку мне потребуется эталонная строка, содержащая все цифры от нуля до девяти.
const string digits = "0123456789";
Имея функцию find_o я могу определить разрядность заданного целого числа.
int order = find_o(n);
Преобразование числа в строку будет выполнено простым циклом путём конкатенации полученных в теле цикла строк, найденных по вычисленному индексу на каждом шаге цикла.
for (int i = order; i > 0; i--) { unsigned long k = pow(10, i); r += digits[(n - n / k * k) / pow(10, i - 1)]; }
Записываю этот код в тело функции conv_n.
Теперь нужно слегка изменить код функции main для решения основной задачи.
int main() { unsigned long num = 54709879023UL; std::cout << num << std::endl; int order = find_o(num); std::string str = conv_n(num); for (int i = 0; i < order; i++) std::cout << str[i] << ' '; std::cout << std::endl; return 0; }
Компилирую программу и пробую её исполнить.
g++ fromint.cpp -o exe ./exe
Задача решена. Как видно, процесс преобразования целых чисел в строки достаточно прост и предполагает рутинное выполнение повторяющихся элементарных действий с заданным числом. В следующем выпуске блога я сосредоточу своё внимание на ещё одной типовой для программистов задаче, а именно, покажу простую сортировку массива целых чисел по возрастанию значений.
Updated later: оптимизация предложенного решения рассмотрена в другом топике блога - Ещё раз о рефакторинге и оптимизации кода.
Код программы целиком:
#include <iostream> #include <string> #include <cmath> int find_o(const unsigned long n); std::string conv_n(const unsigned long n); int main() { unsigned long num = 54709879023UL; std::cout << num << std::endl; int order = find_o(num); std::string str = conv_n(num); for (int i = 0; i < order; i++) std::cout << str[i] << ' '; std::cout << std::endl; return 0; } std::string conv_n(const unsigned long n) { using std::pow; using std::string; string r = ""; const string digits = "0123456789"; int order = find_o(n); for (int i = order; i > 0; i--) { unsigned long k = pow(10, i); r += digits[(n - n / k * k) / pow(10, i - 1)]; } return r; } int find_o(const unsigned long n) { using std::pow; int order = 0; while (!(n / pow(10, order) >= 1 and n / pow(10, order) <=9)) order += 1; return order + 1; }