Using an ASCII value as a condition - c++

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.

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)

Need some help finding a logical error in my while loop

I am learning C++, and I am doing some exercises in the book I am using. One of them asks to write a program that asks a user how many numbers they want to add up. Then prompt for the numbers the user wants to add or to enter '|' once finished. The numbers are then pushed into a vector. Part of the program asks to check if the size of the vector is equal to the original number of input items and that is where I keep getting an error.
cout << "Please enter the numbers and | once you are done: ";
while(true)
{
for(int num; cin >> num; )
{
if(num == '|')
{
break;
}
ints.push_back(num);
}
if(ints.size() != n)
{
cout << "There are more or less numbers in the vector than originally specified\n"
<< "Vector will be cleared; please re-enter the values: ";
ints.clear();
continue;
}
else
{
break;
}
}
The problem is that if the number of input is off, the message goes into an infinite loop and I am not sure how to fix it.
EDIT: n is the variable that holds in the number of values user wanted to enter.
Thanks!
num is an integer and cin >> num won't extract | symbol. Comparison num == '|' may not work as expected because num could have the numeric value of | ascii symbol even when user did not input any | symbol. You should properly handle end marker reading:
// loop will break when user enters `|` because it is not an integer
// setting failbit of cin
for(int num; cin >> num;)
{
ints.push_back(num);
}
cin.clear(); // reset failbit making cin able to read again
// check the end marker entered by user
{
string end_marker;
cin >> end_marker;
if("|" != end_marker)
{
// use of endl will flush the stream ensuring that
// printed text won't stuck in the buffer
cout << "Please use | as end marker" << endl;
continue;
}
}
Here is how I implemented it. I am worried about the logic in your while loop. I had been taught to avoid while(true) whenever possible. You know the logic behind how your code should work. With more practice you'll start to recognize the conditions you need to use. I am sure there are better ways to do it. But this is the way I tried it.
But to answer your question, the main reason it is failing is because integers cannot compare themselves with characters.
if(num == '|')
That does not work since num is an integer and not a character.
Normally I would implement this in a class and since global variables are not highly looked upon I created my own namespace. You'll have to finish the rest of the logic yourself however:
#include <iostream>
#include <vector>
#include <string>
namespace global
{
std::vector<std::string> strings;
std::vector<int> ints;
std::string a = " ";
int num = 0;
}
void doWork()
{
std::cout << "Please enter the number of integers you would like to add up: ";
std::cin >> global::num;
std::cout << "Please enter the numbers and | once you are done: ";
while (global::a != "|")
{
std::cin >> global::a;
global::strings.push_back(global::a);
}
global::strings.pop_back();
for(auto &e : global::strings)
{
global::ints.push_back(std::stoi(e));
}
}
int main()
{
doWork();
if(global::ints.size() != global::num)
{
std::cout << "Size of vector does not match the size specified. Clearing vector" << std::endl;
global::ints.clear();
global::strings.clear();
global::num = 0;
global::a = " ";
doWork();
}
}
I made a vector of char's and converted those into integers so that way you could add them up. The while loop should be checking for | rather than always running true. It then will check the size of the vector in the end, clear it if it does not match, and ask you to do it again. This is the best way that I could think of doing it.
EDIT: as VTT pointed out, char can only do one character at a time. I have converted it into a string in order to handle the conversion.
EDIT 2: reset the values of global::num and global::a to their default at the end of the failure in order to prevent crashing.

C++ : check whether an input is a number

I want the user to enter a key and I want to check whether the key is a number or not, throw a message if it is not and exit if it is 0.
I read an answer that suggested the below method here : isdigit() c++, probably simple question, but stuck
int key;
while (true){
cout << "Enter Key (Press 0 to Exit) : ";
if (cin>>key){
if (key == 0){ break; }
//Code goes here
}
else{cout<<"Key should be a digit "<<endl;}
}
but my code goes into an infinite loop as soon as I enter an alphabet and I am not able to figure out why.
Any help would be appreciated or if there is a better alternate method for the same then do suggest.
cin>>key
try to read an int from the console.
If you enter a non number character the next read from cin will set the cin stream into error state and nothing can be read from cin anymore until you clear the error flags of the stream.
cin.clear();
resets the error state.
You also have to ignore the entered chars which results in failure mode with
cin.ignore();
Example:
int main()
{
int i;
while (1)
{
std::cin >> i;
if ( std::cin.fail())
{
std::cout << "Something went wrong with cin" << std::endl;
std::cin.clear();
std::cin.ignore();
}
else
{
std::cout << "input works, read: " << i << std::endl;
}
}
}
If you try to read a single digit form console look also here:
Capture characters from standard input without waiting for enter to be pressed
my code goes into an infinite loop as soon as I enter an alphabet
That's because you declared key as an int, so when std::cin fails to read an integer number the stream is set into an error state and the break statement inside the if's is no longer reachable.
A possible alternative is to read a line from the input stream as a string and then try to convert it to a number.
Now, given OP's question:
I want the user to enter a key and I want to check whether the key is
a number or not, ...
It's not clear to me (my fault, probably) if key has to be considered a single or a multi digit number. In the following snippet I'll show the latter case. Please, note that it may include the former too.
#include <iostream>
#include <string>
int main()
{
std::string line;
while ( std::getline(std::cin, line) )
{
if ( line.empty() ) continue;
try
{
int key = stoi(line);
if ( !key ) break;
// code that uses the key...
}
catch ( const std::invalid_argument &e )
{
std::cout << "Key should be a digit!\n";
}
catch ( const std::out_of_range &e )
{
std::cout << "The value entered can't be represented by an int.\n";
}
}
return 0;
}

