System Calls and Terminal Management

This lesson introduces system calls, and how to use them to clear the terminal
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, Unlimited Access
3D art showing a maid cleaning
Ryan McCombe
Ryan McCombe
Posted

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.

Clearing the Terminal using System Calls

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
}

A Practical Example

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

Flickering and Double Buffering

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 being shown to the user
  • the "back" buffer is hidden from the user and is where we’re building the next output (or frame) to be shown to the user

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.

Summary

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:

  • Learned how to use system() function to execute system-specific commands like cls for Windows and clear for Linux/macOS.
  • Understood the use of preprocessor directives to ensure cross-platform compatibility in clearing the terminal.
  • Developed a simple clock application to apply the concept of clearing the terminal screen.
  • Gained insight into the challenges of flickering in terminal output and an introduction to the concept of double buffering.
  • Prepared the groundwork for more advanced topics like interactive user interfaces and handling user inputs.

Preview of the Next Lesson

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:

  • Introduction to standard input (std::cin) and how it works.
  • Using std::getline to get input from the user.
  • Practical examples demonstrating the implementation of user input.

Was this lesson useful?

Edit History

  • First Published

Ryan McCombe
Ryan McCombe
Posted
Lesson Contents

System Calls and Terminal Management

This lesson introduces system calls, and how to use them to clear the terminal

3D art showing a progammer setting up a development environment
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, Unlimited Access
Odds and Ends
3D art showing a progammer setting up a development environment
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, unlimited access

This course includes:

  • 56 Lessons
  • Over 200 Quiz Questions
  • Capstone Project
  • Regularly Updated
  • Help and FAQ
Next Lesson

User Input in the Terminal

This lesson introduces the fundamentals of capturing user input, using std::cin and std::getline
3D Character Concept Art
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved