Soon, we'll be working with libraries that help us create fully interactive user interfaces. But, before we move on to that, it's worth quickly covering how we can improve the terminal output.
Even though the products we ship to users generally aren't going to be interacted with on the terminal, Command Line Interfaces (CLIs) are very common for internal tools, intended to be used by other developers.
Currently, our output has always been a vertical stream of text. Typically, a better user experience is to update the existing output on the screen, rather than appending new information below the old.
A common technique to accomplish this is to clear the terminal before sending our next output. To clear the terminal, we can send commands to the underlying operating system, using the system()
function.
For example, when using the Windows command prompt, we can clear the screen by typing the command "cls" and pressing enter.
Within our C++ program, we can trigger this same behavior by calling system("cls")
:
void ClearScreen() {
system("cls");
}
In Linux and macOS, the equivalent command is "clear". When we’re building for Windows, the compiler defines the _WIN32
preprocessor directive, which we can use to ensure our code is sending the correct system command:
void ClearScreen() {
#if defined _WIN32
system("cls");
#elif
system("clear");
#endif
}
We can use this to create a simple clock application, that updates every second:
#include <chrono>
#include <iomanip>
#include <iostream>
#include <thread>
void ClearScreen() {
#if defined _WIN32
system("cls");
#elif
system("clear");
#endif
}
int main() {
using namespace std::chrono;
while (true) {
std::string Time{std::format(
"Time: {:%H:%M:%OS}", system_clock::now()
)};
ClearScreen();
std::cout << Time;
std::this_thread::sleep_for(seconds(1));
}
}
Time: 21:24:50
If we expand this technique to implement more elaborate rendering, we’re likely to start noticing flickering effects. This is caused because rendering output takes time, and for the duration between clearing the terminal and generating the next output, there would be nothing on the screen at all.
This can be minimized simply by minimizing the amount of work that the user’s system needs to do between clearing the screen and drawing the next screen.
To eliminate the problem entirely, we’d need to rely on a technique called double buffering. We can think of a buffer as the canvas where we’re drawing our output:
The front buffer is shown until the back buffer is ready, and then they get swapped around. The back buffer becomes the front buffer and is shown to the user, and the previous front buffer becomes the back buffer, where we start generating the next frame.
Using this technique, the user only ever sees complete frames. We cover this and other techniques for improving our visual output in the next course.
Next, we'll see how we can extend our use of the terminal to get input from our users, letting our software react to their input.
In this lesson, we explored how to enhance terminal interfaces by using system calls to clear the screen. This fundamental technique not only improves the user experience for CLI tools but also sets a foundation for more advanced UI management in programming.
Key Takeaways:
system()
function to execute system-specific commands like cls
for Windows and clear
for Linux/macOS.In the upcoming lesson, we will dive into the interactive aspect of command line interfaces by focusing on getting user input in the terminal.
Key Topics for the Next Lesson:
std::cin
) and how it works.std::getline
to get input from the user.This lesson introduces system calls, and how to use them to clear the terminal
Become a software engineer with C++. Starting from the basics, we guide you step by step along the way