C++ - Cin.fail when space on begining

I need help with cin.fail when it starts with a space.
This is what I mean.
#include <iostream>
#include <math.h>
using namespace std;
int main ()
{
char b[80];
int e,d,v,m=0;
for(int i=0;i<80;i++)
{
b[i]=0;
}
cout << "Insert number in binary:" << endl;
cin >> b;
v=0;
for(int i=0;i<80;i++)
{
if(b[i]=='1' || b[i]=='0' || b[i]=='\n')
{
v++;
}
else if(b[i]!=0 || b[i]!='\0' || b[i]==' ')
{
cout << "Error" << endl;
return 0;
}
}
e=v-1;
d=0;
m=0;
for(int i=0;i<v;i++)
{
m=(b[i]-48)*(pow(2,e));
d=d+m;
e=e-1;
}
cout << "His number in decimal: "<< d << endl;
return 0;
}
When there is something like 1010 it OK, it will give me number.
If it contains other number - 2,3 etc.. it will fail, its OK
But when it get something like _101010 .. programm will still proceed and it will give me number, but I need it to fail. So I need something like .. when b contains 1 0 or \n, programm will continue, otherwise it will fail. But when I put in \n like
if(b[i]=='1' || b[i]=='0' || b[i]=='\n') - its not working .. I mean, programm fails in any case ...
Sorry for asking on this "stupid" question, but I am doing it for hours and still didnt figure it out .. Thanks guys.
cin >> b; will skip leading whitespace and then read the next word. That's how it is designed.
If you want to read an entire line of input, use getline instead.
It will also be much easier, and a lot safer, if you read into a std::string instead of a fixed size char b[80];. If you ever happen to read more than 80 characters into that, you're toast.

while loop to infinity when the input of a cin is a 'dot'

I am having trouble using the cin method to acquire a variable. When the input is a number there is no problem, but when it is a special character like a dot [.],
the whileloop loops into infinity.
What am I doing wrong?
cout << "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
while(*race<1||*race>3)
{
system("cls");
cout << "Wrong choice"<<endl<< "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
}
I searched for the answer and i should have to flush the buffer but i don"t get how to do it. I'm rather new with c++. Thanx
Make race an char, then you will be able do to:
while (*race < '1' || *race > '3')
which is probably what you want to achieve.
Explanation:
When you cin >> into an int, it converts given ASCII string to integer value. . doesn't have an integer meaning, so it isn't read into race and failbit is set - further >>s are no-op, until you clear them. However, if you cin >> into char and compare it with other chars (well, their ASCII codes, actually), you will be able to check it without troubles.
This example exactly reproduces your problem:
#include <iostream>
int main()
{
int i = 5;
while (i < 1 || i > 3)
{
std::cin >> i;
}
}
Here's what happens: When operator>> fails to read an integer (e.g. when you type a dot and press enter), whatever you typed stays in the stream, including the newline character.
So in the next iteration of the while loop the next input is already there and since it's not a valid integer, the loop can never break.
You need to make sure that, when operator>> fails, you empty the stream and clear all the error flags that got set.
#include <iostream>
#include <limits>
int main()
{
int i = 5;
while (i < 1 || i > 3)
{
if (!(std::cin >> i))
{
// clear streams internal error flags
std::cin.clear();
// ignore what's left in the stream, up to first newline character
// or the entire content, whichever comes first
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
}
There are several problems with your code. The first is that you don't
verify that your input has succeeded; the correct condition for the
while should be:
while ( !cin || (*race < 1 || *race > 3) )
As written, if the input fails (which is what is happening when you
enter a '.', supposing that race has type int*), then *race
contains its previous value, whatever that was.
The second is that if you do get an error from cin, you don't clear
it. Once the stream is in an error state, it stays that way until you
explicitly clear it. If cin has failed, you need to execute:
cin.clear();
somewhere in the loop.
The third is that if cin fails, you don't extract the character which
made it failed, so that after clearing the error status, you need to
extract it. Given the way you've structured your dialog, you probably
want to ignore everything until the end of the line:
cin.ignore( INT_MAX, '\n' );
You may want to do this even if cin didn't fail, either in the loop
(if entered because of the *race < 1 || *race > 3 condition), or in
case of success. Alternatively, you may want to shift to reading lines,
and ensure that the line only contains whitespace after the character
you're interested in.
This last solution is the one I would adopt, since it handles pretty
much all of the above problems. So my code would look something like:
// return -1 on error in input,
// throw exception on (unexpected) end of file
int
getRace( std::istream& source )
{
std::string line;
if ( !std::getline( source, line ) ) {
throw std::ios_base::failure( "Unexpected end of file" );
}
std::istringstream tmp( line );
int results;
return tmp >> results >> std::ws && tmp.get() == EOF
? results
: -1;
}
// ...
int race = -1;
while ( race < 0 ) {
std::cout << "What is your race\n"
"1. Human\n"
"2. Troll\n"
"3. Zombie\n" << std::flush;
race = getRace( std::cout );
if ( race < 0 ) {
std::cout << "Wrong choice" << std::endl;
}
}
Note that by inputting through a line, you avoid any problems with
resetting format errors, skipping erroneous input or resynchronizing in
case of error.
The other solution besides the one accepted is to clear the cin's failbit and ignore the last input like below:
cout << "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
while(*race<1||*race>3)
{
// Clears the state of cin to be in good state
cin.clear();
// Ignores the last input read so that it's not read back again
cin.ignore();
system("cls");
cout << "Wrong choice"<<endl<< "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
}