C++是一种语言静态地键入。这意味着所有类型都应该在编译期间确定:运行程序时不能引入新类型。
- 创建一个 void 类型向量(显然不允许,因为我已经研究过它了,哎呀)
void
实际上是一个相当奇怪的类型,主要是当您期望一个类型(如函数返回类型)但没有提供任何类型时的占位符。void*
用作指向未知类型的指针(主要在 C 中),但这完全是一个 hack,因为有关原始类型的信息被丢弃(就语言而言),因此这会导致实际使用该值执行操作时出现问题,因此获得。
不幸的是,这两种情况都不可能:因为你不能声明没有类型的变量,那么变量的类型是什么?firstElement
首先?
你所描述的问题总体来说是比较困难的。基本上,这意味着您必须接受一串字符,然后编写一组规则来确定如何解释这些字符。这通常是通过使用grammar对这些规则进行编码;但对于可能很简单的任务来说,语法可能会变得复杂。
让我举一个小例子:
class Input {
public:
enum Type {
Int,
Double,
String
};
static Input Parse(std::string const& s);
Input(): _type(Int), _int(0), _double(0.0) {} // need to define a default...
Type type() const { return _type; }
int asInt() const {
assert(_type == Int && "not an int");
return _int;
}
double asDouble() const {
assert(_type == Double && "not a double");
return _double;
}
std::string const& asString() const {
assert(_type == String && "not a string");
return _string;
}
private:
Type _type;
int _int;
double _double;
std::string _string;
};
显然,真正的挑战是正确地Parse
输入。
这个想法是使用一组规则,例如:
- an
int
仅由数字组成,可选地带有前缀-
- a
double
完全由数字组成,最多有一个.
并可选地加上前缀-
- a
string
可以是任何东西,因此是我们的包罗万象
然后我们就可以写识别部分了Parse
method:
static bool isInt(std::string const& s) {
if (s.empty()) { return false; }
// The first character may be among digits and '-'
char const first = s.at(0);
if (not isdigit(first) and first != '-') { return false; }
// Subsequent characters may only be digits
for (char c: s.substr(1)) {
if (not isdigit(c)) { return false; }
}
// Looks like it is an int :)
return true;
} // isInt
// Note: any int could be interpreted as a double too
static bool maybeDouble(std::string const& s) {
if (s.empty()) { return false; }
// The first character may be among digits, '.' and '-'
char const first = s.at(0);
if (not isdigit(first) and first != '.' and first != '-') { return false; }
// There may only be one dot
bool hasSeenDot = s.at(0) == '.';
// Subsequent characters may only be digits and a dot now
for (char c: s.substr(1)) {
if (not isdigit(c) and c != '.') { return false; }
if (c == '.') {
if (hasSeenDot) { return false; } // no second dot allowed
hasSeenDot = true;
}
}
// Looks like it could be a double
return true;
} // maybeDouble
static Input::Type guessType(std::string const& s) {
if (isInt(s)) { return Input::Int; }
// Test double after we ensured it was not an int
if (maybeDouble(s)) { return Input::Double; }
return Input::String;
} // guessType
加上猜测逻辑,最后解析出来了:
Input Input::Parse(std::string const& s) {
Input result;
result._type = guessType(s);
switch(result._type) {
case Input::Int: {
std::istringstream stream(s);
s >> result._int;
return result;
}
case Input::Double: {
std::istringstream stream(s);
s >> result._double;
return result;
}
case Input::String:
result._string = s;
return result;
}
// Unreachable (normally)
abort();
} // Input::Parse
Phew!
所以 ?差不多了。现在我们需要确定如何比较两个输入。如果它们都具有相同的类型,则很容易,否则您将需要确定任意逻辑。您可以轻松地将输入 Int 转换为输入 Double,但对于字符串来说有点奇怪。
// define < for comparing two instance of "Input",
// assuming they both have the same type
bool operator<(Input const& left, Input const& right) {
assert(left.type() == right.type() && "Different Types!");
switch(left.type()) {
case Input::Int: return left.asInt() < right.asInt();
case Input::Double: return left.asDouble() < right.asDouble();
case Input::String: return left.asString() < right.asString();
}
} // operator<
最后,该程序:
int main(int argc, char* argv[]) {
// parse command line
std::vector<Input> inputs;
// by convention argv[0] is the program name, it does not count!
for (int i = 1; i != argc; ++i) {
inputs.push_back(Input::Parse(argv[i]));
// Detect that the type is the same as the first input
if (inputs.size() >= 2) {
if (inputs.back().type() != inputs.front().type()) {
std::cerr << "Please only use one type among Int, Double and String\n";
return 1; // non-0 is an error
}
}
}
// sort
std::sort(inputs.begin(), inputs.end());
// echo back to the user
for (Input const& i: inputs) {
switch(i.type()) {
case Input::Int: std::cout << i.asInt() << "\n"; break;
case Input::Double: std::cout << i.asDouble() << "\n"; break;
case Input::String: std::cout << i.asString() << "\n"; break;
}
}
// End of the program
return 0;
}
当然,因为我不知道你想要处理的类型..我已经决定了一个任意的集合;)但这应该给你一个框架来作为自己的基础。