do while and switch error - c++

The error is when I run the program and type n to end choosing
it doesn't end and keeps repeating the first cout and the default value:
#include <iostream>
using namespace std;
int main()
{
int x;
float y,result=0,paid,change;
do {
cout<<"enter another choose or press (n/N) to end choosing ";
cin>>x;
switch (x)
{
case 1:
{
int a=5;
cout<<"enter the wighte you want in (Kg) : ";
cin>>y;
result=a*y;
break;}
default:
cout<<"wrong choooose "<<endl;
}
}
while (x='n');
cout<<"your total= "<<result<<endl;
cout<<"mony value paid = ";
cin>>paid;
change =paid-result;
cout<<"the change = "<<change<<endl;
return 0;
}

The problem is that x is an integer, which you then compare to a character literal.
This works well when using old C-style standard I/O, which uses int instead of char, but doesn't work in C++ where the types are distinct. This means that the input on the line
cin>>x;
will fail if you do not enter a valid integer.
Change the type of x to char and it should work.
There is also the problem with the assignment instead of the condition inside while.

Sorry, I totally missed that you're using C++ I/O here.
You declare x as an int, yet you enter the character literal 'n'. The conversion will fail with C++ I/O streams, so x is never set. Don't confuse your data types; if you want to read a char then read a char, same for int.
Try something like this instead:
int x = 0;
do {
if(!(cin >> x)) {
cout << "enter a valid number" << endl;
// clear fail flag
cin.clear();
// consume newline
cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
} else {
// your logic here
}
} while( x != -1 );
while (x='n');
That is not a comparison, it is an assignment, and the character 'n' when converted to an integer will always evaluate to true, so your loop never ends.
Your next problem will be that you want to exit the loop when the input is 'n', not the other way around, so it should be...
while(x != 'n');
Also realize that, if the user enters 110, the loop will exit. x is an int, and the integral value of the character literal 'n' is 110. It will also fail for 'N'.

Related

Unable to detect enter key in C++

