我想知道的是,如果我要求用户输入一些内容,如果输入是整数、字符串或浮点值,我将如何输出。我想要一些方法来检查 C++14 中输入的数据类型。
例如。
如果输入是“Hello world”
输出应该是:“输入是字符串”
如果输入的是“134”
输出应该是:“输入是整数”
如果输入是“133.23”
输出应该是:“输入是浮点数”
读取字符串。
在
<string>
中,标准库提供了一组函数,用于从字符串或 wstring 中的字符表示中提取数值。
使用
x=stoi(s,p)
。检查 p
- 如果读取整个字符串 - 它是整数。
使用
x=stof(s,p)
或 x=stod(s,p)
、x=stold(s,p)
执行相同操作以检查 float/double/long double。
如果一切都失败 - 它是字符串。
用户总是会输入一个字符串,你能做的就是尝试将其转换为浮点数,如果成功则可能是浮点数或整数。 如果浮点转换不成功,那么它可能不是一个数字。
#include <iostream>
#include <string>
#include <boost/variant.hpp>
#include <sstream>
using myvariant = boost::variant<int, float, std::string>;
struct emit : boost::static_visitor<void>
{
void operator()(int i) const {
std::cout << "It's an int: " << i << '\n';
}
void operator()(float f) const {
std::cout << "It's a float: " << f << '\n';
}
void operator()(std::string const& s) const {
std::cout << "It's a string: " << s << '\n';
}
};
auto parse(const std::string& s) -> myvariant
{
char* p = nullptr;
auto i = std::strtol(s.data(), &p, 10);
if (p == s.data() + s.size())
return int(i);
auto f = std::strtof(s.data(), &p);
if (p == s.data() + s.size())
return f;
return s;
}
void test(const std::string& s)
{
auto val = parse(s);
boost::apply_visitor(emit(), val);
}
int main()
{
test("Hello world");
test("134");
test("133.23");
}
预期输出:
It's a string: Hello world
It's an int: 134
It's a float: 133.23
输入是字符串。如果没有额外的协议,你怎么可能知道用户想要“1”是包含字符“1”的字符串还是整数 1 的字符串表示形式?
如果你决定“如果它可以被解释为 int,那么它就是 int。如果它可以是 double,那么它就是 double。否则它就是 string”,那么你可以进行一系列转换,直到一个有效,或者进行一些格式检查,也许使用正则表达式。
由于所有整数都可以转换为双精度数,并且双精度数的字符串表示形式也可以转换为整数(可能还剩下一些垃圾),如果您关心差异,您可能需要检查它是双精度数的指示符(带有也许是一个 .,可能是一个“e”,后面可能有 +/-。等等。您可以在互联网上找到正则表达式,具体取决于您想要允许的内容,前导 +、电子符号等。
如果是 int,则可以使用正则表达式 ^\d+$,否则如果是 double,则 [+-]?(?:0|[1-9]\d*)(?:.\d*)?( ?:[eE][+-]?\d+)?否则它是一个字符串。
这里有一些似乎有效的代码。 :)
#include <iostream>
#include <string>
#include <regex>
using namespace std;
void handleDouble(double d) {
std::cout << "Double = " << d << "\n";
}
void handleInt(int i) {
std::cout << "Int = " << i << "\n";
}
void handleString(std::string const & s) {
std::cout << "String = " << s << "\n";
}
void parse(std::string const& input) {
static const std::regex doubleRegex{ R"([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)" };
static const std::regex intRegex{ R"(\d+)"};
if (std::regex_match(input, intRegex)){
istringstream inputStream(input);
int i;
inputStream >> i;
handleInt(i);
}
else if (std::regex_match(input, doubleRegex)) {
istringstream inputStream(input);
double d;
inputStream >> d;
handleDouble(d);
}
else {
handleString(input);
}
}
int main()
{
parse("+4.234e10");
parse("1");
parse("1.0");
parse("123abc");
}
输出:
Double = 4.234e+10
Int = 1
Double = 1
String = 123abc
您可以轻松地将
string.strof
换成 float
或 string.stroi
换成 int
在 try-catch 块中:
#include <string>
bool isFloat(string str) {
try {
float floatCheck = stof(str);
return true;
}
catch (...) {
return false;
}
}
bool isInt(string str) {
try {
int intCheck = stoi(str);
return true;
}
catch (...) {
return false;
}
}
我没有答案,但我无法将其放入评论中 - 我担心涉及“尝试使用 stoi()”的建议:如果你没有整数,那么 stoi() 会抛出一个例外。突然间,您进入了异常处理领域,这种逻辑方法有问题(您不想将异常处理用作逻辑),并且可能会显着减慢速度。请参阅下面的代码以了解如何触发异常。
在我看来,基于解析文本的解决方案更合适。
#include <string>
#include <iostream>
// compile and run with:
// g++ -Wall test_stoi.cpp
// ./a.out
// output should look like:
// terminate called after throwing an instance of 'std::invalid_argument'
// what(): stoi
using namespace std;
int main()
{
string s = "dude";
size_t pos;
int x = stoi(s, &pos);
cout << "x,pos: " << x << " " << pos << "\n";
}
脚注:C++“官方”常见问题解答明确指出:
不要使用异常作为从函数返回值的另一种简单方式。大多数用户假设——正如语言定义所鼓励的那样——**异常处理代码是错误处理代码**,并且实现被优化以反映该假设。