Any C++ programmers out there? I need a little help.

I’m doing a project for my C++ college class and while it’s very close to working, I am running into an annoying glitch.

As part of the guidelines, the program will take user entered data from a prompt and process via a series of loops and if else statements. It is also supposed to discard bad data(in this case negative numbers) and then bring back the prompt for the user to re-input his answer and to keep doing so until he does it correctly. I’ve succesfully done that but now have a new problem.

When I test it and type in a non-numerical character(say, a letter or a symbol), the program goes into an ifinite loop and I have to control-C out of it.

I know I have to tell the program to loop properly and go back to the input prompt (“Enter number here”) if a non-numerical character is entered. At the moment though, I’m somewhat at a loss as to how to accomplish this in a fairly simple way. I’ve been going through the textbook but nothing is jumping out at me.

Any suggestions?

You could post your code.

//loads proper data library for interface.
#include <iostream.h>
//loads proper data library for manipulators
#include <iomanip>

int main()
{

    //Declare variables
    float loan = 0;       //The amount of the loan
    float intrate = 0;    //The Interest rate. 
    float apint = 0;  //The applied interest  
    float monpay = 0;     //The monthly payment
    float mdmonpay = 0;   //The monthly payment
    int month = 0;  //the months counter

   //Print a message telling the user what this program does
    cout &lt;&lt; "Welcome to Student Loan scheduler. ";
    cout &lt;&lt; "This program will find the amount of time";
    cout &lt;&lt; " it will take you to pay off your loan.";
    cout &lt;&lt; "Let's go!" &lt;&lt;endl;
    cout &lt;&lt; endl;

    //Set trailing zeros
    cout.setf(ios::fixed, ios::floatfield);
    cout.precision(2);
    cout.setf(ios::showpoint);

   //while loop takes data and checks for errors
    while(loan &lt;= 0)
    {

    //Prompt the user to enter the loan amount
    cout &lt;&lt; "Please enter the loan amount:$";
    cin&gt;&gt;loan;
    cout &lt;&lt; endl;

    //Echo loan
    cout &lt;&lt; "You have entered: $" &lt;&lt;loan &lt;&lt; endl;

//Display error message if loan is a negative 		//amount, loops back for input of amount if not
    if(loan &lt;= 0)
            {
            cout&lt;&lt;"You have entered a negative amount.";
            cout&lt;&lt;"Please enter a postive amount"&lt;&lt;endl;
            }
    }

This is not the entirely of it, but all that I felt could possibly be relevent to my question.

Yeah, youre likely trying to do some math on a capital R. Or something to that effect.

If you want you can use the isdigit() function in <ctype>

and do something like:

do{

prompt;
get data into var;
etc…;
}while (!isdigit(var))

The reason you get this error is because you are declaring an indeger and trying to put a character into it. like:
int a;
cin>>a;
and then the user enters ‘b’ or something instead of a number. To avoid this problem declare a character and then use it as an integer later. Like:
char x;
int y;
cin>>x;
if() //Put your logic to check for validity here
y=atoi(x); //This will turn a character into an integer if it is valid

As you can see it all boils down to getting the input in from a user as a character and then using it as an integer. The best site for these type of questions is www.experts-exchange.com Enjoy

Check out http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.3. This seems to be pretty close to exactly what you are asking.

The ascii values for integers are 48-57. If the users input falls in that range (including the endpoints), it’s an integer. Otherwise, it ain’t.

I tried rearranging this code so that it would work.

Does C++ have any isVar function or a isNumerical functions like VB, or at least vbscript?
cpluscplus.com

Yes, many. Like I posted above, the ctype include has a slew of them.

isalpha
isalnum
isdigit
isspace
isprint
ispuntc
etc

Thanks.

So, HPL, put if ((loan >=0) && (!isalpha(loan)))
{
//and so on.

I have a question for you. Why are you starting out the loop before you ask for the loan? I think it’s better practice asking the loan before the loop and ask again at the end of the loop. Any other programmers out there: Is this better?

This is just a suggestion. Do it your way. I was just giving an example of how I would have done it. Everyone has different programming styles.

Well, I had it outside the loop before, but I want it to automatically re-prompt for the data if the data is not valid(which at this point is a negative number).

I’m trying to keep it realitivly simple, because I’m still rather new to loops.

After a bit of coding with g++, I figured out what the problem is with the OP’s original code. There is no problem with order or anything like that (well, except for a missing ‘}’ at the end). The problem is the istream object cin is put into a bad state after the cin >> loan call. To continue with life, you need to clear the bad state and flush what’s in the buffer:



// Is the console in in a bad state?
if (!cin)
{
    // Clear the bad state.
    cin.clear();
    // Flush the buffer.
    while('
' != cin.peek())
        cin.get();
}


This works with the Gnu g++ compiler, and should work with the VC++ compiler.

Follow up: that bit of code goes in the “if (loan <= 0)” block.

Also, another way to do this properly (with a shout out to all the old school C homies):



// Some sample code
// iostream for the cin and cout
#include <iostream>
// stdio for sscanf
#include <stdio.h>

int main()
{
    float ftNumber;
    char szInputBuffer[1024];
    
    do
    {
        cout << "Enter a happy float: ";
        cin.getline(szInputBuffer, sizeof(szInputBuffer));

        // Set ftNumber to 0, because sscanf won't change ftNumber
        // if a float isn't available.
        ftNumber = 0;

        // sscanf: String Scan Function. Parses first argument
        // (a char string) using specifiers in second argument.
        // For any variable other than a string, the following 
        // arguments must be pointers (i.e. &ftNumber instead of
        // ftNumber) (strings are actually already pointers).
        sscanf(szInputBuffer, "%f", &ftNumber);

        if (0 == ftNumber)
        {
            cout << "0 is not a happy float :-(" << endl;
            cout << "Try again!" << endl;
        }
    } while (0 == ftNumber);
    cout << "Now, " << ftNumber << " is a happy float :-)" << endl;
    return 0;
}


This will not work. isalpha takes a character (‘a’, ‘%’, ‘1’) and checks to see if it’s a letter (such as ‘a’ or ‘Z’, instead of ‘2’ or ‘;’). loan is a float, not a character.

As long as loan is initialized to 0.0 before entering the while loop, this is perfectly fine. However, using a do {} while loop would be a more natural solution. Having more than one copy of the input gathering code raises the hairs on the back of my neck (if at all possible, I never have two copies of the same code that do the same thing: twice as much code = twice as many chances for a bug, and if you find a bug in one copy you need to remember to fix it in the other copy).

The way to choose between the while{} and do{}while loops is to ask yourself: will this code run at least once? If the code in the loop needs to run at least once before the condition matters, the do{}while loop is what you want.

Another thing that helps with loops, HPL, is proper indentation. I can’t tell if you had indentation that was lost when you posted your code, but if you aren’t using indentation, you should start. (Any time you’re in a loop, indent should increase.)

p.s. sscanf can cause some hairy problems if you don’t know how to use it, so when in doubt just use the method I outlined in my first post with the cin object.

And kudos to Mbossa for posting a link to a site that answers the question succinctly.

atoi is for strings, not characters. To convert a character to an integer, use:

if (isdigit(x)) y = x - ‘0’;

I thought about what I said earlier. The way you have it is ok. The order that is.

What does that function return if it’s a letter? I put ! to make it if it isn’t a letter.

I was thinking of something different when I asked that question. In my modifications I made to it, I had a conditional before the loop, and then put this while loop in an else statement. But to come to think about it, you are right about trying not to repeat the code like I did. Less chance for bugs. Of course, that’s why I like function calls and Objects.

ANother thing that I found usefull is putting comments at the end of each brace signalling the end of what bracket of code it closes. See my post above where I changed your code. You don’t need to change anything about your order.