Now, before this question gets marked for duplicate. I have already gone through most of the questions and their relative answers of C++. These are the links that I have tried and none of them work for me. It maybe because they are using an older version of C++, and I have the latest version of C++. Here are the links that I have tried:
Detecting ENTER key in C++
https://www.sololearn.com/Discuss/1863352/how-can-i-check-that-user-press-enter-key-in-c
http://www.cplusplus.com/forum/beginner/2624/
https://www.dreamincode.net/forums/topic/398680-detect-enter-key/
Now, with the duplicates out of the way. I am making an expression calculator. So, for example if the user input is: 2+2*6*9/9, then the output should be 14.
The code where I suspect that the problem lies is in:
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
using std::string;
using std::vector;
void clear();
void error(string message);
int main() {
cout << "Enter an expression: ";
double l_Value = 0, r_Value = 0, result = 0, count = 0, previous_number;
char op;
while (cin >> l_Value) { // 1+2*3+6-4/2+3
if (!cin) {
error("Invalid operand entered!");
}
else {
bool is_Error = 0; // false
vector<double> numbers;
numbers.push_back(l_Value);
previous_number = l_Value;
while (cin >> op) {
if (op == '\0') {
break;
}
cin >> r_Value;
switch (op)
{
case '+':
numbers.push_back(r_Value);
previous_number = r_Value;
break;
case '-':
numbers.push_back((-1 * r_Value));
previous_number = (-1 * r_Value);
break;
case '*':
numbers.pop_back(); // take out the number
r_Value *= previous_number;
numbers.push_back(r_Value);
previous_number = r_Value;
break;
case '/':
if (r_Value == 0) {
error("Sorry, division by zero has occured. Please re-evaluate your expression!\n");
is_Error = 1; // true
break;
}
else {
numbers.pop_back(); // take out the number
previous_number /= r_Value;
numbers.push_back(previous_number);
break;
}
}
}
if (!is_Error) {
for (int i = 0; i < numbers.size(); i++) {
result += numbers[i];
}
cout << result << '\n';
}
numbers.clear();
result = 0;
l_Value = 0;
r_Value = 0;
}
cout << "Enter an expression: ";
}
clear();
return 0;
}
None of the links above seemed to work for me.
When I press the Enter key, it expects me to give another input, and that is not supposed to happen. So when I used cin.get() == 'n' or cin.get() == (int)'\n', it expects for another input. But, when I have an 'x' at the end of the expression, it works perfectly fine. So, I need the "cin" operator to help me detect an Enter character at the end of the expression and then terminate the program.
Here, is a sample run of a program with 'x':
[![running as x-terminator][1]][1]
[1]: https://i.stack.imgur.com/ORPQa.png
When I try the above solution such as "cin.get() == '\n':
Then, I thought that maybe it is reading the null character and so, I tried if (op == '\0'):
For the enter key and null character I had to press Ctrl+Z to terminate the program. Please help!
As, mentioned by user #idclev, I already have a string program that works, but I am trying to avoid using string to calculate any expressions! So, if I could detect an enter key pressed using a character datatype that would be great!
I avoided strings to avoid parsing through the text
That argument is moot. What you can read from cin you can also read from a std::string, no difference whatsoever. You just need to add one step:
#include <iostream>
#include <string>
#include <sstream>
int main( ){
std::string x;
std::cin >> x;
if (x == "") {
std::cout << "user pressed enter (and nothing else)";
} else {
double y;
std::stringstream ss{x};
ss >> y;
std::cout << y;
}
}
This will read one std::string. If user only hit enter then the string will be empty. If the user entered something the else branch will be taken and you can extract the number from the string in the same way you did extract the number from cin (via using a std::stringstream).
If you have more than one number in the input you need to use getline to read the string, because cin will (by default) only read till the next whitespace.
Again...
If I used a string, I would have a tough time in extracting single-digit and two-digit or n-number of digits in a string. The double data type does that for me
You can read single-digit or any number of digits from a stringstream in exactly the same way as you read them from cin.
I already made a program with string in it. I was trying to avoid string to see how much faster would it be without string.
It won't be any faster. Constructing the string and the stringstream is maybe in the order of microseconds. A user entering input is in the order of seconds, maybe milliseconds when they are typing very fast.
Your approach cannot work because hitting enter is not considered as a character. Trying to read a character when there is none in the stream will fail. It will not set the character to \n or \r.
On the outer loop, you are trying to read a double, but you keep pressing enter. There is no input to evaluate, so it keeps trying to read a double. You can get out of it by ending the input stream with ^Z, or you can give it any actual content to read, and it will try to make it into a double (which is what your code explicitly told it to wait for).
Basically, when you press enter, it's ignoring it because
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
Extracts as many characters as possible from the stream and inserts them into the output sequence controlled by the stream buffer object pointed by sb (if any), until either the input sequence is exhausted or the function fails to insert into the object pointed by sb.
Try experimenting with this to see what is happening.
#include <iostream>
#include <vector>
#include <string>
int main() {
double x;
std::cin >> x;
std::cout << "read this value: " << x << std::endl;
// this is what while or if will look at
bool success = !std::cin.fail();
if (success)
std::cout << "success" << std::endl;
else
std::cout << "failure, loop will exit" << std::endl;
return 0;
}
What you should want (in my opinion) is a function that takes the expression as a string, and returns the result, so you can write unit tests, and make sure the function works. You can use this function with any expression that you can put in a string. It doesn't HAVE to be typed in by a user.
If you want the user to type in the experession, it's a lot easier to just use getline() then pass the string to your function. The big problem with using cin on each variable and character is that the user has no idea which datetype is expected right then. Granted, it's not hard to guess with an expression, but you wrote it and debugged it and still didn't know which cin you were failing to get the right datatype to. (this is normal, btw -- been there, which is why I getline and parse separately)

Why "keep_window_open()" doesn't wait for a character to be entered?

