Проверьте тип переменной в C++
Вопрос
Итак, в настоящее время я изучаю C++ и решил создать программу, которая проверит мои навыки, которые я изучил на данный момент.Теперь в моем коде я хочу проверить, является ли значение, которое вводит пользователь, двойным. Если это не двойное значение, я поставлю цикл if и попрошу его ввести его повторно.У меня проблема в том, как мне проверить, какой тип переменной вводит пользователь, например, если пользователь вводит символ или строку, я могу вывести сообщение об ошибке.Вот мой код:
//cubes a user entered number
#include <iostream>
using namespace std;
double cube(double n); //function prototype
int main()
{
cout << "Enter the number you want to cube: "; //ask user to input number
double user;
cin >> user; //user entering the number
cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number
return 0;
}
double cube (double n) //function that cubes the number
{
return n*n*n; // cubing the number and returning it
}
Редактировать:Должен сказать, что я только начал и не имею ни малейшего представления о вашем коде, но я проверю вашу ссылку.Кстати, я еще не научился работать с шаблонами, учусь работе с данными только по главе 3 в моем C++ Primer Plus 5-го издания.
Решение
Нет подходящего способа проверить, содержит ли строка Действительно двойное значение в стандартной библиотеке. Вы, вероятно, хотите использовать Boost . Следующее решение основано на рецепте 3.3 в C ++ Cookbook :
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
double cube(double n);
int main()
{
while(true)
{
cout << "Enter the number you want to cube: ";
string user;
cin >> user;
try
{
// The following instruction tries to parse a double from the 'user' string.
// If the parsing fails, it raises an exception of type bad_lexical_cast.
// If an exception is raised within a try{ } block, the execution proceeds
// with one of the following catch() blocks
double d = lexical_cast <double> (user);
cout << "The cube of " << d << " is " << cube(d) << "." << endl;
break;
}
catch(bad_lexical_cast &e)
{
// This code is executed if the lexical_cast raised an exception; We
// put an error message and continue with the loop
cout << "The inserted string was not a valid double!" << endl;
}
}
return 0;
}
double cube (double n)
{
return n*n*n;
}
Другие советы
Безопасный способ C++
Вы можете определить функцию для этого, используя std::istringstream
:
#include <sstream>
bool is_double(std::string const& str) {
std::istringstream ss(str);
// always keep the scope of variables as close as possible. we see
// 'd' only within the following block.
{
double d;
ss >> d;
}
/* eat up trailing whitespace if there was a double read, and ensure
* there is no character left. the eof bit is set in the case that
* `std::ws` tried to read beyond the stream. */
return (ss && (ss >> std::ws).eof());
}
Чтобы помочь вам разобраться, что он делает (некоторые моменты упрощены):
- Создание потока входных строк, инициализированного заданной строкой
- Чтение из него двойного значения с помощью
operator>>
.Это означает пропуск пробелов и попытку прочитать двойное значение. - Если бы ни один двойной текст не мог быть прочитан, как в
abc
поток устанавливает неудача-кусочек.Обратите внимание, что такие случаи, как3abc
добьется успеха и будет нет установите бит отказа. - Если установлен бит отказа,
ss
принимает нулевое значение, что означает ЛОЖЬ. - Если был прочитан двойной символ, мы пропускаем конечные пробелы.Если мы находимся в конце потока (обратите внимание, что
eof()
вернется истинный если бы мы попытались прочитать дальше конца.std::ws
делает именно это),eof
вернет истину.Обратите внимание, что эта проверка гарантирует, что3abc
не пройдет нашу проверку. - Если в обоих случаях, справа и слева от
&&
оценить истинный, мы возвращаем true вызывающей стороне, сигнализируя, что данная строка является двойной.
Аналогично, вы проверяете int
и другие типы.Если вы умеете работать с шаблонами, вы знаете, как обобщить это и на другие типы.Кстати, именно это boost::lexical_cast
предоставляет вам.Проверьте это: http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm.
C, первый путь
Этот способ имеет преимущества (быстрый), но также и серьезные недостатки (нельзя обобщить с помощью шаблона, необходимо работать с необработанными указателями):
#include <cstdlib>
#include <cctype>
bool is_double(std::string const& s) {
char * endptr;
std::strtod(s.c_str(), &endptr);
if(endptr != s.c_str()) // skip trailing whitespace
while(std::isspace(*endptr)) endptr++;
return (endptr != s.c_str() && *endptr == '\0');
}
strtod
установит endptr
до последнего обработанного символа.В нашем случае это завершающий нулевой символ.Если преобразование не выполнялось, endptr устанавливается на значение строки, указанной в strtod
.
C Способ второй
Можно было бы подумать, что std::sscanf
делает свое дело.Но легко что-то уследить.Вот правильный способ сделать это:
#include <cstdio>
bool is_double(std::string const& s) {
int n;
double d;
return (std::sscanf(s.c_str(), "%lf %n", &d, &n) >= 1 &&
n == static_cast<int>(s.size()));
}
std::sscanf
вернет преобразованные элементы.Хотя стандарт указывает, что %n
не включен в этот подсчет, некоторые источники противоречат друг другу.Это лучшее, что можно сравнить >=
чтобы сделать это правильно (см. справочную страницу sscanf
). n
будет установлено количество обработанных символов.Его сравнивают с размером строки.Пространство между двумя спецификаторами формата учитывает необязательные конечные пробелы.
Заключение
Если вы новичок, прочтите std::stringstream
и сделайте это способом C++.Лучше не связываться с указателями, пока не освоитесь с общей концепцией C++.
sscanf может делать то, что вы хотите; возвращает количество правильно обработанных аргументов. Это должно помочь вам начать:
//cubes a user entered number
#include <iostream>
#include <cstdio>
using namespace std;
double cube(double n); //function prototype
int main()
{
cout << "Enter the number you want to cube: "; //ask user to input number
string user;
cin >> user; //user entering the number
// Convert the number to a double.
double value;
if(sscanf(user.c_str(), "%lf", &value) != 1)
{
cout << "Bad! " << user << " isn't a number!" << endl;
return 1;
}
cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number
return 0;
}
double cube (double n) //function that cubes the number
{
return n*n*n; // cubing the number and returning it
}
Другие методы, опубликованные в других ответах, имеют свои преимущества и недостатки. У этого есть проблемы с завершающими символами, и он не является "C ++" -y.
Я бы сказал, что я только начал и не имею ни малейшего понятия о вашем коде, но я проверю вашу ссылку. Кстати, я еще не научился работать с шаблонами, я учусь работать с данными, только глава 3 в моем C ++ Primer Plus 5-е издание.
Вы можете воспользоваться C и использовать strtod р>
Вы запрограммировали чтение строки и затем передаете ее функции, которая пытается преобразовать строку в double. Р>
bool is_double(const char* strIn, double& dblOut) {
char* lastConvert = NULL;
double d = strtod(strIn, &lastConvert);
if(lastConvert == strIn){
return false;
} else {
dblOut = d;
return true;
}
}