How to read until ESC button is pressed from cin in C++ - c++

I'm coding a program that reads data directly from user input and was wondering how could I read all data until ESC button on keyboard is pressed. I found only something like this:
std::string line;
while (std::getline(std::cin, line))
{
std::cout << line << std::endl;
}
but need to add a portable way (Linux/Windows) to catch a ESC button pressed and then break a while loop. How to do this?
EDIT:
I wrote this, but still - works even if I press an ESC button on my keyboard:
#include <iostream>
#include <string>
using namespace std;
int main()
{
const int ESC=27;
std::string line;
bool moveOn = true;
while (std::getline(std::cin, line) && moveOn)
{
std::cout << line << "\n";
for(unsigned int i = 0; i < line.length(); i++)
{
if(line.at(i) == ESC)
{
moveOn = false;
break;
}
}
}
return 0;
}
EDIT2:
Guys, this soulution doesn't work too, it eats the first char from my line!
#include <iostream>
#include <string>
using namespace std;
int main()
{
const int ESC=27;
char c;
std::string line;
bool moveOn = true;
while (std::getline(std::cin, line) && moveOn)
{
std::cout << line << "\n";
c = cin.get();
if(c == ESC)
break;
}
return 0;
}

int main() {
string str = "";
char ch;
while ((ch = std::cin.get()) != 27) {
str += ch;
}
cout << str;
return 0;
}
this takes the input into your string till it encounters Escape character

After you read the line, go though all characters you just read and look for the escape ASCII value (decimal 27).
Here's what I mean:
while (std::getline(std::cin, line) && moveOn)
{
std::cout << line << "\n";
// Do whatever processing you need
// Check for ESC
bool got_esc = false;
for (const auto c : line)
{
if (c == 27)
{
got_esc = true;
break;
}
}
if (got_esc)
break;
}

I found that this works for getting input for the escape key, you can also define and list other values in the while function.
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#define ESCAPE 27
int main()
{
while (1)
{
int c = 0;
switch ((c = _getch()))
{
case ESCAPE:
//insert action you what
break;
}
}
return 0;
}

#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
int number;
char ch;
bool loop=false;
while(loop==false)
{ cin>>number;
cout<<number;
cout<<"press enter to continue, escape to end"<<endl;
ch=getch();
if(ch==27)
loop=true;
}
cout<<"loop terminated"<<endl;
return 0;
}

I would suggest that for not just ESC character in C++, but for any other character of the keyboard in any language, read characters that you input into an integer variable and then print them as integer.
Either that or search online for a list of the ASCII characters.
This will give you ASCII value of the key, and then it's plain simple
if(foo==ASCIIval)
break;
For the ESC character, the ASCII value is 27.

Related

I want my program to stop accepting input from console when I type STOP in console C++ Program

I am making a C++ program which accepts input from user (even \n) is required but the program should stop when I type STOP, so can anyone help me out. Earlier I was using getline but that also got some issue like when I enter \n two (hit enter two times) it stops the whole code.
So can anyone guide me what to do, I want to capture whole input until user types STOP in console.
Thank you.
#include <iostream>
using namespace std;
int main()
{
cout<<"Main Started\n";
char array[10];
string str;
while(fgets(array,sizeof(array),stdin))
{
str = (string) array;
if(str=="STOP") // This line is not getting executed. Also tried strcmp but of no use
break;
}
cout<<"\nMain Ended\n";
return 0;
}
You can use getline:
#include <iostream>
#include <string>
int main() {
std::cout << "Main Started\n";
std::string str;
while(std::getline(std::cin, str)) {
if(str == "STOP")
break;
}
std::cout << "\nMain Ended\n";
return 0;
}
or operator>>
#include <iostream>
#include <string>
int main() {
std::cout << "Main Started\n";
std::string str;
while(std::cin >> str) {
if(str == "STOP")
break;
}
std::cout << "\nMain Ended\n";
return 0;
}
fgets() includes '\n' in the output, if the read is terminated by ENTER, so you need to check for that, eg:
while (fgets(array, sizeof(array), stdin) != NULL)
{
str = array;
if (str == "STOP" || str == "STOP\n")
break;
}
Or:
while (fgets(array, sizeof(array), stdin) != NULL)
{
if (strcmp(str, "STOP") == 0 || strcmp(str, "STOP\n") == 0)
break;
}
std::getline() (and std::istream::getline()), on the other hand, do not include the terminating '\n' in the output:
while (getline(cin, str))
{
if (str == "STOP")
break;
}

