首页 > 解决方案 > 浮点输入中的 C++ 理解字符问题

问题描述

#include <iomanip>
#include <math.h>

int main() {

    float x, a, b;
    char conditions[] = { 'Y', 'y' };

    std::cout << "Enter a number: ";
    std::cin >> x;

    if (!std::cin) {
        std::cout << "error";
    }
    else {
        a = x * x;
        std::cout << "A is: " << a << std::endl;
    }

}
//I need to create an if statement or a loop to
//ask to input float x again if char conditions were input instead.

我有一个问题几周来一直在寻找答案。从代码中您可以看到!std::cin条件不接受任何字符,因此将打印错误。但是我需要一个例外,如果'y'|| 'Y'输入它会循环回到std::cin >> x;并再次请求一个浮点值,直到它被提供,但是如果输入任何其他字符,'h'它显然会返回错误消息。

我尝试了多个 if 语句,检查了递归但没有运气。问题是我不能例外,因为如果'y'输入了,那么程序就无法理解它,因为它std::cin >>要求的是一个数字而不是一个字符......

标签: c++

解决方案


任务描述不清楚。一方面,您声明您希望程序再次请求一个浮点值,直到提供一个。另一方面,您声明这只应该在用户输入"y"or时发生"Y",但是当用户输入其他任何内容时,它应该打印一条错误消息。这是矛盾的。

如果您希望您的程序检查用户是否输入了某个字符,那么您必须将输入读取为字符串,而不是数字。我建议您使用std::getline它。

一旦确定用户没有输入"Y"or "y",就可以使用该函数std::stof将字符串转换为数字。

当用户不输入数字时,我不明白您为什么说要循环回到 and 上的输入"y""Y"而是想在所有其他输入上打印错误消息。但是,如果这是您想要的,那么您可以通过以下方式实现它:

#include <iostream>
#include <string>

int main()
{
    std::string input;
    float x;

    for (;;) //infinite loop, equivalent to while(1)
    {
        //prompt user for input
        std::cout << "Enter a number: ";

        //read one line of input
        std::getline( std::cin, input );
        if ( !std::cin )
            throw std::runtime_error( "unexpected stream error!" );

        //check if "y" or "Y" was entered
        if ( input == "y" || input == "Y" )
            continue;

        //attempt to convert input to a number
        try
        {
            x = std::stof( input );
        }
        catch ( std::invalid_argument )
        {
            printf( "Unable to convert to number\n" );
            break;
        }
        catch ( std::out_of_range )
        {
            printf( "Number is out of range\n" );
            break;
        }

        std::cout << "You entered the following number: " << x << "\n";
    }
}

该程序按预期工作(基于您的矛盾描述)。如果输入"y"or "Y",它将循环回到提示用户输入:

Enter a number: y
Enter a number: y
Enter a number: y
Enter a number: 67.5
You entered the following number: 67.5

"y"如果您改为提供不是or的非数字输入"Y",它将打印一条错误消息,而不是循环回输入:

Enter a number: y
Enter a number: y
Enter a number: j
unable to convert to number

这种行为没有意义,但它似乎是你所要求的。

不过,这个程序确实有一个小问题。它将接受6sdfjloj作为数字的有效输入6

Enter a number: 6sdfjloj
You entered the following number: 6

使用错误消息拒绝此类输入可能更有意义。

也可以这样做,通过将第二个参数传递给std::stof,以确定转换了多少字符。如果不是所有字符都被转换,您可以拒绝输入。另一方面,您可能希望接受尾随空白字符(由 确定std::isspace),但如果有任何其他尾随字符,则拒绝输入。这是有道理的:因为std::stof接受前导空格字符,所以也接受尾随空格字符是有意义的。


在我看来,通过以下任务展示这些编程可能性会更有意义:

应改为使用以下消息提示用户:

"Please enter a number, or enter "q" to quit: "

如果用户输入"q""Q",程序应该退出。

否则,它应该确定用户是否输入了有效的数字。如果输入是一个有效数字,程序应该这样说并打印该数字,否则它应该打印一条错误消息。无论哪种方式,程序都应该循环回到初始提示。

这个问题的解决方案如下:

#include <iostream>
#include <string>
#include <cctype>

int main()
{
    std::string input;
    float x;
    std::size_t pos;

    for (;;) //infinite loop, equivalent to while(1)
    {
        //prompt user for input
        std::cout << "Please enter a number, or enter \"q\" to quit: ";

        //read one line of input
        std::getline( std::cin, input );
        if ( !std::cin )
            throw std::runtime_error( "unexpected stream error!" );

        //check if "q" or "Q" was entered
        if ( input == "q" || input == "Q" )
        {
            std::cout << "Quitting program!\n";
            break;
        }

        //attempt to convert input to a number
        try
        {
            x = std::stof( input, &pos );
        }
        catch ( std::invalid_argument )
        {
            printf( "Unable to convert to number!\n" );
            continue;
        }
        catch ( std::out_of_range )
        {
            printf( "Number is out of range!\n" );
            continue;
        }

        //make sure that any trailing characters are whitespace,
        //otherwise reject input
        for ( std::size_t i = pos; input[i] != '\0'; i++ )
        {
            if ( !std::isspace( static_cast<unsigned char>(input[i]) ) )
            {
                std::cout << "Unexpected character encountered!\n";
                //we cannot use continue here, because that would jump
                //to the next iteration of the innermost loop, but we
                //want to jump to the next iteration of the outer loop
                goto continue_outer_loop;
            }
        }

        std::cout << "Input is valid, you entered the following number: " << x << "\n";

    continue_outer_loop:
        continue;
    }
}

该程序具有以下输出:

Please enter a number, or enter "q" to quit: 67.5
Input is valid, you entered the following number: 67.5
Please enter a number, or enter "q" to quit: 32.1
Input is valid, you entered the following number: 32.1
Please enter a number, or enter "q" to quit: sdfjloj
Unable to convert to number!
Please enter a number, or enter "q" to quit: 6sdfjloj
Unexpected character encountered!
Please enter a number, or enter "q" to quit: q
Quitting program!

如您所见,它现在也正确拒绝输入,例如6sdfjloj.

请注意,该程序包含一个goto语句。为了跳出嵌套循环,使用它是合适的。这被认为是可接受的使用goto. goto但是,除非在没有更清洁的替代方案的极少数情况下,否则不应使用。所以请不要习惯使用它。


推荐阅读