是否有一种仅使用基本概念检查输入数据类型的方法

Is there a way to check input data type using only basic concepts?

本文关键字:检查 基本概念 输入 数据类型 方法 一种 是否      更新时间:2023-10-16

我面临的挑战是找到执行通常需要使用标头(除了iostreamiomanip)或高于基本c++知识的任务的方法。如何仅使用逻辑运算符、基本算术(+、-、*、/、%)、if语句和while循环来检查用户输入的数据类型?

显然,输入变量首先有一个声明的数据类型,但是这个问题掩盖了用户输入错误数据类型的可能性。

我尝试了几种方法,包括if (!(cin >> var1))技巧,但没有正确工作。这可能吗?

例子
int main() {
    int var1, var2;
    cin >> var1;
    cin >> var2;
    cout << var1 << " - " << var2 << " = " << (var1-var2);
    return 0;
}

可以在这里输入asdf5.25,那么我如何检查输入不是预期的整数,只使用我前面所说的方法?


我知道这个问题在很多方面是模糊的,主要是因为限制是非常具体的,列出我被允许使用的所有东西将是一件痛苦的事情。我想正如评论中提到的部分问题在于如何首先区分数据类型。

您可以使用简单的操作来做到这一点,尽管这可能有点困难,例如,可以使用以下函数来检查输入是否是十进制数。您可以扩展这个想法并检查浮点数之间是否有句号。

如果需要进一步的帮助,请添加注释。

bool isNumber(char *inp){
    int i = 0;
    if (inp[0] == '+' || inp[0] == '-') i = 1;
    int sign = (inp[0] == '-' ? -1 : 1);
    for (; inp[i]; i++){
        if (!(inp[i] >= '0' && inp[i] <= '9'))
            return false;
    }
    return true;
}

阅读后的一般检查是这样做的:

stream >> variable;
if (not stream.good()) {
    // not successful
}

这可以在任何std::ios上完成。它适用于标准类型(任何数字类型,char, string等),止于空格。如果无法读取variable,则good返回false。您可以为自己的类定制它(包括控制good的返回值):

istream & operator>>(istream & stream, YourClass & c)
{
    // Read the data from stream into c
    return stream;
}

对于您的特定问题:假设您读取字符42。没有办法区分把它读作-和int- a double因为两者都很好。您必须更精确地指定输入格式。

标准库不是魔术-您只需要解析从用户读取的数据,类似于标准库所做的。

首先读取来自用户的输入:

std::string s;
cin >> s;

(如果你想读取整行,你可以使用getline代替)

然后你可以继续解析它;我们将尝试区分整数(*[+-]?[0-9]+ *),实数(*[+-][0-9](.[0-9]*)?([Ee][+-]?[0-9]+)? *),字符串(*"[^"]" *)和其他任何("坏")。

enum TokenType {
    Integer,
    Real,
    String,
    Bad
};

基本构建块是一个"吃掉"连续数字的例程;这将有助于我们与[0-9]*[0-9]+部分。

void eatdigits(const char *&rp) {
    while(*rp>='0' && *rp<='0') rp++;
}

同样,跳过空格的例程也很方便:

void skipws(const char *&rp) {
    while(*rp==' ') rp++;
    // feel free to skip also tabs and whatever
}

然后我们才能解决真正的问题

TokenType categorize(const char *rp) {
首先,我们要跳过空格
    skipws(rp);
那么,我们将尝试匹配最简单的内容:字符串
    if(*rp=='"') {
        // Skip the string content
        while(*rp && *rp!='"') rp++;
        // If the string stopped with anything different than " we
        // have a parse error
        if(!*rp) return Bad;
        // Otherwise, skip the trailing whitespace
        skipws(rp);
        // And check if we got at the end
        return *rp?Bad:String;
    }

然后,关于数字,请注意实数和整数的定义以相同的方式开始;我们有一个共同的分支:

    // If there's a + or -, it's fine, skip it
    if(*rp=='+' || *rp=='-') rp++;
    const char *before=rp;
    // Skip the digits
    eatdigits(rp);
    // If we didn't manage to find any digit, it's not a valid number
    if(rp==start) return Bad;
    // If it ends here or after whitespace, it's an integer
    if(!*rp) return Integer;
    before = rp;
    skipws(rp);
    if(before!=rp) return *rp?Bad:Integer;

如果我们注意到还有东西,我们处理实数:

    // Maybe something after the decimal dot?
    if(*rp=='.') {
        rp++;
        eatdigits(rp);
    }
    // Exponent
    if(*rp=='E' || *rp=='e') {
        rp++;
        if(*rp=='+' || *rp=='-') rp++;
        before=rp;
        eatdigits(rp);
        if(before==rp) return Bad;
    }
    skipws(rp);
    return *rp?Bad:Real;
}

您可以在读取输入后轻松调用此例程。

(注意这里的字符串只是为了好玩,cin对双引号分隔的字符串没有任何特殊处理)