How to input many letters and stop after a certain one (q or Q)?

I was assigned a homework to input as many letters as the user wants and stop after input q or Q. Then the programs should output how many vowels there were in such string. We're supposed to use _getche() function but I have MacBook so it doesn't work.
I've tried making conio.h.
I've tried also using cin.get() and getchar() but none work.
__getche() is not a standard function and conio.h is not a standard header. The usual way of doing this is:
int main() {
int ch;
int vowel_count = 0;
while ((ch = getchar()) != 'q' && ch != 'Q' && ch != EOF) {
vowl_count += is_vowel(ch);
}
}
#include <iostream> // getchar(), std::cout
#include <cctype> // tolower()
int main()
{
int count = 0;
for (;;) // infinite loop
{
char c = getchar(); // read a single char from stdin
if (tolower(c) == 'q') // if input is 'q' or 'Q'
break; // break out of the loop
// check for vowel here
{
count++;
}
}
std::cout << "You typed in " << count << " vowels!\n";
return 0;
}
i think you need it:
#include <conio.h>
using namespace std;
int main()
{
bool h = true;
while(h){
char ch;
ch = getche();
if(ch=='q' || ch == 'Q'){
h = false;
}
}
return 0;
}

Detecting if input string has a space

I wrote this code to detect if an input string has a space or not. Please tell what is wrong in this approach.
#include <iostream>
#include <string>
using namespace std;
int main(){
string inp;
getline(cin, inp);
for (int i = 0; i < inp.length(); i++) {
string z = to_string(inp[i]);
if (z == " ") {
cout << "space";
}
else {
i++;
}
}
}
If i enter a string with spaces, it doesn't print "space".
Since inp is an std::string, inp[i] will be a char. Since std::to_string only has overloads for arithmetic, non-char values, calling it on a char is akin to calling it on the integer representation of said char. (If you log z, you'll likely find a number printed.)
Instead, directly compare inp[i] to a space. else { i++; } is also unnecessary – you may be jumping over spaces.
for (int i = 0; i < inp.length(); i++) {
if (inp[i] == ' ') { // note single quotes for char
cout << "space";
}
}
#TrebledJ's answer explains why your code is broken and how to fix it.
Another way to handle this situation is to use std::string::find() instead:
#include <iostream>
#include <string>
int main(){
std::string inp;
std::getline(std::cin, inp);
if (inp.find(' ') != std::string::npos) {
std::cout << "space";
}
}
Alternatively, your original code tries to output "space" for each space character found. You could use find() in a loop:
#include <iostream>
#include <string>
int main(){
std::string inp;
std::getline(std::cin, inp);
std::string::size_type idx = inp.find(' ');
while (idx != std::string::npos) {
std::cout << "space at " << idx << std::endl;
idx = inp.find(' ', idx+1);
}
}

Fstream gives error when reused on a file

I have two text files.
Original Output:
Log.txt
Joe hello
Joe gargabash
Joe random unnecessary text
Hello
How are you?
Log2.txt is another text file that is initially blank.
When I run this code, it succesfully copies all of the lines that don't start with Joe. However, I want to copy the text back to the original .txt. When I uncomment out the selection I commented to try to do that, I get errors. Anyone know what i'm doing wrong? Thanks so much for reading all of this mess.
For clarification, the bool STRINGCONTAINS(int, char, char, int) checks if a char array matches with another char array.
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
using namespace std;
bool STRINGCONTAINS(bool CaseSensitive, //If this is true, we are checking a case sensitive string, if it's false, we're not.
char * input1, // First string [Type: Char Array]
char * input2, //Second String [Type: Char Array]
int MAXSTRINGLENGTH) // Integer representing max possible length of string.
{
if (CaseSensitive)
{
for(int i=0;i<MAXSTRINGLENGTH;i++)
{
if (*input1 == *input2)
{
input1++;
input2++;
} else
{
return 0;
}
}
} else
{
int char1, char2;
for(int i=0;i<MAXSTRINGLENGTH;i++)
{
char1 = *input1;
char2 = *input2;
if (char1 == char2 || char1 == (char2+32) || char2 == (char1+32))
{
input1++;
input2++;
} else
{
return 0;
}
}
}
return 1;
}
int main() {
int input;
char * loadedline = new char[192];
ifstream log;
ofstream templog;
log.open("log.txt");
templog.open("log2.txt");
while(log.getline(loadedline,sizeof(log)))
{
if (!STRINGCONTAINS(0,loadedline,"joe",3))
{
cout << loadedline << endl;
templog << loadedline << endl;
}
}
log.close();
templog.close();
/*ifstream templog2;
ofstream log2;
templog2.open("log2.txt");
log2.open("log.txt");
while(templog2.getline(loadedline,sizeof(templog2)))
{
log2 << loadedline << endl;
}
templog2.close();
log2.close;*/
delete[] loadedline;
cin >> input;
return 0;
}
The error in your program is that you are missing a parenthesis in your log2.close.
Change it to log2.close(); and it will run!

Removing words between < and > signs in a string c++

I'm not sure where to go from here. I know something needs to go after ifstr.get(c). It copies the exact words that I have in my text file called project.txt but I just need to remove any words that have the chars < or >?
Any help would be great. Thanks:)
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
string line;
char c;
ifstream ifstr("project.txt");
ofstream ofstr("past.txt");
if(ifstr.fail()){
cout<<"error!"<<endl;
} // if
ifstr.get(c);
while(!ifstr.eof()) {
cout<<c;
ifstr.get(c);
ofstr<<line<<endl;
} // while
cout<<endl<<"copy complete"<<endl;
ifstr.close();
ofstr.close();
system ("pause");
return 0;
} // main
Pseudo-code (iostream-esque conditions) for the question in title (also removes the angle brackets):
char c;
while (read_char_succeeded(&c))
if (c == '<')
while (read_char_succeeded(&c) && c != '>')
;
else
write_char(c);
Just another shot in the dark:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream ifstr("project.txt");
ofstream ofstr("past.txt");
if(ifstr.fail()){
cout << "error!" << endl;
} // if
bool skipOutput = false;
do
{
string word;
ifstr >> word;
if(!word.empty() && word[0] == '<')
{
skipOutput = true;
}
if(!skipOutput)
{
ofstr << word << " ";
// replicate the output to stdout
cout << word;
}
if(word[word.length()-1] != '>')
{
skipOutput = false;
}
} while(!ifstr.eof());
cout << endl << "copy complete" << endl;
ifstr.close();
ofstr.close();
//system ("pause"); Doesn't compile with my system
return 0;
} // main
If you're really just want to filter out words enclosed within '<' and '>' characters this should be sufficient. If you have more complex parsing rules for your <> tags you should elaborate your question.
I'm not sure, that this is what you wanted. Please take a look at the code!
//we create a boolean value, to know if we started skipping
bool skipStarted = false;
while(ifstr.get(c))
{
//if its a '<' and we havent started skipping jet,
//then we start skipping, and continue to the next char.
if(c=='<' && !skipStarted)
{
skipStarted = true;
continue;
}
//if its a '>' and we started skipping,
//then we finish skipping, and continue to the next char.
if(c=='>' && skipStarted)
{
skipStared = false;
ifstr.get(c);
if(c==' ')
continue;
}
//if we are skipping, then we go to the next char.
if(skipStarted)
continue;
//otherwise we simply output the character.
ofstr<<c;
}