infinite while-loop not displaying cout - c++

#include <iostream>
int main()
{
char c;
int value{}, value2{};
while(true)
{
if(std::cin >> c)
{
if(c == '|') break;
else continue;
while(std::cin >> value >> value2)
{
std::cout << value << '\n' << value2 << std::endl;
}
}
}
}
Hello, I am trying to do here is take two integers as input in an infinite while-loop with a terminating char to exit the loop. Seems to work nice and dandy but then why is it that my output for my declarations isn't displaying? I am working through my reading material step-by-step to further my understanding, any help please greatly appreciated.
p.s
Further, I may try to make an exception to handle a minor detail, like using Z^ (ctrl+ Z) in my command line prompt window to exit as it's not accepting, thank you.

That is because you have
if(c == '|') break;
else continue;
in your code.
What this is doing is, if the value of c is equal to '|', the compiler gets outside the while loop and if value of c is not equal to '|', the compiler encounters continue, which makes it go back to the while (true) line.
The compiler never reaches the cout line.

The nuance with C++ and working with parsing integers may cause some headaches as its implementation is quite specific. But here is some code that fulfills what I may have been requesting.
#include <iostream>
#include <string>
int main()
{
char c;
int i = 0;
int value[2];
std::string text;
while(std::cin >> c)
{
if(c == ',' || c == '|')
{
value[i] = std::stoi(text);
text = "";
i++;
i = i%2;
if(i==0)
{
std::cout << value[0] << ' ' << value[1] << std::endl;
}
}
else
{
text = text + c;
}
if(c == '|') break;
}
return 0;
}
What needs to happen is a comma is required for parsing int values here.
I.E
User input: 123, (enter) 456,
There is also a way to implement without commas using getline. message for further details if curious.

Related

how do you define an exact case constant with a switch statement in c++

I'm learning C++ and I don't fully understand how case works in switch statements. I have the following code:
bool accept3() {
int tries = 1;
while (tries<4) {
std::cout<<"Do you want to proceed (y or n)?\n";
char answer = 0;
std::cin>>answer;
switch(answer) {
case 'y':
return true;
case 'n':
return false;
default:
std::cout<<"Sorry, but I don't understand that.\n";
tries ++;
}
}
std::cout << "I'll take that as a no.\n";
return false;
}
int main()
{
//accept();
//accept2();
accept3();
}
It works as expected when you input, 'y', 'n', or any other single character that does not meet the two defined cases.
When you input any string of characters that begins with n, it still takes that as the 'n' case. Why does it do this? How can I make this more exact, so that it ONLY accepts 'n' and not 'no', 'no way' or any other string beginning with 'n'.
Thank you!
This is tricky because if you input text with spaces into the terminal, like "d d d y", then you'll see the loop trigger 4 times in a row because "cin >> answer" breaks the line into separate inputs (this is called tokenization).
Here's code demonstrating how to properly parse an entire line of input as one menu command:
#include <iostream>
#include <string>
bool accept3() {
int tries = 1;
while (tries < 4) {
std::cout << "Do you want to proceed (y or n)?\n";
std::string answerStr;
std::getline(std::cin, answerStr);
char answer = '\0';
if (answerStr.size() == 1) {
answer = answerStr[0];
}
switch (answer) {
case 'y':
return true;
case 'n':
return false;
default:
std::cout << "Sorry, but I don't understand that.\n";
tries++;
}
}
std::cout << "I'll take that as a no.\n";
return false;
}
int main()
{
//accept();
//accept2();
accept3();
}
When you input any string of characters that begins with n, it still takes that as the 'n' case. Why does it do this?
Because you are asking cin to read a single char, so that is what it does. operator>>(char&) ignores leading whitespace, if any, and then reads 1 char. Any subsequent characters, if any, are left in the input buffer for later reads.
How can I make this more exact, so that it ONLY accepts 'n' and not 'no', 'no way' or any other string beginning with 'n'.
Use cin.getline() or std::getline() instead, and then compare the entire line, eg:
bool accept3() {
int tries = 1;
std::string answer;
do {
std::cout << "Do you want to proceed (y or n)?\n";
std::getline(std::cin >> std::ws, answer);
if (answer == "y")
return true;
if (answer == "n")
return false;
std::cout << "Sorry, but I don't understand that.\n";
++tries;
}
while (tries < 4);
std::cout << "I'll take that as a no.\n";
return false;
}

How to read from keyboard a complete random text, filter and cast

