How to detect user input of CTRL-X in C++ - c++

I need to end my function once the user inputs CTRL-X or '/'. I don't know how to detect/check for a user input of CTRL-X.
The task given to me states:
'When you edit the file, you will enter data line by line and when done, you will enter ‘/’ or CTRL + X to exit.'
I have written this code so far. I'm a beginner so pardon my code.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string data;
int line_num=1;
ofstream editFile;
editFile.open("edit_test.txt");
while(data!="/"){ //some kind of condition ORed with the condition already present in while loop?
cout<<line_num<<"> "; //I want to display line numbers every time the user presses enter
getline(cin, data);
if(data!="/"){
editFile<<data<<endl;
line_num++;
}
}
editFile.close();
return 0;
}

CTRL+X is the same as character code 24 (since X is the 24th letter of the alphabet). Barring any system interference*, all you need to do is check to see if character code 24 is in the input.
while (getline( std::cin, s ))
{
// Find ^C in s
auto n = s.find( '\x18' );
if (n != s.npos) s = s.substr( 0, n );
// process s normally here
// If ^C was found in s, we're done reading input from user
if (n != s.npos) break;
}
CTRL+X doesn’t tend to have any special system actions attached to it, so you shouldn’t have any problem getting it as input.

Related

Can't exit an infinite loop

My program starts by entering any key,then the user sees a color changing text "Welcome to my
program". Now, the user should hit any key to continue, but he can't quit the infinite loop that is changing the color of text. Let me show you the code for a better understanding.
HANDLE color=GetStdHandle(STD_OUTPUT_HANDLE);
cout<<"Press any key to start...";
int stop=getchar();
while(stop){
for(i=10;i<=15;i++){
cout <<("\n\t\t\t\t\t Welcome to my program\n");
SetConsoleTextAttribute(color,i);
Sleep(100);
system("cls");
}
}
This would be a solution for you (comments included)
#include <iostream>
#include <Windows.h>
#include <thread>
int main()
{
HANDLE color = GetStdHandle( STD_OUTPUT_HANDLE );
std::cout << "Press any key to start...";
bool stop = false; // use a Boolean instead of int
// doesn't really matter what the input is, so use getchar().
// Note, this is really just "enter". You can modify if you expect user to
// hit multiple keys before hitting enter
getchar();
// This line here will start a new thread which will wait for the user to hit enter
std::thread getInput = std::thread( [&stop] { getchar(); stop = true; } );
// Loop stays the same (except I inverse the "stop" variable to make more sense)
while ( !stop ) {
for ( int i = 10; i <= 15; i++ ) {
std::cout << ( "\n\t\t\t\t\t Welcome to my program\n" );
SetConsoleTextAttribute( color, i );
Sleep( 100 );
system( "cls" );
}
}
}
When you are using getchar() to get input from the user, it will store inside the integer stop the decimal value of the buffer the user entered.
For example: if the user entered '0', the stop variable will store the value 48 (the decimal value of the char '0').
And you while loop will keep running while stop is not equal to 0, which is never because the decimal value of all of the characters is not 0, the only character that its decimal value is 0 is NULL.
To fix your problem you will need to add an exit option according to your needs.
If you create a loop as follows:
int myInt = 1;
while (myInt)
{
std::cin >> myInt;
}
The loop will continue until the user enters 0. This is because conditional statements use 0 as "false" and in this case, any other value as "true".
The problem with your implementation is you only get the users input once, and even if the user enters "0" (in char format) the integer value associated is 48.
You could add this:
HANDLE color=GetStdHandle(STD_OUTPUT_HANDLE);
cout<<"Press any key to start...";
int stop=getchar();
while(stop){
for(i=10;i<=15;i++){
cout <<("\n\t\t\t\t\t Welcome to my program\n");
SetConsoleTextAttribute(color,i);
Sleep(100);
system("cls");
}
std::cin >> stop;
}
Now the loop will start when the user presses any key, then the the inner loop will run, then the user will need to enter a key again. If the user enters "0" this time the while() loop will break and the program will proceed.
If you are trying to keep a loop running while searching for user input to break the loop, then you are attempting a much more complex task. Look into the std::thread library if you are interested in this.
The issue with your code from what I could tell is that you're only initializing the variable "stop" once in your code and never inside your loop. So, the program will only ask the user for input once. A simple fix would be to continuously ask the user for input at the end of your for loop:std::cin>>stop;. In addition, like what others have already said, if the user inputs '0', it would implicitly typecast the char variable into an integer variable using ASCII. Since '0' corresponds to the integer value of 48, it would save 48 into the variable instead of 0. You can fix this by using this code:
HANDLE color=GetStdHandle(STD_OUTPUT_HANDLE);
cout<<"Press any key to start...";
int stop=getchar()-'0';
while(stop){
for(i=10;i<=15;i++){
cout <<("\n\t\t\t\t\t Welcome to my program\n");
SetConsoleTextAttribute(color,i);
Sleep(100);
system("cls");
}
std::cin>>stop;
}

