不清楚 ANSI CUB/CUF 行为

Unclear ANSI CUB/CUF behaviour

在研究 ANSI 控制序列时,我遇到了不明确的行为。

我尝试在终端中制作“矩阵”效果, 在 n 0/1 位数字的一行中每次循环迭代更改一个随机数字:

#include <iostream>
#include <chrono>
#include <thread>

const int n = 5; // row length
const int pause = 50; // milliseconds

int main() {
    using namespace std;
    using this_thread::sleep_for;
    using chrono::milliseconds;

    for (int i = 0; i < n; i++) {
      cout << rand() % 2;
    }

    int offset;
    while (true) {
      offset = rand() % n + 1; // random digit in row 1..n

      cout << "\x1b[" << offset << "D";
      cout.flush();
      sleep_for(milliseconds(pause));

      cout << rand() % 2;
      cout.flush();
      // cout << "\x1b[" << 1 << "D";
      // cout.flush();
      sleep_for(milliseconds(pause));

      cout << "\x1b[" << offset - 1 << "C";
      cout.flush();
      sleep_for(milliseconds(pause));
    }
}

据我了解CSI offset D 将光标向后移动 offset 次,如果在当前行中可能的话,那么我 cout 随机数字,将光标向前移动 1 次,然后我使用 CSI offset - 1 C 将其向前移动 offset - 1 次,即应该 return 光标到 n + 1 行位置,所以 n 数字在光标之前,但有时它比 n + 1,因此,经过几次迭代后,它最终出现在该行的末尾。我想知道为什么会这样。

但是,当我使用 cout << "\x1b[" << 1 << "D"; 然后 cout << "\x1b[" << offset << "C"; 而不是 cout << "\x1b[" << offset - 1 << "C"; 时,它工作正常。

我也知道使用 CSI n G,它也可以正常工作,但我想了解 CSI n [=48 是怎么回事=]。也许这是我的数学错误,但不使用 cout << "\x1b[" << 1 << "D"; 似乎等同于使用 cout << "\x1b[" << offset - 1 << "C"; 所以我真的很困惑。

似乎 \x1b[0C 将光标向右移动,至少在我的终端上是这样(不知道这是否是 specified/required 行为)。

$ printf "a\x1b[0Cb\n"
a b
$ printf "a\x1b[1Cb\n"
a b

检查 offset - 1 是否不为零。

if (offset - 1) {
  cout << "\x1b[" << offset - 1 << "C";
}