I`m developing a Tic Tac Toe game for school, but it is getting difficult develop a nice way to read a play from keyboard, in a practical and nice formated way.
This is what I did:
Human::play() const
{
int pos
std::cout << endl << Name << ", please, insert the desirable move:";
//^^this is a class atribute
std::string keyboard;
std::stringstream ss;
std::getline(std::cin, keyboard);
ss << keyboard[0];
ss >> pos;
return (pos);
}//end of Human class method *play*
This function will be called and I will verify if the player move was acceptable, thus, see if it is between 0 and 8. Also, I would like to check if there was an entry of "r" or "q", as it will mean that the player wants to come back one turn or quit the game.
To check if the player had enter this instructions, I do this i.e:
int playermove = player1.play()
if (playermove == 'q')
...
I am having troubles because from what was shown above, pos is returned 0 when a character is entered. But, I don't see any practical solutions.
Could you please suggest me alternatives?
You can check for r and q and on false just subtract -48 (because of ASCII table).
Check this out:
#include <iostream>
using namespace std;
int main() {
char tmp;
cin >> tmp;
if(tmp == 'q') {
cout << tmp;
return 0;
} else {
int smth = tmp;
cout << smth - 48;
return 0;
}
return 0;
}
This will catch q and numbers. You can then check if (smth - 48) is in range 0-9 by checking (> -48 && < -39).

How to limit visible user input when using std::cin?

I'm looking for a method to limit the visible user input using std::cin.
#include <iostream>
int main()
{
std::cout << "Enter your planet:\n";
string planet;
std::cin >> planet; // During the prompt, only "accept" x characters
}
What the user sees if they enter earth or any other word exceeding 4 characters before pressing enter:
Enter your planet:
eart
This is assuming the character limit is 4, note that the 'h' is missing. The console does not display any other character once it has exceeded the character limit. and this is before you press the enter key.
Kinda like typing in an input box like password fields, but it only allows 5 characters, so typing any other character goes unnoticed
A better analogy would be the maxlength attribute for text input in HTML.
That can't be achieved portably, because OS consoles aren't part of C++ standard. In windows, you could use <windows.h> header - it provides console handles etc., but since you didn't specify OS you are using, the is no point in posting windows-only code here (since it might not meet your needs).
EDIT:
Here is (not perfect) code that will limit visible input of the user:
#include <iostream>
#include <windows.h>
#include <conio.h>
int main()
{
COORD last_pos;
CONSOLE_SCREEN_BUFFER_INFO info;
std::string input;
int keystroke;
int max_input = 10;
int input_len = 0;
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
std::cout << "Input (max 10) characters, press ENTER to prompt:" << std::endl;
GetConsoleScreenBufferInfo(handle, &info);
last_pos = info.dwCursorPosition;
while(true)
{
if(kbhit())
{
keystroke = _getch();
//declare what characters you allow in input (here: a-z, A-Z, 0-9, space)
if(std::isalnum(keystroke) || keystroke == ' ')
{
if(input_len + 1 > max_input)
continue;
++input_len;
std::cout << char(keystroke);
input += char(keystroke);
GetConsoleScreenBufferInfo(handle, &info);
last_pos = info.dwCursorPosition;
}
else if(keystroke == 8) //backspace
{
if(input_len - 1 >= 0)
{
--input_len;
input.pop_back();
COORD back_pos {short(last_pos.X-1), last_pos.Y};
SetConsoleCursorPosition(handle, back_pos);
std::cout << ' ';
SetConsoleCursorPosition(handle, back_pos);
GetConsoleScreenBufferInfo(handle, &info);
last_pos = info.dwCursorPosition;
}
}
else if(keystroke == 13) //enter
{
std::cout << std::endl;
break;
}
}
}
std::cout << "You entered: " << std::endl
<< input << std::endl;
}
After a few days of experimenting, I found another solution that seems to be quite easy to grasp as it is somewhat beginner level and without requiring any knowledge of windows programming.
NOTE:
The conio.h library function _getch() could easily be replaced with the getchar() function;
I'm not saying the previous answer was not okay, but this solution is sort of aimed towards beginners with only basic knowledge of c++
char ch;
string temp;
ch = _getch();
while(ch != 13)// Character representing enter
{
if(ch == '\b'){ //check for backspace character
if(temp.size() > 0) // check if string can still be reduced with pop_back() to avoid errors
{
cout << "\b \b"; //
temp.pop_back(); // remove last character
}
}
else if((temp.size() > 0) || !isalpha(ch))// checks for limit, in this case limit is one
{ //character and also optional checks if it is an alphabet
cout << '\a'; // for a really annoying sound that tells you know this is wrong
}else {
temp.push_back(ch); // pushing ch into temp
cout << ch; // display entered character on screen
}
ch = _getch();
}
This could probably use some tweaks, because it's definitely not perfect, but I think it is easy enough to understand, at least I hope so

While-loop breaks, and I don't know the reason why

I was writing a code for a counter. If I give 'a' as input, it should +1 the counter and show it on the screen. But when I do it, it shows 1 on the screen and the program ends. I want it to run until and unless i give some other character as input. What's the mistake I am making?
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int Counter = 0;
char t;
while(true)
{
t = cin.get();
if(t == 97)
{
Counter = Counter + 1;
}
else
break;
system("cls");
cout << Counter;
}
return 0;
}
The issue is when you are entering your 'a', you are probably hitting Enter as well, which is interpreted as another char. That second char is definitely not a, so your program breaks. This can be verified by just outputting what you read:
for (;;) {
std::cout << '?';
char t = std::cin.get();
std::cout << (int)t << '\n';
if (t != 'a') break;
}
std::cout << "done\n";
Which, when run, prints:
?a
97 // this is 'a'
?10 // this is '\n', note the additional ?
done
The simplest fix would be to use the input stream operator on cin, which would discard whitespace in the input (whereas get() does not):
char t;
for (;;) {
std::cout << '?';
std::cin >> t;
std::cout << (int)t << '\n';
if (t != 'a') break;
}
std::cout << "done\n";
Which, when run, produces:
?a
97
?b
98
done
which is what you'd intended.
Try this:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int Counter = 0;
char t;
while(true)
{
t = cin.get();
if(t == 97)
{
Counter = Counter + 1;
}
// else
// break;
system("cls");
cout << Counter;
}
//system("pause");
return 0;
}
Your else break; is the reason why you're closing after any interation. Basically after any iteration, it will break because due to any non-a input. However, running the code above, you will see the counter increment at every a input given and it will not break.
This will give you the basic operation you're looking for which is increment the counter based on input a, otherwise do nothing.
Edit: The above code will buffer your input and read it all, so if you have 5 a's like the following aaaaa, it will read it and output 5 for the counter.
If you want to break out of the loop, i suggest this:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int Counter = 0;
char t;
while(true)
{
cin >> t;
// t = cin.get();
if(t == 97)
{
Counter = Counter + 1;
}
else
break;
system("cls");
cout << Counter;
}
//system("pause");
return 0;
}
I tested it and it works. Seems to be with how cin.get() reads the buffered input from the console (i think). Not too sure on the specifics, but cin >> t does the trick.
Edit 2: Did some reading and i think cin.get() will consume the next character after your input, but in this case it is a newspace \n, which is why it will always break in your original code.

Need Help Using "Sort" Within My Program

I have a simple program that lists input in order of precedence, checking only for operators and ranking them like so, "*/+-":
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int prec(char op)
{
if (op == '*' || op == '/') return 0;
return 1;
}
bool compareprec(char a, char b)
{
return prec(a) < prec(b);
}
int main()
{
char input[] = "+-/*";
cin >> input;
sort(input, input + 4, &compareprec);
cout << input;
}
I'm trying to implement it within a more complex program that uses stacks to check alpha numerical input and do an infix to postfix conversion, ranking something that looks like this: "9*9+9" into "9 9 9 * +". The more complex program is as follows:
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int prec(char op)
{
if (op == '*' || op == '/' || op == '+' || op == '-') return 0;
return 1;
}
bool compareprec(char a, char b)
{
return prec(a) < prec(b);
}
int main()
{
stack<char> s;
char input;
while (cin.get(input) && input != '\n')
{
if (isalnum(input))
cout << input << " ";
else if (input == '(')
s.push(input);
else if (input == ')')
{
while (!s.empty() && s.top() != '(')
{
cout << s.top() << " ";
s.pop();
}
if(!s.empty())
s.pop();
else
cout << "ERROR: No Matching ( \n";
}
else if (s.empty() && input == '*'|| input == '/'|| input == '+'|| input == '-')
{
sort(input, input + 4, &compareprec); // Error Begins Here?
s.push(input);
}
else if (input == '*'||input == '/'||input == '+'|| input =='-')
while (!s.empty())
{
sort(input, input + 4, &compareprec); // More Errors Here?
cout << s.top() << "\n ";
s.pop();
s.push(input);
}
}
while (!s.empty())
{
cout << s.top() << " ";
s.pop();
}
}
But I keep getting an error that says:
error: no matching function for call to 'sort(char&, int, bool (*)(char, char))'
error: no matching function for call to 'sort(char&, int, bool (*)(char, char))'
And I'm not sure why. I know it's probably something painfully obvious/silly but I can't figure it out. Any help would be appreciated. Thanks in advance!
sort expects something that can be iterated over.
Your working example has
char input[]
(an array of char)
Your non working example removes the array syntax and makes it a plain char
char input
When you attempt to do:
sort(input, input + 4, &compareprec)
In the working case, because you are providing an array, you're telling it to iterate from the beginning of input to 4 past the location. In the non-working case you're telling it to go from say 'a' to 'd' (which is 'a' + 4).
Why do you have to sort anything in the second example? You have maximally two operators you have to compare, one on the top of the stack and one in the input. Just use your compareprec-function and act accordingly based on the result.
And by the way, to make your code a little prettier, create a function:
bool is_operator(char s);
Almost forgot to tell you, the version of int prec(char a) in the second example is wrong, use the first one.