How do I combine user input with with if statements? - c++

I'm making a program. For the program to work, I need to know how to combine user input (cin) with if statements, for example, something like:
start:
(program)
cout << "What would you like to do?";
if cin = "end" goto end;
if cin = "redo" goto start;
end:
return 0;
I know this isn't valid code, but I hope you understand what I'm trying to do. I need to know how to do this in C++, if possible, and if not, how to do the same thing.
Also, in Batch, doing something like :start: "bookmarks" the program, so that you can do a "GOTO start" command to jump back to it. How do you do that in C++?

This question is a little bit vague, but I'm trying to help you as good as I can.
First of all, the code for reading in a string is:
std::string input;
std::cin >> input;
(Of course, this requires that you include #include <string> and #include <iostream>).
Secondly, there is support for goto and labels in C++. But in most cases, there are better, more robust and more maintainable solutions to express yourself with. You want to learn more about while and for loops.
I hope that this answer provides some hints for you, where to start. Any basic C++ book will cover these topics and you should probably get one, if you really want to learn C++ by yourself.
Here is a small example that covers your questions:
#include <string>
#include <iostream>
int main( int, char ** )
{
std::string input;
while( true )
{
std::cout << "What would you like to do?" << std::endl;
std::cin >> input;
if( input == "redo" )
{
continue;
}
else if( input == "end" )
{
break;
}
else
{
std::cout << "Invalid input: " << input << std::endl;
}
}
return 0;
}

Related

std::cin is not accepting input

I am trying to get the first program working from "Accelerated C++".
I was having trouble getting the program to stay open without shutting down, so I decided to put a int i = 0; and cin >> i; after main() returns. Unfortuantely, it doesn't seem to take any input, no matter where I put that cin statement.
If it helps, it is using an istream reference to accept cin input. I can't figure out how to enter code on this site.
For most of my adult life, I used system("PAUSE") without any problems to keep the program window open. It's not good for real-time systems, of course, but it's simple and powerful because you're actually running a console command and it can be used to make console scripts.
#include <iostream>
#include <cstdlib>
using namespace std;
inline void Pause () { cout << "\n"; system ("PAUSE); }
int main () { Pause (); }
This solution is not 100% portable, but it will work on PCs. A more portable solution is:
#include <conio.h>
#include <cstdio>
void Pause() {
cout << "\nPress any key to continue...";
while (_getch() < 0)
;
}
cin is good for doing simple things, but what I do is wrap the std library in C functions and use those because it can dramatically improve compile times to hide the std library headers in the implementation files.
The prefered method in C++ is std::getline() using std::string, though many teachers won't let you use that.
With cin, you also have to clear input errors and use ignore() to throw away a specific number of chars.
#include <string>
string foo;
cout << "Why do they always use foo? ";
getline (cin, foo);
cout << "You just entered" << foo;
int bar;
cout << "\nThe answer is because programmers like to go to the bar."
"\nHow many times have you seen foo bar in an example? ";
while (!(cin >> bar)) {
cout << "\nPlease enter a valid number: ";
cin.clear ();
cin.ignore (10000, '\n');
}
My many years of experience have taught me to put the \n char at the beginning of output lines as opposed to the end of them.

Why is this code exiting at this point?

I'm new to C++. I stumbled upon one tutorial problem, and I thought I'd use the few things I have learnt to solve it. I have written the code to an extent but the code exits at a point, and I really can't figure out why. I do not want to go into details about the tutorial question because I actually wish to continue with it based on how I understood it from the start, and I know prospective answerers might want to change that. The code is explanatory, I have just written few lines.
Here comes the code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
double average_each_student() {
cout << "\n>Enter your scores seperated by spaces and terminated with a period\n"
<< ">Note: scores after total number of six will be truncated.\n"
<< endl;
double sum = 0, average = 0;
int user_input, counter = 0;
const double no_of_exams = 6;
while(cin >> user_input) {
++counter;
if(counter < 5) sum += 0.15 * user_input;
else if(counter > 4 && counter < 7) sum += 0.20 * user_input;
}
return sum / no_of_exams;
}
int reg_number() {
cout << "Enter your registration number: " << endl;
int reg_numb;
cin >> reg_numb;
return reg_numb;
}
int main() {
vector<int> reg_num_list;
vector<double> student_average;
reg_num_list.push_back(reg_number());
student_average.push_back(average_each_student());
string answer;
cout << "\n\nIs that all??" << endl;
//everything ends at this point.
//process returns 0
cin >> answer;
cout << answer;
}
The code exits at cout << "\n\nIs that all??" << endl;. The rest part after that is not what I intend doing, but I'm just using that part to understand what's happening around there.
PS: I know there are other ways to improve the whole thing, but I'm writing the code based on my present knowledge and I wish to maintain the idea I'm currently implementing. I would appreciate if that doesn't change for now. I only need to know what I'm not doing right that is making the code end at that point.
The loop inside average_each_student() runs until further input for data fails and std::cin gets into failure state (i.e., it gets std::ios_base::failbit set).
As a result, input in main() immediately fails and the output of what was input just prints the unchanged string. That is, your perception of the program existing prior to the input is actually wrong: it just doesn't wait for input on a stream in fail state. Since your output doesn't add anything recognizable the output appears to do nothing although it actually prints an empty string. You can easily verify this claim by adding something, e.g.
std::cout << "read '" << answer << "'\n";
Whether it is possible to recover from the fail state on the input stream depends on how it failed. If you enter number until you indicate stream termination (using Ctrl-D or Ctrl-Z on the terminal depending on what kind of system you are using), there isn't any way to recover. If you terminate the input entering a non-number, you can use
std::cin.clear();
To clear the stream's failure stated. You might want to ignore entered characters using
std::cin.ignore(); // ignore the next character
or
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// ignore everything up to the end of the line
use cin.clear(); before cin >> answer; That will fix the problem. But you are not controlling the input. it just runs out to cin..

Control stdin and stdout of second program (pipes/piping?)

I've been wondering how to go about running a program within another program where the the main process can output into the stdin of the secondary process as well as have that second process output to the input to the primary one.
The closest I have come to finding a term for this idea is pipes and forks but I don't quite get the examples i've seen. I've only seen ones where the same program is using pipes to launch itself again. Additionally all of these examples assume that that the programmer is writing/has access to both program's source code.
I would like to be able to interface in this way with programs that are already compiled. Here's an example of what I would like to be able to do:
This is the "compiled" program-
#include <iostream>;
using namespace std;
int main(){
int answer = 42;
int guess = 0;
do{
cout << "Guess a number..." << endl;
cin >> guess;
if(guess<answer)
cout << "Guess Higher!" << endl;
else if(guess>answer)
cout << "Guess Lower!" << endl;
}while(answer!=guess);
cout << "You win!";
return 0;
}
This is the "parent" program-
#include <iostream>;
using namespace std;
int main(){
//Code executing and connecting the other program
//while cin/cout would be nice for keeping it clean, other methods of doing this are fine
//I used cin/cout as placeholders to try and make what I am asking clearer
String out;
cin >> out;//Load initial prompt
int high=100, low=0;
do{
cout << (high+mid)/2 << endl;
cin >> out;//Load response
if(out.compare("Guess Higher!"))
low = (high+low)/2;
else
high = (high+low)/2;
}while(out.compare("You win!")!=0);
return 0;
}
The idea here is that my "parent" program could play this game for me. It would make a guess, view the response, use some logic to decide what to do next, guess, repeat until it wins. This particular example is pretty useless but the same general idea of controlling one program with another has a lot of uses. This is just a hypothetical demo of would I would like to be able to do.
Thanks to anyone kind enough to take time out of their day to help.

Using an ASCII value as a condition

The following program should read some integer values from input and store them into an array until the user presses "Esc" key, but i cannot figure out how to do that. I have tried to use it's ASCII value as a condition but it doesn't work, or I'm doing something wrong.Could somebody please help me? Here is the code :
void main(){
int i=0, a[MAX];
cout <<"Please enter several integer numbers and press Esc when you want to finish" << endl;
while ((i != char(27)) && (i < MAX)) {
cin >> a[i];
i++;
}
There are several problems here. The first, and most important,
is that most systems will do line oriented input, which means
that they will pick up a lot of control characters (including,
probably, ESC) and do something with them internally, rather
than returning them to you; it might not even be possible to
ever see an ESC in the input.
For the rest, there are several problems with your code. The
first is that you're testing against the index into the array
(where you'll put the next character), not against anything
you've read. The second is that you're inputting int, so you
won't see any individual characters; just the results of the
conversion of your input. (In fact, if an ESC character does
get through, you'll end up with std::cin in a error state.)
The third is that you never test whether the input has
succeeded.
A better solution would be to adopt some other convention for
the input: say one number per line, with an empty line signaling
the end. In that case, you could write something like:
std::vector<int> a;
std::string line;
std::cout << "..." << std::endl;
while ( std::getline( std::cin, line ) && !line.empty() ) {
std::istringstream parse( line );
int value;
parse >> value >> std::ws;
if ( !parse ) {
std::cout << "That wasn't an integer, try again" << std::endl;
} else if ( parse.get() != EOF ) {
std::cout << "Extra garbage at end of line, ignoring it" << std::endl;
} else {
a.push_back( value );
}
}
(You'll note that I've used std::vector, since you don't know
up front how many inputs you'll get.)
If you really want to use ESC, you'll probably need a third
party library, along the lines of curses, to do raw input,
reading one character at a time, and collecting the digits into
a string, for conversion using std::istringstream.
Do not do this use James method its much better and will run on evrything but just for the sake of answering a question you can do this. This will not work on all platforms It works on visual c++ compiler.
# include <iostream>
# include <conio.h>
# include <vector>
using namespace std;
int main()
{
char key;
vector<int> a;
int temp = 0;
while ((key = getch()) != 27)
{
cin >> temp;
a.push_back(temp);
}
for (int i = 0 ; i < a.size() ; i++)
{
cout << a.at(i) << endl;
}
printf("Exit");
cout << endl;
system("Pause");
return 0;
}
Edit: Programs clearer now. Note this program should not be used it is very platform and compiler dependant.

What is the better implementation for this loop?

I need to implement a loop where I have to ask the user, and then check the validity of the input (in this case it is necessary to print that is an invalid number). What is the better way to implement it?
Our programming professor does not let us use break, and for(;;) since, as he says, it is a bad practice. Is that correct?
Example 1:
int i = 0;
while(i == 0) {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
}
Example 2:
int i = 0;
do {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
} while (i == 0) // Better while(true) and use break ?
Example 3:
int i = 0;
for ( ;; ) {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
else
break;
}
In your case the second construct (do..while) is the most intuititve for the reader to look at what the code does, and this is important.
The first one isn't so bad, the last one is poor a "for" construct is usually used where there are a limited number of iterations with the limit set in advance. It doesn't have to be, but intuitively that is how a for loop is used.
(Incidentally if the user entered a string that isn't a number you would have to clear the fail flag on cin, but that is not really the question being asked here).
Don't you need to accept zero as an integer? It's good practice to not rely on input numbers having a special meaning.
If the meaning of the loop is to loop infinitely until the task is done there's nothing wrong with clearly saying while(true). I would probably do something more like this (requires C++11): (or use boost lexical_cast)
#include <iostream>
#include <string>
#include <stdexcept>
int infini_asker(){
while (true) {
std::cout << "...: ";
std::string tmp;
std::cin >> tmp;
int i;
try{
i=std::stoi(tmp);
}catch(std::invalid_argument){
continue;
}catch(std::out_of_range){
continue;
}
return i;
}
}
int main(){
int num=infini_asker();
std::cout << " got:" <<num << std::endl;
}
A modification of Example 1 looks to be the best form:
while(true) {
cout << "...: ";
cin >> i;
/*... other stuff ...*/
// Do your input validation here:
// Note that it's much better to whitelist what is
// acceptable input as opposed to checking all of the
// possible cases of invalid input
if (...) { // where .. is the condition for valid input
break
}
}
do-while loops should be reserved for special cases where you want to get the point across that the nested logic should be executed at least once. Anything you can do with do-while, you can do with while(...)
for(;;) is less familiar syntax for a lot of programmers (I didn't know what it meant a year ago), whereas while(true) is much more obvious.
They all work. Like Shmiddty says a for(;;) is not a good programming habit. I would do it like example 2, but I am not a professional programmer.