make user enter a string of integers and output a different string

hi i am having trouble starting this program as i am new and have no idea how to use loops to construct this thanks
here are the directions:
For this assignment, write a program named assignment2 (source is the same name with .cpp extension) to
prompt the user for an integer value (ignore negative values) and then output this value using the following rules:
Each digit within the integer value is to be displayed the same number of times as the value of the digit
itself, with one exception...the digit 0 will be displayed once, like the digit 1.
Separate each string of digits using a single dash character.
For example:
If the input value is 120473, the display should look like:
1-22-0-4444-7777777-333
If the input value is 5938061, the display should look like:
55555-999999999-333-88888888-0-666666-1
In addition, ask the user if they would like to retry using another integer value. If so, repeat the above. End the
program when the user chooses to quit (does not want to retry).
This assignment is an exercise in using the following:
Unary Operators:
! ++ --
Binary Operators:
+ - * / % && ||
Data types:
bool
char
int
enum
Flow control:
if-else
switch
do-while loop
while loop
for loop
In addition, you are allowed to use any necessary functions provided by the Math library. To include the Math
library, add the following line to your list of include statements:
#include <cmath>
For most digit manipulation assignments, I recommend treating the number as a string of characters rather than as a number.
The Foundation
Let's start with the foundation:
#include <iostream>
#include <string>
#include <cstdlib>
using std::cout;
using std::cin;
using std::getline;
int main(void)
{
cout << "Paused. Press Enter to continue.\n";
cin.ignore(100000, '\n');
return EXIT_SUCCESS;
}
The above program will hopefully keep the console (terminal) window open until the Enter key is pressed.
Getting The Input
We'll ask the User for a number, this is also known as prompting:
// The prompt text doesn't change so it's declared as const.
// It's declared as static because there is only one instance.
static const char prompt[] = "Enter a number: ";
cout.write(prompt, sizeof(prompt) - 1U); // Subtract 1 so the terminating nul is not output.
// Input the number as text
string number_as_text;
getline(cin, number_as_text);
Printing The Digits
Really, before this step, you should verify that the text only contains numbers. Repeat the prompting until the User inputs nothing or valid data.
A string can be accessed as an array. So we'll set up a loop:
const unsigned int length = number_as_text.length();
for (unsigned int index = 0U;
index < length;
++index)
{
// Extract the digit.
const char c = number_as_text[index];
// Verify it is a digit.
if (!isdigit(c))
{
continue;
}
unsigned int quantity = c - '0'; // Convert to a number.
if (quantity == 0) quantity = 1; // The requirements lie, for zero there is a quantity of 1.
// Use "quantity" to print copies of the character.
}
cout << "\n";
Stuff
I'm not going to write the entire program for you, as you haven't paid for my services. So you will have to figure out when to print the '-' and how to print many copies of the digit.
If this answer is not correct, please update your question with some clarifications or restrictions.

Invalid input for std::cin

The following code is intended to concatenate words entered by the user.
#include <iostream>
#include <string>
int main() {
// insert code here...
std::string s;
std::string concString;
while (std::cin >> s)
{
concString = concString + s;
}
std::cout << concString << std::endl;
return 0;
}
I am stuck in this while loop during execution because of which I am not able to print the concatenated string. How do I exit this loop? What is an invalid input for std::cin?
Typically, a loop like that is stopped by end of file, rather than invalid input.
In a *nix environment, you can usually send an end of file to the terminal with CTRL+d, and at a windows console, CTRL+z.
See https://stackoverflow.com/a/16136924/1084944
You could, however, implement your own additional way to signify end of input. For example, having your users enter a blank line when done, or the word quit or such. Once you've chosen one, you should communicate that to the user, and you will have to structure your loop to be able to detect these conditions and exit.

Detecting if the user enters space or enter in a conditional with cin.get()

