I appreciate your help, but the 1000 level class i'm in would look at me funny if i showed up with week 10 stuff in my code when he hasnt even taught it yet. Thanks for everything, everyone!!
I appreciate your help, but the 1000 level class i'm in would look at me funny if i showed up with week 10 stuff in my code when he hasnt even taught it yet. Thanks for everything, everyone!!
Dunno, works for me.
#include <iostream>
and
using namespace std;
When writing cases, typically it's more readable to indent the code:
NOTCode:case 'x': // my code here break;
The same goes for indentation for } and {. They should both be on the same level. They mark the start and end of a block and therefore should be on the same level because each "indentation level" is a guideline to us which code belongs where.Code:case 'x': // my code here break;
About why your program just dies when typing a non-number entry... well, it's because of the poor design (IMO) of the STL.
To solve it, a typical approach is to read a string, convert to number, and if number == 0 and the user did NOT enter 0, then it's an invalid number, otherwise just continue.
Taking this a little off topic here, but do you guys prefer to indent switch structures as:
or:Code:switch (x) { case 0: foo(); break; case 1: bar(); break; default: baz(); }
Assuming the former, would you also indent as:Code:switch (x) { case 0: foo(); break; case 1: bar(); break; default: baz(); }
or:Code:switch (x) { case 0: { foo(); bar(); } break; default: baz(); }
?Code:switch (x) { case 0: { foo(); bar(); } break; default: baz(); }
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
My homepage
Advice: Take only as directed - If symptoms persist, please see your debugger
Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"
Nevermind, I misunderstood your question. It doesn't work for me.
In response to laserlight, I prefer the second.
Last edited by robwhit; 01-15-2008 at 01:12 PM.
I prefer the second. The only problem is that IDEs have troubles deindenting the closing brace. But then, switches ain't good OOP anywayTaking this a little off topic here, but do you guys prefer to indent switch structures as:
User input in a console program is a nuissance anyway (although may-be higher-level languages provide means for all the validation).About why your program just dies when typing a non-number entry... well, it's because of the poor design (IMO) of the STL.
To solve it, a typical approach is to read a string, convert to number, and if number == 0 and the user did NOT enter 0, then it's an invalid number, otherwise just continue.
It is not entirely impossible to write
And it is not impossible to turn this into a template function and have this problem solved for goodCode:while (!(cin >> x)) { //clear error //flush stream //display error prompt }
I haven't actually ever bothered to display a message "You must type either Y/N! Try again!!!" I have always just chosen to loop while Y or while not N, depending on whether exiting or continuing by accident would be a greater annoyance.how would I handle adding a y/n option making sure to be aware of syntax errors on behalf of the user?
But then, I'm the only user of my console programs...
Last edited by anon; 01-15-2008 at 12:53 PM.
I might be wrong.
Quoted more than 1000 times (I hope).Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
It's part of the C++ libraries, is it not?
Yeah, but if you enter something other than 9, it won't terminate, yes? And "a" is not 9.His program exits because 'option' is not equal to 9, as I already stated.
As for the switch question, I typically do:
Depends on the situation, really. Is the switch long? Then typically I try to compact it if there's just one line of code (plus break).Code:switch(something) { case x: // something; break; case y: { // something break; } case z: /* something */; break; }
Otherwise I use the non-brace version.
If I use local variables and need to initialize or so, I use the brace type since it won't compile otherwise.
The only problem I have is that Visual Studio default to:
Which I find annoying. It's identical to if, so why the heck am I supposed to indent it again after the case?Code:switch(something) { case y: { // something break; } }
Good idea!
Simple examples:Code:// // basic_input.h // // Contains the declaration/definition of console input helper functions // that make basic console input easier for new C++ programmers. // // basic_input: // template<typename charT, typename traits, typename T> // inline bool basic_input(std::basic_istream<charT,traits>& is, // T& x, charT delim) // template<typename charT, typename traits, typename Allocator> // inline bool basic_input(std::basic_istream<charT,traits>& is, // std::basic_string<charT,traits,Allocator>& x, charT delim) // template<typename charT, typename traits> // inline bool basic_input(std::basic_istream<charT,traits>& is, // charT* x, std::streamsize count, charT delim) // template<typename charT, typename traits, typename T> // inline bool basic_input(std::basic_istream<charT,traits>& is, // T& x) // // Returns: // bool - true if the input succeeded, false otherwise. // // Effects: // This function attempts to read from the input stream into the passed in // variable up to the specified delimiter. If the data in the stream does // not match the expected format of the variable type, or if the character // following the data read in is not the delimiter, then the input fails. // // On success, the variable x contains the inputted value. On failure, the // variable x is cleared (i.e. default-initialized). // // On success or failure, the input stream is left in a good state and all // characters up to and including the delimiter are removed from the stream. // // The delimiter defaults to '\n' if not specified. // // If the variable type is char* (or some other character pointer), and the // delimiter has not yet been reached prior to count characters being read // in, then the input has failed and the array pointed to by the char* will // be filled with count characters set to null. // // Sample usage: // int i; // std::cout << "Enter an int: "; // while (!bip::basic_input(std::cin, i)) // std::cout << "Invalid int! Try again: "; // // // ignore_line: // template<typename charT, typename traits> // inline std::basic_istream<charT,traits>& ignore_line(std::basic_istream<charT,traits>& is, // charT delim) // template<typename charT, typename traits> // inline std::basic_istream<charT,traits>& ignore_line(std::basic_istream<charT,traits>& is) // // Returns: // std::basic_istream<charT,traits>& - the stream passed in. // // Effects: // This function reads and discards all characters in the passed in input // stream up to and including the first instance of the delimiter. The // delimiter defaults to '\n' if not specified. // // Sample usage: // std::cout << "Press Enter to Close.\n"; // bip::ignore_line(std::cin); // #ifndef BASIC_INPUT_H_ #define BASIC_INPUT_H_ #include <istream> #include <ios> #include <string> #include <limits> namespace bip { template<typename charT, typename traits> inline std::basic_istream<charT,traits>& ignore_line(std::basic_istream<charT,traits>& is, charT delim) { return is.ignore(std::numeric_limits<std::streamsize>::max(), delim); } template<typename charT, typename traits> inline std::basic_istream<charT,traits>& ignore_line(std::basic_istream<charT,traits>& is) { return ignore_line(is, is.widen('\n')); } template<typename charT, typename traits, typename T> inline bool basic_input(std::basic_istream<charT,traits>& is, T& x, charT delim) { std::ios::fmtflags old_flags = is.flags(); if ((is >> std::noskipws >> x) && (is.eof() || is.get() == delim)) { is.flags(old_flags); return true; } is.flags(old_flags); x = T(); is.clear(); ignore_line(is, delim); return false; } template<typename charT, typename traits, typename Allocator> inline bool basic_input(std::basic_istream<charT,traits>& is, std::basic_string<charT,traits,Allocator>& x, charT delim) { if (std::getline(is, x, delim)) return true; x.clear(); is.clear(); return false; } template<typename charT, typename traits> inline bool basic_input(std::basic_istream<charT,traits>& is, charT* x, std::streamsize count, charT delim) { if (is.getline(x, count, delim)) return true; if (is.gcount()+1 < count) memset(x, charT(), count); is.clear(); ignore_line(is, delim); return false; } template<typename charT, typename traits, typename T> inline bool basic_input(std::basic_istream<charT,traits>& is, T& x) { return basic_input(is, x, is.widen('\n')); } } #endif // BASIC_INPUT_H_
More complex examples:Code:#include <iostream> #include <string> #include "basic_input.h" using namespace std; using namespace bip; int main() { // Reading integers int i; cout << "Enter an int: "; if (basic_input(cin, i)) cout << "The number read in was: " << i << '\n'; else cout << "Sorry, invalid int!" << '\n'; // Reading doubles double d; cout << "Enter a double: "; while (!basic_input(cin, d)) { cout << "Invalid double! Try again: "; } cout << "The double read in was: " << d << '\n'; // Reading strings (one whole line at a time like getline) string s; cout << "Enter a line of text: "; basic_input(cin, s); cout << "The line of text read in was: " << s << '\n'; // Pause the program cout << "Press Enter to Close.\n"; ignore_line(cin); }
Code:#include <iostream> #include <string> #include "basic_input.h" int main() { const std::streamsize cslen = 5; char cstyle[cslen]; std::cout << "Enter a line of text: "; if (bip::basic_input(std::cin, cstyle, cslen, '\n')) std::cout << "The line of text read in was: " << cstyle << std::endl; else std::cout << "Sorry, invalid: " << cstyle << std::endl; std::string s; std::cout << "Enter a line of text: "; bip::basic_input(std::cin, s); std::cout << "The line of text read in was: " << s << std::endl; int i; std::cout << "Enter an int: "; if (bip::basic_input(std::cin, i)) std::cout << "The number read in was: " << i << std::endl; else std::cout << "Sorry, invalid int!" << std::endl; double d; std::cout << "Enter a double: "; while (!bip::basic_input(std::cin, d)) { std::cout << "Invalid double! Try again: "; } std::cout << "The double read in was: " << d << std::endl; std::wstring ws; std::wcout << L"Enter a line of text: "; bip::basic_input(std::wcin, ws); std::wcout << L"The line of text read in was: " << ws << std::endl; int wi; std::wcout << L"Enter an int: "; if (bip::basic_input(std::wcin, wi)) std::wcout << L"The number read in was: " << wi << std::endl; else std::wcout << L"Sorry, invalid int!" << std::endl; double wd; std::wcout << L"Enter a double: "; while (!bip::basic_input(std::wcin, wd)) { std::wcout << L"Invalid double! Try again: "; } std::wcout << L"The double read in was: " << wd << std::endl; std::cout << "Press Enter to Close.\n"; bip::ignore_line(std::cin); }
Last edited by jlou; 01-15-2008 at 02:02 PM.
switch only uses builtin types.Looks like Yarin gets the last laugh.Code:#include <iostream> int main() { using namespace std; double num1, meters, feet, kilos, pounds, liters, gallons, kms, miles; string option; cout << "English/Metric Conversion Calculator v1.0" << endl; cout << "-----------------------------------------" << endl; cout << "1. Convert feet to meters" << endl; cout << "2. Convert meters to feet" << endl; cout << "3. Convert lbs. to kilograms" << endl; cout << "4. Convert kilograms to lbs." << endl; cout << "5. Convert gallons to liters" << endl; cout << "6. Convert liters to gallons" << endl; cout << "7. Convert square miles to square kilometers" << endl; cout << "8. Convert square kilometers to square miles" << endl; cout << "9. Quit" << endl << endl; do // makes sure the loop is ran at least once { cout << endl << "Please select the conversion type you want to perform:" << endl; getline(cin, option); if(option == "1") { cout << endl << "Enter the number of feet to convert to meters: "; cin >> num1; meters = num1 * 0.3048; cout << endl << num1 << " feet is equal to " << meters << " meters." << endl; } else if(option == "2") { cout << endl << "Enter the number of meters to convert to feet: "; cin >> num1; feet = num1 * 3.2808399; cout << endl << num1 << " meters is equal to " << feet << " feet." << endl; } else if(option == "3") { cout << endl << "Enter the number of pounds to convert to kilograms: "; cin >> num1; kilos = num1 * 0.45359237; cout << endl << num1 << " lbs. is equal to " << kilos << " kilograms." << endl; } else if(option == "4") { cout << endl << "Enter the number of kilograms to convert to pounds: "; cin >> num1; pounds = num1 * 2.20462262; cout << endl << num1 << " kilograms is equal to " << pounds << " lbs." << endl; } else if(option == "5") { cout << endl << "Enter the number of gallons to convert to liters: "; cin >> num1; liters = num1 * 3.7854118; cout << endl << num1 << " gallons is equal to " << liters << " liters." << endl; } else if(option == "6") { cout << endl << "Enter the number of liters to convert to gallons: "; cin >> num1; gallons = num1 * 0.264172051; cout << endl << num1 << " liters is equal to " << gallons << " gallons." << endl; } else if(option == "7") { cout << endl << "Enter the number of square miles to convert into square kilometers: "; cin >> num1; kms = num1 * 2.58998811; cout << endl << num1 << " square miles is equal to " << kms << " square kilometers." << endl; } else if(option == "8") { cout << endl << "Enter the number of square kilometers to convert into square miles: "; cin >> num1; miles = num1 * 0.386102159; cout << endl << num1 << " square kilometers is equal to " << miles << " square miles." << endl; } else { cout << "That is an invalid option. Please choose again." << endl; } } while(option != "9"); // keep looping to ask user as long as '9' isn't chosen cout << "Thank you for using Conversion Calculator v1.0!" << endl; return 0; }
Ok, so what do we agree is the final verdict? I've already established in my first post that I am not a programmer, I am an Industrial Engineer who took an entry level C++ class as an elective, and I just need some help with a few topics.
I don't care if there is an easier way to write this program using templates or structs with arrays or a magic hat you can pull rabbits out of. We're not even at that point in class to use all of that stuff, so its a moot point anyway... plus rabbits have poor syntax...
I also don't need people telling me my code is poorly written. If you think it is, I don't care. Indentation levels = I don't care. Does that effect the functionality? No. I appreciate the help on everything but all I want to know is how I add some code to allow the user to type in something other than 1-9 and get prompted for a selection again.
You've got the three choices Malcolm gave, which are all not really that different. None of us are going to care which one you use, and I can't find any others that I like.
Occasionally questions are interesting on their own, regardless of whether there is a use for them right this minute. Look at the contest forum.I don't care if there is an easier way to write this program using templates or structs with arrays or a magic hat you can pull rabbits out of. We're not even at that point in class to use all of that stuff, so its a moot point anyway... plus rabbits have poor syntax...
You will be extremely lucky if you never find out how wrong you are. It's obviously not as direct as, say, Python, but when you let the indentation make you miss a brace, or add an extra brace, or.... Plus, when assignment two adds to the source code of assignment one, and assignment three adds to the source of assignment two, and so on, being able to read, as you put it, will come in extremely handy. (I actually took a class -- granted, it was COBOL -- where we had one program. Ten programming assignments, starting at "read all the names" going through double-control-break programming or whatever, but you needed to have program n-1 in the code of program n. I've never gone that far myself.)I also don't need people telling me my code is poorly written. If you think it is, I don't care. Indentation levels = I don't care. Does that effect the functionality? No.
C++ includes the Standard C++ Library which is similiar-to but not the same-as the STL (Standard template library). It is based on the STL. The commonly used correct term for it is SC++L. 'cin' doesn't involve templates either. It instead involves many overloads for different data types.
Now it seems I was back-to-front with the while(option != 9) thing. So why did he say that typing something other than 9 was ending the program? I'm a little confused about that.
I blame the heat. I just had a cold shower and I can't stop sweating.
My homepage
Advice: Take only as directed - If symptoms persist, please see your debugger
Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"
Ok, I used one of Malcom's fixes to correct the mis-typing error. Thanks to everyone who helped, I appreciate it.
Chris