0
#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.

I have a problem I've been trying to find an answer to for weeks. From the code you can see that !std::cin condition won't accept any chars, therefore an error will be printed. I however need an exception where if 'y' || 'Y' is inputted it loops back to the std::cin >> x; and asks for a float value again until it is provided, however if any other char is inputted like 'h' it would obviously go back to the error message.

I've tried multiple if statements, checked recursives but no luck. The problem is that I can't make the exceptions because if 'y' is inputted then the program doesn't understand it because the std::cin >> is asking for a number not a char...

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
SkewEd
  • 1
  • 1
    You can try reading the input into a string instead of a float and then try to process it, either into float with a conversion function (like `stof`) or checking if it equals the character 'y'. – Daniel Marques Sep 27 '21 at 05:53
  • 1
    You may want to use std::getline in conjunction with std::stringstream. – n. m. could be an AI Sep 27 '21 at 05:54
  • 1
    The task description is unclear. On the one hand, you state that you want the program to ask for a float value again, until one is provided. On the other hand, you state that this should only happen when the user enters `y` or `Y`, but when the user enters anything else, it should print an error message instead. This is contradictory. – Andreas Wenzel Sep 27 '21 at 07:06
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Oct 05 '21 at 09:43

2 Answers2

2

The task description is unclear. On the one hand, you state that you want the program to ask for a float value again, until one is provided. On the other hand, you state that this should only happen when the user enters "y" or "Y", but when the user enters anything else, it should print an error message instead. This is contradictory.

If you want your program to check whether the user enters a certain character, then you must read the input as a string, instead of as a number. I recommend that you use std::getline for this.

Once you have determined that the user did not enter "Y" or "y", you can use the function std::stof to convert the string to a number.

When the user doesn't enter a number, I don't understand why you say you want to loop back to the input on "y" and "Y", but want to print an error message instead on all other inputs. However, if that is what you want, then this is how you can implement it:

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

This program works as intended (based on your contradictory description). If you enter "y" or "Y", it will loop back to the prompt for user input:

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

If you instead provide a non-number input that is not "y" or "Y", it will print an error message, instead of looping back to the input:

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

This behavior does not make sense, but it appears to be what you are asking for.

This program does have one small problem, though. It will accept 6sdfjloj as valid input for the number 6:

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

It would probably be more meaningful to reject such input with an error message.

Doing this is also possible, by passing a second argument to std::stof, in order to determine how many characters were converted. If not all characters were converted, you can reject the input. On the other hand, you may want to accept trailing whitespace characters (as determined by std::isspace), but reject the input if there are any other trailing characters. This would make sense: Because std::stof accepts leading whitespace characters, it makes sense to also accept trailing whitespace characters.


In my opinion, it would be more meaningful to demonstrate these programming possibilities with the following task:

The user should instead be prompted with the following message:

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

If the user enters "q" or "Q", the program should exit.

Otherwise, it should determine whether the user entered a valid number. If the input is a valid number, the program should say so and print the number, otherwise it should print an error message. Either way, the program should loop back to the initial prompt.

The solution to this problem would be the following:

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

This program has the following output:

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!

As you can see, it now also properly rejects input such as 6sdfjloj.

Note that this program contains one goto statement. It was appropriate to use it, in order to jump out of a nested loop. This is considered an acceptable use of goto. However, you should not use goto except in rare situations, in which there is no cleaner alternative. So please don't get used to using it.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • Looks like this is exactly what I needed. I'm happy to find out that there even is such a possibility to convert strings to numbers! Code is a little bit hard for me ( there are a few things I don't understand yet) but this is not only a great studying material but also, in my opinion, the best solution. – SkewEd Sep 27 '21 at 22:05
  • @SkewEd: I have now added a second program which demonstrates the same programming possibilities. In contrast to the first program, this second program actually does something meaningful. Also, it fixes the problem of accepting `6sdfjloj` as valid input for the number `6`. – Andreas Wenzel Sep 28 '21 at 01:34
0

Seems like you want to take a floating number as input.

If the user gives any invalid input like a character, you want to show an error message and take input again.

If this is the case, taking input using string might be a better way.

Take the input as a string, check if the string contains any additional character other than digits and a dot.

If it does, take input again. So you can use a loop to do that.

If you get a valid string, then calculate the result and stop taking input.

Sample code:

int main()
{
    float x, a, b;
    char conditions[] = { 'Y', 'y' };
    string input;
    while(true)
    {
        std::cout << "Enter a number: ";
        std::cin >> str;

        if (input_contains_any_other_character)
        {
            std::cout << "error";
            // going back to the beginning of the while loop
        }
        else
        {
            // first convert the string and keep it in the variable x
            // then calculate your result
            a = x * x;
            std::cout << "A is: " << a << std::endl;
            break;  // stop taking further input
        }
    }
}
Md. Faisal Habib
  • 1,014
  • 1
  • 6
  • 14
  • This is pretty good! I didn't know that it's possible to convert string to numbers. Very helpful! – SkewEd Sep 27 '21 at 22:02
  • Check the following resources to learn more about it. 1. https://www.geeksforgeeks.org/converting-strings-numbers-cc/ 2. https://www.programiz.com/cpp-programming/string-int-conversion 3. https://www.geeksforgeeks.org/stdstof-in-cpp/ – Md. Faisal Habib Sep 28 '21 at 04:07