I'm trying to get this input loop to stop if the user enters a space ' ' or enter \n but the space part doesn't seem to work, even when I replace in != ' ' with in != 32 which is the ASCII code for space.
#include<iostream>
using namespace std;
int main()
{
int temp, cho = 0;
char in = '0';
while (in != '\n' && in != ' ')
{
in = cin.get();
temp = in - '0';
if (temp >= 0 && temp <= 9)
cho += temp;
}
}
Is it even possible to achieve with cin.get() and a console application?
You actually have three problems here that won't be independently distinguishable from each other to begin with, but which become clear once you apply the reasoning below:
I. Boolean conditional is incorrect
while (in != '\n' || in != ' ')
This is wrong! You probably meant &&.
(A != B || A != C) is always true (assuming B and C are different, as they are in your example) because A cannot possibly equal both of them at the same time.
II. Program logic is in the wrong order
Furthermore, you're checking this in the wrong place. You're doing this:
Set input #0 to '0' to get us going
Does the input #0 meet my exit criteria? (no)
Take input #1
Deal with input #1
Does the input #1 meet my exit criteria? (no)
Take input #2 (say this is a space)
Deal with input #2
Does the input #2 meet my exit criteria? (YES!)
End the loop
You see how you check input #2 too late? It's already been "dealt with". You'll exit the loop just fine after implementing the above fix, but you've already appended the character to cho.
How about this:
int temp, cho = 0;
// Get input for the first iteration
char in = cin.get();
while (in != '\n' && in != ' ')
{
temp = in - '0';
if(temp >=0 && temp <=9)//so only the ASCII of digits would be entered
cho += temp;
// Now get input for the next iteration
in = cin.get();
}
The duplication isn't nice, but you can fiddle with it as you please once the logic's correct.
III. Your terminal has line buffering turned on
Finally, even with this code you may experience problems due to line buffering in your terminal: your program will be functioning absolutely correctly, but since your characters are often by default not sent to the program until a whole line is provided, there is no "live"/"instant" reaction to the act of pressing a space. Only once you hit enter are all those characters finally submitted to your program by your terminal, at which point the backlogged spaces trigger the loop exit; this makes it look like your program is only terminating on the newline condition, but it's not. You might have spotted this if you had generated some output from within your program to see how many characters it was actually processing before quitting.
You can resolve this by turning off line buffering in your terminal emulator, or by removing the ability to use spaces to terminate the loop and instead just rely on newlines — the latter is the convention as then you do not have to ask your users to configure their terminal specially to run your program: it'll already function properly in all the usual cases.
Bootnote — general advice
It's important not to assume that, if applying solution A for problem 1 doesn't immediately make your program work perfectly, that solution A must be wrong. You should consider the possibility that you also have as-yet-unknown problems 2 and 3.
It's really important to keep an open mind and gather evidence, such as writing output from your program to track its execution... or use a debugger to step through it and analyse what it is doing. As far as I can tell, you haven't really gathered any evidence at all about how your program executes… beyond cursory empirical observations, that is.
Keeping Lightness's great answer in mind, it should be noted that you're reading a single whitespace-separated token, which the built-in formatted I/O operators already do. For example, operator>>() is designed to pull out a token of input (say a number) until it reaches whitespace which is a space character and newline character.
A cleaner way of doing it would be to use the standard algorithms and classes from the standard library such as std::istream_iterator and std::accumulate():
#include <iterator>
#include <string>
#include <iostream>
#include <numeric>
int main()
{
typedef std::istream_iterator<std::string> iter_t;
iter_t it(std::cin);
int cho(0);
if (it != iter_t{})
{
auto s = *it;
cho = std::accumulate(std::begin(s), std::end(s), 0,
[] (int v, unsigned char c) { return v + c - '0'; });
}
std::cout << cho;
}
std::istream_iterator uses operator>>() internally and std::accumulate() will go through the characters, convert them to integers, and accumulate their sum.

Wait until user presses enter in C++?

waitForEnter() {
char enter;
do {
cin.get(enter);
} while ( enter != '\n' );
}
It works, but not always. It doesn't work when an enter is pressed just before the function is called.
You can use getline to make the program wait for any newline-terminated input:
#include <string>
#include <iostream>
#include <limits>
void wait_once()
{
std::string s;
std::getline(std::cin, s);
}
In general, you cannot simply "clear" the entire input buffer and ensure that this call will always block. If you know that there's previous input that you want to discard, you can add std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); above the getline to gobble up any left-over characters. However, if there was no extra input to begin with, this will cause an additional pause.
If you want full control over the console and the keyboard, you may have to look at a platform-specific solution, for instance, a terminal library like ncurses.
A select call on a Posix system that can tell you if reading from a file descriptor would block, so there you could write the function as follows:
#include <sys/select.h>
void wait_clearall()
{
fd_set p;
FD_ZERO(&p);
FD_SET(0, &p);
timeval t;
t.tv_sec = t.tv_usec = 0;
int sr;
while ((sr = select(1, &p, NULL, NULL, &t)) > 0)
{
char buf[1000];
read(0, buf, 1000);
}
}
On Windows, you can do this:
void WaitForEnter()
{
// if enter is already pressed, wait for
// it to be released
while (GetAsyncKeyState(VK_RETURN) & 0x8000) {}
// wait for enter to be pressed
while (!(GetAsyncKeyState(VK_RETURN) & 0x8000)) {}
}
I don't know the equivalent on Linux.
(the first parameter) The name of the array of type char[] in which the characters read from cin are to be stored.
(the second parameter) The maximum number of characters to be read. When the specified maximum has been read, input stops.
(the third parameter) The character that is to stop the input process. You can specify any character here, and the first occurrence of that character will stop the input process.
cin.getline( name , MAX, ‘\n’ );
Page 175 IVOR HORTON’S BEGINNING VISUAL C++® 2010