input code problem

Started by
5 comments, last by Zahlman 18 years, 8 months ago
#include<iostream.h> int main(void) { int a; float b,c,d; cout <<"Hourly wage="; cin>> a; cout<<'\n'; cout<<"Days worked="; cin>> b; cout<<'\n'; cout<<"Hours worked="; cin>> c; cout<<'\n'; d=a*b*c; cout <<"Money earned="; cout <<d; cout <<'\n'; } it lets you input A, says days worked, skips input on b and goes to hours worked and input on c. anyone know what is wrong?
Advertisement
What value did you enter for a? If it's not an integer (say you entered 10.50), then some data would be left in the input stream which would get drawn into b at the next input operation.

This is an excellent opportunity for you to familiarize yourself with the debugger, if you haven't already. Assuming you're using Visual Studio, point to the line with cin >> a; and press F9. This sets a breakpoint (you should see a red circle to the left of that line). Now press F5 to run the application in the debugger. You'll see your output window flash, and then return to your IDE with a yellow arrow pointing at the breakpoint line. You can now press F10 to execute a single statement at a time. You can also look toward the bottom of the IDE at a few windows that opened up by themselves - Watch, Variables and Output.

You place a value in the list in the Watch window if you want to see how it changes over time as various code is executed, say to determine why it doesn't have the value you expect. This is useful in larger programs. The Variables window shows all variables in the current scope, and any variables whose values are changed by the just-executed statement are highlighted in a bright red. Finally, the Output window provides a lot of debugging information from the runtime, as well as custom strings you can send yourself using the Win32 OutputDebugString API.

One more thing: <iostream.h> is pre-standard and deprecated. Switch to <iostream> (no extension) instead, and read up on the std namespace here.

Hope that helped!
no im not using studio, im just startin out right now so im using dev c++ and yes i put in an integer, so get rid of .h and and using namespace std; ?
edit- how can i also make it so i can put in like 6.74 or sumthin non whole
Quote:Original post by EmptyMinion
no im not using studio, im just startin out right now so im using dev c++...

Sorry, I don't know much about Dev-C++, but I do know that it also can interoperated with the GNU debugger (gdb) and present similar functionality to what I described above.

Quote:...and yes i put in an integer

That's very strange. Not having full knowledge of your situation, and not having a compiler here to test your exact code, I'll suggest the following:
...cout << "Enter hourly wage rate: ";cin >> a;cin.flush(); // this flushes the input stream, discarding any leftover data...


Quote:...so get rid of .h and and using namespace std; ?

Yes. If you want to learn/write C++, it's better to build good habits from the start.

Quote:edit- how can i also make it so i can put in like 6.74 or sumthin non whole

Use a float, of course! (Or double, but float will generally suffice.)
#include<iostream>
using namespace std;
int main(void)
{
float a,b,c,d;
cout <<"Hourly wage=";
cin>> a;
cout<<'\n';
cout<<"Days worked=";
cin>> b;
cout<<'\n';
cout<<"Hours worked per day=";
cin>> c;
cout<<'\n';
d=a*b*c;
cout <<"Money earned=";
cout <<d;
cout <<'\n';

}
That is what it ended with, and it worked fine. thank you for your help. This is my first day with C++ ^_^
Good to see you're making progress. One thing you can do is chain operations on cin and cout, which can sometimes make the code easier to understand. For instance,
cout <<"Money earned=";cout <<d;cout <<'\n';

can become
cout << "Money earned= " << d << '\n';

Also, you can flush the output stream (cout for the console) in two ways:
cout << flush;

The above will simply flush the stream without sending any additional output.
cout << endl;

This will send a newline character ('\n') and then flush the stream. Learning how and when to use the two flushes, as well as other stream operations and manipulators, is essential to efficient I/O in C++.

Happy hacking!
(Warning! All code in here is off the top of my head. If it does actually work right off, I'll be fairly impressed with myself. But in any event it shouldn't be too hard to fix. Consider it a learning experience :) )

