I have an equation with 4 variables, I am prompting the user to enter each one of these variables, and then the program decides based on what variables are entered, which variables it needs to solve for. For instance, given variable a and b, I need to solve for b and c. I am trying to come up with a way for the program to decide which variables have been entered, and which ones have not been. This is what I have been thinking so far:
int a,b,c,d;
char unknown;
cout<<"****This program decides which variables to solve for****\n;
cout<<"Please enter the known variables below, if a variable is unknown,
please enter a'?'\n"
cout<< "please enter variable a\n";
cin>>a;
cout<< "please enter variable b\n";
cin>>b;
etc....
if (a =='?'){
check b,c,d}
if (b =='?'){
check c,d}
And then running those variables through if statements to determine which variables are present and which aren't. There has to be an easier way though, these if else if statements have the potential to be ridiculous. If any of you have any advice its much appreciated. Thanks!
The pseudo-code that you've posted won't work, because >>x where xis an int will try to interpret the user's input as a specification of an integer. So, with the user typing ? what happens is that the operation fails, cin is put in a failure state, and further input operations are ignored until or if that failure state is cleared.
One way around this is to input a line at a time, into a std::string, by using std::getline from the <string> header. When you have the line of input you can then check whether it's a question mark (or simpler, just empty). And if not you can then attempt to convert the user's number specification to an int by using e.g. a std::istringstream (as I recall from the <sstream> header).
It can be instructive to make this part work even if you'll probably discover, as "Potatoswatter" commented, that the problem you're doing this for can be quite complex.
Cheers & hth.,
– Alf
Related
I realise this question probably has been asked before. I'm asking this as I don't know what to search for.
Hi, so I've started learning about arrays, but I'm not sure how (or if) they can help me with this problem:
Let's say I want the user to be able to choose what to do within my program. I then write a numbered list to the console:
Output "a"
Output "b"
Output "c"
The user will be asked to enter a number, and the number defines which function the program is going to run. What i want the program to do is instead of having me write this three times and changing out the numbers and letters:
if (numberInput == "1") {
functionA;
}
I just write something that takes the number from numberInput and then runs the function associated with it.
Again, I know this question probably has been asked a 1000 times before, so I'm wondering if someone has an idea on how I should go forward on searching for the answer. Thanks!
What you want is called a switch statement
I would start there
i think best here is switch/case stuff
exactly what you're askin about is to use array of function pointers.See
How can I use an array of function pointers?
you'll end up with
int c;
std::cin >> c;
....
(*fnpointers[c])();
I am new and beginner in programming and dont quiet understand how to post my question here. Hope this works.
Anyways, im starting from basic and just learnt the "if" statement. But when i tried to create my own version its not working. My program below is showing all three cout results even if i enter only one option(attack or run or hide). It was working fine when there was just one "if" statement. I tried the "else if" too but then it only printed out the result "you have attacked" no matter what i chose. :( I used the search bar for similar questions that might have already been answered but didnt find much that could help me.
If there are similar questions then i'd appreciate if you could point me towards it, although i'd really be grateful if you could point out what my mistakes are specifically.
Thnx~
#include <iostream>
#include <string>
using namespace std;
int main(){
cout<<"Welcome to the jungle!!!"<<endl;
cout<<"--------"<<endl;
cout<<"Enemies approaches! \n Choose your next move! \n";
cout<<"Attack / Run / Hide \n\n\n";
string choice;
cin>>choice;
if(choice=="Attack"||"attack")
{
cout<<"You have attacked!"<<endl;
}
if(choice=="Run"||"run")
{
cout<<"You start running!"<<endl;
}
if(choice=="Hide"||"hide")
{
cout<<"You hide in a cave!"<<endl;
}
return 0;
}
if(choice=="Attack"||"attack")
does not mean "if choice contains "Attack", or choice contains "attack", do the thing".
It means "if choice contains "Attack", or "attack" is true, do the thing".
In pseudo-code, you expect:
if choice is the string "Attack"
or choice is the string "attack"
do a thing
but the or splits the statement into halves, and the second half doesn't mention the variable choice at all. It breaks down more like
if choice is the string "Attack"
or the string "attack" on its own is somehow true, whatever that might mean
do a thing
Since "attack" is a pointer to a char array, being true means it is not NULL, which is always the case, so this branch is always entered.
To express what you mean, write instead:
if(choice=="Attack"||choice=="attack")
Welcome to C/C++ world.
As you have already read in tutorials or book, the content inside the parens of an if has to be a boolean value. Now, a lot of stuff can be converted automatically to bool and as a condition for an if.
In particular, anything that can be converted to an int will, in turn, have a bool value attached to it. Pointers are of such kind.
If the value is different from 0 then the result will be -> true
0 otherwise.
Writing if(choice=="Attack"||"attack") you are telling the compiler to execute the content of the if either if the content of choice is equal to the string Attack or if the the pointer to the underlying const char* attack is not zero.
attack is a valid string which mean its value is not zero which in turn means you are getting a true out of it.
Same goes for all the others ifs. The second part of all you ifs are true cause they are not null pointers.
Change the all the ifs as the following: if(choice=="Attack"||choice=="attack") and the problem will be fixed.
You must use
if(choice=="Attack"||choice=="attack")
{
cout<<"You have attacked!"<<endl;
}
OR( || ) is a boolean operator.
So Anything other than 0 gives an impression of 1 in boolean. Thus the syntax in if code is always executed. This is the reason for in the else if case first statement is always executed (and further statements are skipped).
Also, using namespace std; is a bad practice since it makes our code confined to just one std library. instead you must use std:cout;
Suppose I created a character array say of 20 bytes and prompts the use to input their name provided their name should not be more than 20 characters...
For Example:
char Name[20];
gets(Name);
Now suppose his name is abcdefghijklmnopqrstuvwxyz
But as soon as he enters abcdefghijklmnopqrst, the Name should not take any further input... Neither the further input provided by the user should appear on the console screen... Only the cursor should blink until he presses enter. So how to do it??
More Information
Operating System: Windows 7
Compiler: Visual C++ 2010 Express
The manpage states:
Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.
So you could use fgets:
char *fgets(char *s, int size, FILE *stream);
Yet the input sequence doesn't stop yet; however, you are no longer running into undefined behaviour and security holes, iff used correctly.
You should better use C++ facilities like std::string, std::getline, and the standard iostreams. They won't enable you stopping input, however, they prevent security holes when used in the canonical manner.
Summary of Standard Alternatives:
gets() can not be used correctly. People will may die when you use this (you wouldn't find a smile on my face as I am not kidding). There is provably no correct way to use it. Do not forget it, but throw it out of your toolbox now.
fgets() can be used correctly, but there's a lot of opportunity to misuse it.
iostreams and strings are automatically used correctly. Use them.
Unforunately, there is no builtin solution to read at max N characters from input without having to discard superfluous characters typed in. You would have to use a 3rd-party library or roll your own.
Here's silly answer:
If you want for example the user to enter a name with maximum 20 characters
Create a char array with. size[20]
Ask the user to enter the size of the name and check the validity of the number if its less than or equal.20 then move on and add the name else ask the user to enter the size again.
You can use a string instead of a char but that won't make sure that the user actually followed the size rule
For example a user can enter a size 10 and the program will allow him to enter the name but once he's allowed if you are using the.string he can write as many as he wishes.
OR using a char array. for name with 20 or less.characters
For example the code would need a simple for loop
Since we already have the size given which is less than or equal.20
For(int i =0; i<20; i++)
Cin>>char[i]
Then you can assign the characters into a string.
So this is a problem that I've been having since I started programming (Not that long ago. I still don't know why I started with C++). When I have some integer variables and the user's input defines them, if the user inputs something other than an integer the program freaks out and runs an endless loop of the last command it was given. I don't think sample code is needed but if it is I can make a basic example pretty easily.
If you want to know exactly what your mistake was, then we'd need to see your code, but the usual idiom is like this:
int i;
while (std::cin >> i) {
// do something with the user's input, i
}
if (std::cin.fail()) {
std::cout << "not a number!\n";
}
If failure occurs and you want to get past the invalid input so that the user can try again, first call cin.clear(), then either cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n') to ignore the whole line, or std::string s; std::cin >> s; to ignore a whitespace-separated word.
Beware that because the second case actually constructs the string in memory, the user could input a few gigabytes without a space, and the program will fail. That's usually fine if the input is from a terminal, it's the user's own stupid fault. It might be less fine if the input is from an HTTP request or other untrusted source, so some time in future you might end up worrying about it...
Check this out Guess the number - Infinite loop when bad read
When programming always, and i mean always, validate your input.
Check if the input you get is sane.
What i mean by that if you get something that is supposed to be int check if it is.
Convert it if it is not.
If you get a string check if it is in bounds, meaning is it to long, to short, to whatever.
cin
Would be the Term to Google for in your case.
My brother recently started learning C++. He told me a problem he encountered while trying to validate input in a simple program. He had a text menu where the user entered an integer choice, if they entered an invalid choice, they would be asked to enter it again (do while loop). However, if the user entered a string instead of an int, the code would break.
I read various questions on stackoverflow and told him to rewrite his code along the lines of:
#include<iostream>
using namespace std;
int main()
{
int a;
do
{
cout<<"\nEnter a number:"
cin>>a;
if(cin.fail())
{
//Clear the fail state.
cin.clear();
//Ignore the rest of the wrong user input, till the end of the line.
cin.ignore(std::numeric_limits<std::streamsize>::max(),\
'\n');
}
}while(true);
return 0;
}
While this worked ok, I also tried a few other ideas:
1. Using a try catch block. It didn't work. I think this is because an exception is not raised due to bad input.
2. I tried if(! cin){//Do Something} which didn't work either. I haven't yet figured this one out.
3. Thirdly, I tried inputting a fixed length string and then parsing it. I would use atoi(). Is this standards compliant and portable? Should I write my own parsing function?
4. If write a class that uses cin, but dynamically does this kind of error detection, perhaps by determining the type of the input variable at runtime, would it have too much overhead? Is it even possible?
I would like to know what is the best way to do this kind of checking, what are the best practices?
I would like to add that while I am not new to writing C++ code, I am new to writing good standards compliant code. I am trying to unlearn bad practices and learn the right ones. I would be much obliged if answerers give a detailed explanation.
EDIT: I see that litb has answered one of my previous edits. I'll post that code here for reference.
#include<iostream>
using namespace std;
int main()
{
int a;
bool inputCompletionFlag = true;
do
{
cout<<"\nEnter a number:"
cin>>a;
if(cin.fail())
{
//Clear the fail state.
cin.clear();
//Ignore the rest of the wrong user input, till the end of the line.
cin.ignore(std::numeric_limits<std::streamsize>::max(),\
'\n');
}
else
{
inputCompletionFlag = false;
}
}while(!inputCompletionFlag);
return 0;
}
This code fails on input like "1asdsdf". I didn't know how to fix it but litb has posted a great answer. :)
Here is code you could use to make sure you also reject things like
42crap
Where non-number characters follow the number. If you read the whole line and then parse it and execute actions appropriately it will possibly require you to change the way your program works. If your program read your number from different places until now, you then have to put one central place that parses one line of input, and decides on the action. But maybe that's a good thing too - so you could increase the readability of the code that way by having things separated: Input - Processing - Output
Anyway, here is how you can reject the number-non-number of above. Read a line into a string, then parse it with a stringstream:
std::string getline() {
std::string str;
std::getline(std::cin, str);
return str;
}
int choice;
std::istringstream iss(getline());
iss >> choice >> std::ws;
if(iss.fail() || !iss.eof()) {
// handle failure
}
It eats all trailing whitespace. When it hits the end-of-file of the stringstream while reading the integer or trailing whitespace, then it sets the eof-bit, and we check that. If it failed to read any integer in the first place, then the fail or bad bit will have been set.
Earlier versions of this answer used std::cin directly - but std::ws won't work well together with std::cin connected to a terminal (it will block instead waiting for the user to input something), so we use a stringstream for reading the integer.
Answering some of your questions:
Question: 1. Using a try catch block. It didn't work. I think this is because an exception is not raised due to bad input.
Answer: Well, you can tell the stream to throw exceptions when you read something. You use the istream::exceptions function, which you tell for which kind of error you want to have an exception thrown:
iss.exceptions(ios_base::failbit);
I did never use it. If you do that on std::cin, you will have to remember to restore the flags for other readers that rely on it not throwing. Finding it way easier to just use the functions fail, bad to ask for the state of the stream.
Question: 2. I tried if(!cin){ //Do Something } which didn't work either. I haven't yet figured this one out.
Answer: That could come from the fact that you gave it something like "42crap". For the stream, that is completely valid input when doing an extraction into an integer.
Question: 3. Thirdly, I tried inputting a fixed length string and then parsing it. I would use atoi(). Is this standards compliant and portable? Should I write my own parsing function?
Answer: atoi is Standard Compliant. But it's not good when you want to check for errors. There is no error checking, done by it as opposed to other functions. If you have a string and want to check whether it contains a number, then do it like in the initial code above.
There are C-like functions that can read directly from a C-string. They exist to allow interaction with old, legacy code and writing fast performing code. One should avoid them in programs because they work rather low-level and require using raw naked pointers. By their very nature, they can't be enhanced to work with user defined types either. Specifically, this talks about the function "strtol" (string-to-long) which is basically atoi with error checking and capability to work with other bases (hex for example).
Question: 4. If I write a class that uses cin, but dynamically do this kind of error detection, perhaps by determining the type of the input variable at runtime, will it have too much overhead? Is it even possible?
Answer: Generally, you don't need to care too much about overhead here (if you mean runtime-overhead). But it depends specifically on where you use that class. That question will be very important if you are writing a high performance system that processes input and needs to have high throughout. But if you need to read input from a terminal or a file, you already see what this comes down to: Waiting for the user to input something takes really so long, you don't need to watch runtime costs at this point anymore on this scale.
If you mean code overhead - well it depends on how the code is implemented. You would need to scan your string that you read - whether it contains a number or not, whether some arbitrary string. Depending on what you want to scan (maybe you have a "date" input, or a "time" input format too. Look into boost.date_time for that), your code can become arbitrarily complex. For simple things like classifying between number or not, I think you can get away with small amount of code.
This is what I do with C but it's probably applicable for C++ as well.
Input everything as a string.
Then, and only then, parse the string into what you need. It's sometimes better to code your own than try to bend someone else's to your will.
In order to get the exceptions with iostreams you need to set the proper exception flag for the stream.
And I would use get_line to get the whole line of input and then handle it accordingly - use lexical_cast, regular expressions (for example Boost Regex or Boost Xpressive, parse it with Boost Spirit, or just use some kind of appropriate logic
What I would do is twofold: First, try to validate the input, and extract the data, using a regular expression, if the input is somewhat not trivial. It can be very helpful also even if the input is just a series of numbers.
Then, I like to use boost::lexical_ cast, that can raise a bad_ lexical_ cast exception if the input cannot be converted.
In your example:
std::string in_str;
cin >> in_str;
// optionally, test if it conforms to a regular expression, in case the input is complex
// Convert to int? this will throw bad_lexical_cast if cannot be converted.
int my_int = boost::lexical_cast<int>(in_str);
Forget about using formatted input (the >> operator) directly in real code. You will always need to read raw text with std::getline or similar and then use your own input parsing routines (which may use of the >> operator) to parse the input.
How about a combination of the various approaches:
Snag the input from std::cin using std::getline(std::cin, strObj) where strObj is a std::string object.
Use boost::lexical_cast to perform a lexical translation from strObj to either a signed or unsigned integer of largest width (e.g., unsigned long long or something similar)
Use boost::numeric_cast to cast the integer down to the expected range.
You could just fetch the input with std::getline and then call boost::lexical_cast to the appropriately narrow integer type as well depending on where you want to catch the error. The three step approach has the benefit of accepting any integer data and then catch narrowing errors separately.
I agree with Pax, the simplest way to do this is to read everything as string, then use TryParse to verify the input. If it is in the right format, then proceed, otherwhise just notify the user and use continue on the loop.
One thing that hasn't been mentioned yet is that it is usually important that you test to see if the cin >> operation worked before using the variable that supposedly got something from the stream.
This example is similar to yours, but makes that test.
#include <iostream>
#include <limits>
using namespace std;
int main()
{
while (true)
{
cout << "Enter a number: " << flush;
int n;
if (cin >> n)
{
// do something with n
cout << "Got " << n << endl;
}
else
{
cout << "Error! Ignoring..." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
return 0;
}
This will use the usual operator >> semantics; it will skip whitespace first, then try to read as many digits as it can and then stop. So "42crap" will give you the 42 then skip over the "crap". If that isn't what you want, then I agree with the previous answers, you should read it into a string and then validate it (perhaps using a regular expression - but that may be overkill for a simple numeric sequence).