I'm new to programming, and I'm trying to learn C++ by myself, and I'm following "Programming principles and practice using C++".
I was trying to do an exercise that, after various other steps, asked me to
" ...change the body of the loop so that it reads just one double each time around. Define two variables to keep track of which is the smallest and which is the largest value you have seen so far. Each time through the loop write out the
value entered. If it’s the smallest so far, write the smallest so far after the number. If it is the largest so far, write the largest so far after the number".
I wrote the following code so far:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
inline void keep_window_open() { cout<<"\nType a character to exit: "; char ch; cin>>ch; }
int main()
{
double val1 = 0, smallest = 0, largest = 0;
int flag = 0;
while (cin >>val1) {
if (val1=='|')
break;
else
cout <<val1 <<'\n';
if (flag==0) {
smallest = val1;
cout <<smallest <<" it's the smallest value so far.\n";
}
if (val1<smallest) {
smallest = val1;
cout <<smallest <<" it's the smallest value so far.\n"; }
else if (val1>largest) {
largest = val1;
cout <<largest <<" it's the largest value so far.\n"; }
++flag;
}
keep_window_open();
return 0;
}
My problem is that when I input a character, e.g. 'c', the program ends, although the program should end, hypothetically, only when I enter '|', and I get:
c
Type a character to exit:
Process returned 0 (0x0) execution time : ...
Press any key to continue.
and "keep_window_open()" doesn't wait for a character to be entered. I just can't understand what happens, and why. Does anyone have a clue?
Well, I think the problem is in the way you defined your loop expression.
Neither cin nor its operator ">>" return a true / false value that you can work with. They return an iStream object which could be a dubious translation to true or false via an automated casting that happens behind the curtains. They will however return null when the input cannot be set inside your variable like in the case of trying to put 'c' into a double, and null translates into false.
What I suggest for you is to create a simple while(true) loop and when you get the "|" character from the user(as a string) you break the loop. until then the loop continues. then inside the loop parse your value and work on it according to your logic(minimum / maximum)
Problem
while (cin >>val1) reads input into a double. If you input something that cannot be read as a double like "|" then this will fail and cause your loop to exit.
You then try to read more input while cin is in an error state.
Solution
Call cin.clear() to first clear any error flags and then cin.ignore(1000, '\n') to throw away anything left hanging in the input stream.
inline void keep_window_open()
{
cout << "\nType a character to exit: ";
char ch;
cin.clear();
cin.ignore(1000, '\n');
cin >> ch;
}
Note
if (val1=='|')
break;
This code will never be true because if you try to input the pipe character your while loop will fall through before ever getting to it.

C++: Why does this code run an endless loop if the input was not integral?

I have this simple code that duplicate a string by using either a reference or a pointer (I'm a beginner), and I would like to make it determine whether the input is integral or not because if it wasn't, it keeps looping for some reason. I've tried using cin.clear() but it doesn't seem to work..
Here is the code:
#include <iostream>
#include <string>
#include "test.h"
using namespace std;
int main() {
while (true) {
cout << "Type something: ";
string hi;
cin >> hi;
cout << "Choose a method to change it:\n1. By reference.\n2. By using pointers.\n";
start:
int i;
cin >> i;
if (cin.fail())
cin.clear();
switch (i) {
case 1:
changestringref(hi);
cout << hi << '\n';
break;
case 2:
changestringptr(&hi);
cout << hi << '\n';
break;
default:
cout << "Choose by typing either 1 or 2: ";
goto start;
break;
}
}
}
Whenever I type a string (at the second input), it keeps looping this sentence: "Choose by typing either 1 or 2: Choose by typing either 1 or 2: Choose by typing either 1 or 2: "etc.
How can I solve this problem? And why isn't cin.clear working? isn't it supposed to clear the input from the last time cin was used or am I wrong? O.o
Thanks in advance :D
And why isn't cin.clear working? isn't it supposed to clear the input from the last time cin was used or am I wrong?
Not quite. It's supposed to Set[s] a new value for the stream's internal error state flags.. clear() without argument sets goodbit and clears the fail() state, but leaves any unprocessed input untouched.
Let's assume you entered 'x'. Since 'x' is not a number, cin >> i sets failbit, and does not consume input (actually, it pushes the already consumed x back into the input buffer, but that's another story).
This is behavior documented somewhat obscurely in num_get::get(). The returned iterator (i.e. the stream) points right before the first character that could not be parsed.
So next time, after the goto start; you read x again. Same input, same result, hence the endless loop.

For loop not letting me change input

