有没有办法只使用基本概念检查输入数据类型?

时间:2015-09-28 20:39:52

标签: c++

我很难找到执行通常需要使用标头(除了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,那么如何使用我之前说明的方法检查输入是否不是预期的整数?

我理解这个问题在很多方面都很模糊,主要是因为限制非常具体,列出我允许使用的所有内容都会很痛苦。我想评论中提到的部分问题是如何首先区分数据类型。

3 个答案:

答案 0 :(得分:1)

您可以使用简单的操作来执行此操作,尽管可能有点困难,例如,可以使用以下函数来检查输入是否为十进制数。您可以扩展该想法并检查浮点数之间是否存在句点。

如果您需要进一步的帮助,请添加评论。

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;
}

答案 1 :(得分:0)

阅读后的一般检查完成如下:

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

这可以在任何std::ios上完成。它适用于在空白处停止的标准类型(任何数字类型,charstring等)。如果无法读取variablegood将返回false。您可以为自己的类(包括control over good's return value)自定义它:

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

针对您的具体问题:假设您阅读了字符42。没有办法区分阅读它   - int   - double 因为两者都很好。您必须更精确地指定输入格式。

答案 2 :(得分:0)

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

首先阅读用户的输入:

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没有对双引号分隔字符串进行任何特殊处理。)