It is frequently overkill, but for console input, you can consider explicitly grabbing a whole line of input at a time, and then re-parsing the line. The thing is that the stream extraction (">>") operator "tokenizes" (cuts up input) on whitespace (and for numbers, at the end of data that can be interpreted as part of the current number), but the console IO is "line-buffered" (meaning that when you input something, control doesn't come back to your program until the user hits return). What this means, practically:

Program: "Enter the first number:"
User: "1 2"
Program: "I got the first number. Enter the second number: I got the second number."

The std::string type represents textual data - it can store a line of text received from the console, of (effectively) any length. There is also a std::stringstream type, which behaves like the console streams (cin and cout), except that it writes to/reads from some "buffer" string. (It might not be implemented exactly like that, but it will appear to the outside to behave exactly that way.)

So we can do something like:

#include <string>#include <iostream> // no .h! Get an updated tutorial please.using namespace std;// We'll make a function to show a prompt, grab a whole line of text,// read the desired item, and throw the rest away (returning the value).// We'll pass in a std::string to hold the prompt message. For now, we'll// assume we're reading from cin and writing to cout.int promptForInteger(const string& prompt) {  cout << prompt << flush; // make sure it appears, but stay on this line  string userLine;  getline(cin, userLine); // does the "read a whole line" part.  // Now we can "parse" the line with a stringstream. First we'll create the  // stringstream, arranging for it to initialize its string buffer with  // the user line:  stringstream parser(userLine);  // and read out the value.  int result;  parser >> result;  // and send it back.  return result;}// In the main function, we can call the function several times:int main() { // don't put the 'void'; it's poor style in C++  int a, b, c, d;  a = promptForInteger("Hourly wage=");  b = promptForInteger("Days worked=");  c = promptForInteger("Hours per day=");  d = a*b*c;  cout << "Money earned=" << d << endl;}


Naturally, there are still a few things missing here. First off, we can only handle ints this way, so far. You'll probably have the idea of writing an equivalent function for floats - it'll work the exact same way, because the >> will "read" a float the same way it "reads" an int - it "knows" the type that it needs to look for, and does something different for each. However, this is messy: we end up copying out the code, and having multiple copies of basically the same thing around is *bad*. It's difficult to maintain (if there's a problem in one copy, you'll need to fix it in several places) and adds extra stuff that you have to read through when you come back to your code later, puts extra space between other parts of the code, etc.

What we can do to work around that is to "template" the function:

// For any type,template<typename T> // <-- no semicolon here! This is part of the same "line"// we can promptFor that type:T promptFor(const string& prompt) {  // We wrote T for the return type, which is a placeholder for whatever  // type it is we want to use the function for.  // All the rest of the function can be as before, except:  T result; // Since this is the variable we're reading our return value into,  // it had better be of the type we want to return! Otherwise, it will try to  // read an int regardless, and convert it into whatever T turns out to be  // when returning.}// When we call the function, there's no way for the compiler to know what// the 'T' type should be, because there aren't any Ts in the argument list.// (If there were, then the compiler could 'deduce' what T is by what's being// passed in - it would have to match up. But it can't do this by looking at// how the return value is used - for complicated reasons.)// To do that looks like this:float a = promptFor<float>("Give me a number:")int b = promptFor<int>("OK, now one without decimals, wise guy:")


Now the 'copying and pasting' is done for you by the compiler (and actually, it will probably do better than that, sharing common bits of code and doing other optimizations that you don't see. This is also the basis of how the stream extraction works in the first place (there is more advanced stuff you can do to handle slight differences in the code for different data types). :)

Next, we have a problem if the input data is invalid. What will happen is that when we read into "result" in promptFor(), the reading fails and "result" is not changed - so it will hold an uninitialized value. We might want to loop until we're successful - but we need to detect success/failure in order to do that, so that we know whether the value of result is one that got read in, or simply one that just happened to be sitting there (i.e. the uninitialized value). So we adjust things:

template<typename T>T promptFor(const string& prompt) {  // We want to do the prompt-get line-grab value process until  // we are successful.  int result;  do {    cout << prompt << flush;    string userLine;    getline(cin, userLine);    stringstream parser(userLine); // This is a "fresh" stringstream each time.  } while (!(parser >> result));  // The way that works, is that the extraction tries to put a value into the  // result, and also returns the stringstream back to you (which is how you  // can "chain" things, like you were shown with cout). Next, the stringstream  // can be interpreted as a boolean value, and appears "true" if reading  // succeeded. So we "do" the loop to prompt and grab a line, "while"   // parsing fails (i.e. at the end of the loop, we try to parse, and if   // failed, try again). Once the parsing succeeds, "result" holds what we  // want, and "parser >> result" is true, thus "!(parser >> result)" is false,  // which breaks the loop.  // and send it back.  return result;}


I have big block comments in all of this, but it's all standard "idioms" that experienced developers are (should be!) familiar with. :) Anyway, this can be modified as desired (once fully understood) - maybe you want different logic for the prompting behaviour, or something. You could also add a check that there is no "garbage" within the rest of the line following the read-in value. Right now, if you promptFor<int>() and the user types "13.23", then it will happily return 13. (it's not rounding; it's completely ignoring the text from the '.' onwards. If the user types "13asdlfjlfj", it will similarly happily return 13.)

This topic is closed to new replies.

Advertisement