Reputation: 31
I am currently making a Self Service Order Payment Program for a project and I was trying to figure out a way to erase the previous line of text to make it look cleaner. I discovered there was a similar function to system("CLS");
but instead of erasing all the text in the console, it only erases certain parts of the text.
I've been coding for about a week or two so if I missed anything please tell me.
switch(buy){
case '1':
//random code
break;
default:
cout << "sorry thats not a valid number ;w;\n\n"; //remove this text after system("pause")
system("pause");
system("CLS"); //I need this to remove only one line instead of the whole thing.
break;
}
Upvotes: 0
Views: 2188
Reputation: 16767
As I know there are no standard C++ only solutions for your task, there are platform-dependend ways that I'll describe below.
Main thing needed to achieve your task is to move cursor one line up. Afterwards you can just print spaces to clear line (and move cursor to start of line through \r
).
I provide two next variants (Variant 1 and Variant 2) of solving your task.
Variant 1. Using ANSI escape codes (Windows/Linux/MacOS).
There are so-called ANSI escaped codes that allow you to do rich manipulations of console. Including your task (moving cursor one line up).
Through this escape codes moving line up is achieved by printing string "\x1b[1A"
to console (to move e.g. 23 lines up you may print "\x1b[23A"
, see 23 inside this string). Also you may want to move cursor to right, this is achieved through "\x1b[23C"
(to move 23 positions to right).
By default Linux/MacOS and other POSIX systems usually support ANSI escape codes (different terminal implementations may or may not support them). Windows also supports ANSI escape codes but they are not enabled by default, it needs to be enabled by special WinAPI functions.
Inside ClearLines()
function don't forget to tweak width
argument, it is set to 40
right now, it signifies width of your console, precisely it clears only first width
chars of line with spaces.
Next code does what you need for Windows and Unix systems. Windows-specific code is located between #ifdef
and #endif
.
#include <iostream>
#include <cstdlib>
#ifdef _WIN32
#include <windows.h>
inline bool WinAnsiConsoleEnable(int stdout_or_stderr = 0) {
if (!SetConsoleOutputCP(65001)) // Enable UTF-8 console if needed.
return false;
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif
DWORD outMode = 0;
HANDLE stdoutHandle = GetStdHandle(stdout_or_stderr == 0 ?
STD_OUTPUT_HANDLE : stdout_or_stderr == 1 ? STD_ERROR_HANDLE : 0);
if (stdoutHandle == INVALID_HANDLE_VALUE)
return false;
if (!GetConsoleMode(stdoutHandle, &outMode))
return false;
// Enable ANSI escape codes
outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (!SetConsoleMode(stdoutHandle, outMode))
return false;
return true;
}
#endif // _WIN32
static void ClearLines(size_t cnt, size_t width = 40) { // Clears cnt last lines.
std::cout << "\r";
for (size_t i = 0; i < cnt; ++i) {
for (size_t j = 0; j < width; ++j)
std::cout << " ";
std::cout << "\r";
if (i + 1 < cnt)
std::cout << "\x1b[1A"; // Move cursor one line up, ANSI sequence.
}
}
int main() {
#ifdef _WIN32
if (!WinAnsiConsoleEnable()) {
std::cout << "Error enabling Win ansi console!" << std::endl;
return -1;
}
#endif
bool good = false;
char buy = 0;
std::cout << "Enter number:" << std::endl;
while (!good) {
std::cin >> buy;
switch (buy) {
case '1': {
std::cout << "Valid number." << std::endl;
good = true;
break;
}
default: {
std::cout << "Sorry thats not a valid number!\n";
#ifdef _WIN32
std::system("pause");
#else
std::system("read -p \"Press enter to continue . . . \" x");
#endif
ClearLines(4);
break;
}
}
}
}
Output (shown on Linux, Windows is same) (+ ascii-video):
Variant 2. Using WinAPI functions (Windows-only).
Next variant works only for windows and uses only WinAPI console manipulation functions (no ANSI escapes).
#include <iostream>
#include <cstdlib>
#include <windows.h>
// Moves cursor by (DeltaX, DeltaY) = (offx, offy) relative to current position.
inline bool WinMoveCursor(int offx, int offy) {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO cbsi = {};
if (!GetConsoleScreenBufferInfo(hConsole, &cbsi))
return false;
COORD coord = cbsi.dwCursorPosition;
coord.X += offx;
coord.Y += offy;
if (!SetConsoleCursorPosition(hConsole, coord))
return false;
return true;
}
static void ClearLines(size_t cnt, size_t width = 40) { // Clears cnt last lines.
std::cout << "\r";
for (size_t i = 0; i < cnt; ++i) {
for (size_t j = 0; j < width; ++j)
std::cout << " ";
std::cout << "\r";
if (i + 1 < cnt)
WinMoveCursor(0, -1); // Move cursor one line up, WinAPI.
}
}
int main() {
SetConsoleOutputCP(65001); // Enable UTF-8 if needed.
bool good = false;
char buy = 0;
std::cout << "Enter number:" << std::endl;
while (!good) {
std::cin >> buy;
switch (buy) {
case '1': {
std::cout << "Valid number." << std::endl;
good = true;
break;
}
default: {
std::cout << "Sorry thats not a valid number!\n";
std::system("pause");
ClearLines(4);
break;
}
}
}
}
Upvotes: 0
Reputation: 118077
The \n
s at the end of this line makes it hard to remove the text on the line using only standard control characters:
cout << "sorry thats not a valid number ;w;\n\n";
Also, the system("pause");
is non-standard and will likely also result in a newline (I'm not sure about that).
What you could do is to skip the printing of \n
and to just sleep a little before continuing.
Example:
#include <chrono> // misc. clocks
#include <iostream>
#include <string>
#include <thread> // std::this_thread::sleep_for
// a function to print some text, sleep for awhile and then remove the text
void print_and_clear(const std::string& txt, std::chrono::nanoseconds sleep) {
std::cout << txt << std::flush; // print the text
std::this_thread::sleep_for(sleep); // sleep for awhile
// Remove the text by returning to the beginning of the line and
// print a number of space characters equal to the length of the
// text and then return to the beginning of the line again.
std::cout << '\r' << std::string(txt.size(), ' ') << '\r' << std::flush;
}
int main() {
print_and_clear("sorry thats not a valid number...", std::chrono::seconds(1));
std::cout << "Hello\n";
}
The above will print your text, sleep for a second, then remove the text and continue. What's left on the screen after the program has executed is only Hello
.
Upvotes: 2
Reputation: 128
You can do:-
cout<<"\r lots of spaces "<<endl;
basically what \r escape sequence does is that it brings the cursor to the start of the line. If you print anything after printing \r it will overwrite what was already on that line
Upvotes: 0
Reputation: 97
you need to declare a variable and then use if condition.
i don`t know c++ but i give to hint here.
bool systempaused=false;
later on
if(!systempaused)
{
//print your line
}
system("pause")
Upvotes: 0