11.6. Преобразование строк с в числа
Строка С "1234" и число 1234 — это не одно и то же. Первое выражение представляет собой последовательность символов, а второе — число. В жизни мы записываем их одинаково и не думаем о различии, но в программе, созданной на языке C++, это различие нельзя игнорировать. Если вы собираетесь выполнять над числом арифметические операции, вам требуется именно число, а не строка, то есть 1234, а не "1234". Если же вам нужно добавить запятую, чтобы отделить тысячи от сотен, тогда требуется строка "1234", которую можно превратить в "1.234". Когда программа должна вводить числа, часто удобнее считывать их как строки символов, редактировать в таком виде и затем преобразовывать в числа. Скажем, если программа должна прочитать значение денежной суммы, пользователь может ввести перед ним символ доллара, а может и не вводить, а когда программа считывает процентное значение, можно поставить в конце знак процента, а можно и не ставить. Программе эти знаки не нужны. Поэтому она может прочитать введенное значение как строку символов, сохранить его в строковой переменной С и удалить ненужные символы, оставив только цифры. После этого строку нужно будет преобразовать в число, что очень легко выполнить с помощью стандартной функции atoi.
Эта функция принимает один аргумент — строку С — и возвращает значение типа int, соответствующее представленному этой строкой числу. Так, atoi ("1234") возвращает число 1234. Если строка не содержит числа, функция возвращает 0. Например, ("#37") возвращает 0, поскольку значение аргумента ("#37") не является цифрой. Название этой функции представляет собой сокращение от англ. alphabetic to integer (произносится как «эй-ту-ай»). Функция atoi определена в библиотеке с заголовочным файлом <cstdlib>, так что любая программа, в которой она используется, должна содержать следующую директиву:
#include <cstdlib>
Если число слишком велико для преобразования его к типу данных int, можно преобразовать строку в значение типа long. Это выполняет функция atol, точно такая же, как atoi, и отличающаяся от нее лишь типом возвращаемого значения.
В листинге 14.1 приведено определение функции readandclean, считывающей введенную пользователем строку и удаляющей из нее все символы, кроме цифр от ' 0' до ' 9'. С помощью функции atoi она преобразует «очищенную» строку в целочисленное значение. Как показывает демонстрационная программа, функцию readandclean можно использовать для ввода значений денежных сумм независимо от того, добавит ли пользователь символ доллара. Точно так же с ее помощью можно вводить процентные значения независимо от наличия знака процента. Посмотрев на выходные данные, можно подумать, что функция просто удаляет из входной строки некоторые символы, но на самом деле она делает больше: формирует значение типа int, которым можно пользоваться в программе как числом, а не как строкой символов.
Листинг 11.1. Преобразование строки С в целое число
// Демонстрирует функцию read_and_clean.
#iinclude <iostream>
#include <cstdlib>
#include <cctype>
void read_and_clean(int& n);
// Считывает входную строку. Удаляет все символы, кроме цифр.
// Преобразует полученную строку С в число и записывает
// его в параметр n.
void new_line();
// Удаляет из входного потока все символы до конца текущей строки.
// Удаляет также символ '\n' в конце строки.
int main()
{
using namespace std;
int n;
char ans;
do
{
cout << "Enter an integer and press Enter: ";
read_and_clean(n);
cout << "That string converts to the integer " << n <<endl;
cout << "Again? (yes/no): ";
cin >> ans;
new_line(); }
while ( (ans != 'n') && (ans != 'N') );
return 0; }
// Используем библиотеки классов iostream, cstdlib и cctype.
void read_and_clean(int& n)
{
using namespace std;
const int ARRAY_SIZE = 6;
char digit_string[ARRAY_SIZE];
char next;
cin.get(next);
int index =0;
while (next != '\n')
{
if ( (isdigit(next)) && (index < ARRAY_SIZE - 1) )
{
digit_string[index] = next;
index++;
}
cin.get(next);
}
digit_string[index] = '\0';
n = atoi(digitstring);
}
// Используем библиотеку классов iostream.
void newline()
{
using namespace std:
char symbol;
do
{
cin.get(symbol);
}while(symbol!= '\n');
}
Пример диалога
Enter an integer and press Enter: $ 100
That string converts to the integer 100
Again? (yes/no): yes
Enter an integer and press Enter: 100
That string converts to the integer 100
Again? (yes/no): yes
Enter an integer and press Enter: 99*
That string converts to the integer 99
Again? (yes/no): yes
Enter an integer and pfess Enter: 23% &&5 *12
That string converts to the integer 23512
Again? (yes/no): no
Функция read_and_clean, приведенная в листинге 14.1, удаляет из введенной пользователем строки все нецифровые символы, но она не может проверить, соответствует ли оставшаяся последовательность символов тому числу, которое хотел ввести пользователь. Нужно предоставить ему возможность посмотреть на результат преобразования и подтвердить, что все сделано правильно. Если получено неверное значение, пользователь должен иметь возможность повторить ввод. В листинге 14.2 функция read_and_clean вызывается из другой функции, называющейся get_int, которая принимает все данные, введенные пользователем, и позволяет ему повторять ввод, пока он не будет удовлетворен числом, полученным из введенной им строки. Это довольно надежная процедура ввода. Функции read_and_clean из листинга 14.1 и get_int из листинга 14.2 являются примерами пользовательских функций для ввода целых числовых значений. Есть и стандартная функция, преобразующая строковое значение в число типа double. Такая функция — atof и находится в той же библиотеке классов с заголовочным файлом cstdlib. Например, функция atof("9.99") возвращает значение 9.99 типа double. Если строка не содержит число, которое можно интерпретировать как значение типа double, то данная функция возвращает 0.0. Название функции представляет собой сокращение от англ. alphabetic to floating point (произносится как «эй-ту-эф»). Вспомните, что числа с десятичной точкой часто называют числами с плавающей запятой из-за особого способа их хранения в памяти компьютера.
Преобразование строки С в число
Функции atoi, atol и atof можно использовать для преобразования строки С, состоящей из цифр, в числовое значение. Первые две функции преобразуют строку С в целочисленное значение. Единственная разница между ними заключается в том, что atoi возвращает значение типа int, a atol — значение типа long. Третья функция — atof — преобразует строку С в значение типа doublе. Если строка С, переданная в качестве аргумента любой из этих функций, не может быть преобразована в число, то функция возвращает 0. Например, оператор
int х = atoi("657");
присваивает переменной X значение 657, а оператор
double у = atof("12.37");
присваивает переменной у значение 12.37.
Любая программа, использующая функцию atoi, atol или atof, должна содержать следующую директиву:
#include <cstdlib>
Листинг 11.2. Функция ввода с повышенной надежностью
#include <iostream>
#include <cstdlib>
#include <cctype>
void read_and_clean(int& n);
// Считывает входную строку. Удаляет все символы, кроме цифр. Преобразует
// результирующею строку С в число и записывает его в параметр п.
void newline();
// Удаляет из входного потока все символы до конца текущей строки.
// Удаляет также символ '\n' в конце строки.
void get_int(int& inputnumber);
// Присваивает параметру inputnumber число, правильность которого
// подтвердит пользователь.
int main()
{
using namespace std;
int inputnumber;
get_int(inputnumber);
cout <<"Final value read in = " <<input_number <<endl;
return 0; }
// Используем библиотеку классов iostream и функцию read_and_clean.
void get_int(int& inputnumber)
{
using namespace std;
char ans;
do
{
cout << "Enter input number: ";
read_and_clean(inputnumber);
cout << "You entered " << inputnumber << " Is that correct? (yes/no): ";
cin » ans;
newline(); }
while ((ans != 'y') && (ans != 'Y')); }
// Используем библиотеки классов iostream, cstdlib и cctype.
void read_and_clean(int& n)
{
... Определение функции read_and_clean приведено в листинге 14.1.
}
// Используем библиотеку классов iostream.
void newline()
{
... Определение функции newline приведено в листинге 14.1. ...
}
Пример диалога
Enter input number: $57
You entered 57 Is that correct? (yes/no): no
Enter input number: $77*5xa
You entered 775 Is that correct? (yes/no): no
Enter input number: 77
You entered 77 Is that correct? (yes/no): no
Enter input number: $75
You entered 75 Is that correct? (yes/no): yes
Final value read in = 75