The point of this program is for the user to enter the grade of a certain amount of students up to 50, from a range of grades A,B,C,D, or F. At the end, the program is then supposed to show how many students got each grade. Whenever I test the following code, whatever I input for the for loop repeats every time, such that if I input for it to do the grades 3 students, whatever letter I enter for student 1 will be the same grade for every student, so if one student has an A, they all will have an A. I also have to use arrays for this program because it's for college. Sorry if there's not enough information, this is my first time posting.
#include<iostream>
#include<iomanip>
#include<string>
void gradeTotals();
using namespace std;
int x,z,a=0,b=0,c=0,d=0,f=0,i=0;
char grade[50];
int main()
{
cout<<"Please enter the number of students"<<endl;
cin>>x;
for (i=0;i<x;i++)
{
int y;
y=i+1;
cout<<"Please enter a letter grade of A,B,C,D, or F for student "<<y<<endl;
cout<<"All grades must be uppercase"<<endl;
cin>>z;
grade[i]=z;
gradeTotals();
}
}
void gradeTotals()
{
if (grade[i]=='A')
{
a++;
}
else if (grade[i]=='B')
{
b++;
}
else if (grade[i]=='C')
{
c++;
}
else if (grade[i]=='D')
{
d++;
}
else if (grade[i]=='F')
{
f++;
}
cout<<a<<endl;
cout<<b<<endl;
cout<<c<<endl;
cout<<d<<endl;
cout<<f<<endl;
}
It looks like your if statements are not doing what you expect. For instance:
if (grade[i]='B')
{
// This code will *always* execute
}
You ought to be using the double equals == to compare a value, and a single equals = to assign a value.
(Edit after additional code change)
Inside the for-loop, you are trying to use cin to read in a single character. However, since the z is an integer, cin is looking for a valid integer, which does not happen to include 'A' or 'B', etc.
Perhaps you should try using a getline() or get().
The problem lies in having your input variable as an int, take in a char.
What happens is that when you perform cin >> z;, the character that was input by the user is recognized as an invalid input by the >> operator and therefore does not extract the character.
As such, z does not get any value, the character stays in the stream, and the >> operator continues to fail to extract the character until the loop ends.
Therefore, you can solve your problem by making your input variable a char instead.
Here's a link to help you better understand how to avoid such problems in the future.
Thank you for reading.

Validating a double in c++

I'm completely new to coding, so please keep this in mind before commenting.
So I've been trying to get into coding for a while, and today I went to the library
and picked up a book called "programming in c++". I've written some basic programs,
but I have gotten stuck at one point, I have no idea how to create a function that
makes sure that when the user is prompted for a double, what they enter is valid.
(If the user enters a character like 'k', the program just breaks).
I searched here and on the net, and there are some answers, but they are more along
the line of "here's a line of code that works, insert x, y, z, into it". And I don't
have enough experience to know what to do. So here is a sample that is a mix of code
from another question, and me failing to try to make it work in my program:
#include <iostream>
#include <stdio.h>
using namespace std;
double GetDouble () {
double x;
cin >> x;
int valid = 0;
while (valid == 0) {
if (x == double) {
return x;
break;
} else if (x != double) {
cout << "Invalid Input! Please input a numerical value." << endl;
cin.clear();
while (cin.get() != '\n') ; // empty loop
}
}
return x;
}
Now what I want it to do is to use "cin << x" to get a user input for x, and
then make sure that x is a double, and I'm failing quite hard at this. If
someone could explain this to in a manner that clarifies each operation,
I would be truly grateful. For example, I don't know what the break function does,
and what the cin.clear(), and cin.get() do. (I know this is a duplicate, but the
answers on the other question does not at all address what I'm confused about,
thank you for taking time to read & answer this! :)
This seems a close analog to your code that (mostly) works:
double GetDouble () {
double x;
cin >> x;
// ver1: while( cin.fail() ) // or !cin.good() no trailing char check.
while( cin.fail() || (cin.peek() != '\r' && cin.peek() != '\n'))
{
cout << "Invalid Input! Please input a numerical value." << endl;
cin.clear();
while( cin.get() != '\n' ); // or cin.ignore(1000, '\n');
cin >> x;
}
return x;
}
First of all, double is a keyword so you don't need to use it in a conditional statement.
Secondly, you can use the cin>>x in a while loop and then process x , a sample code is given below:
while(cin>>x)
{
//process
}
whenever you use anything in a while statement, it first checks it's validity.
if for example user enters a character the condition will evaluate to false and you can then tell this to the user. In this way you can run the loop till the time user enters correct input.
As for the function of break keyword, it gets you out of a loop, for ex
for(int i=10; i>0; i++)
{
// do something
}
will keep on running forever, but suppose you rewrite the code as:
for(int i=10; i>0; i++)
{
if(i==15)
break ;
}
the loop will end as soon as the value of i reaches 15
Something like so:
double getDouble(const string& askMessage = "Please Enter a number: ",const string& errorMessage = "Please enter a valid number: ", const int numberOfTrials = 10){
double userInput = 0.0;
bool isValidInput = false;
int trials = 0;
do{
cout << endl << askMessage;
if(cin >> input) break;
else{
cin.clear(); //EDIT thanks ebyrob, forgot about this.
std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
std::cout << errorMessage;
}
}while(!isValidInput || trials < numberOfTrials);
return userInput;
}
use it like so
const double d1 = getDouble();
const double d2 = getDouble("Please Enter a number: ", "Error! Enter a valid number: ", 1000);
Break breaks out of a loop (in this case, a while)
cin.clear() clears the cin buffer of all chars.
cin.get() gets a single character from cin (probably standard in).