#c #escaping #ansi
Вопрос:
Изучая контрольные последовательности 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));
}
}
Насколько я понимаю, криминалист офсетной Д перемещает курсор назад офсетной раз, если это возможно в текущей строке, а затем я cout
случайная цифра, что перемещает курсор вперед 1 раз, затем я использую криминалист смещение — 1 С , чтобы переместить его вперед смещение — 1 раз, то следует вернуться курсор N 1 для строк позиций, поэтому Н цифр идти до курсора, но иногда идет дальше, чем Н 1, значит, после нескольких итераций он заканчивается в конце строки. Я хотел бы знать, почему это происходит.
Однако, когда я использую cout << "x1b[" << 1 << "D";
, а затем cout << "x1b[" << offset << "C";
вместо cout << "x1b[" << offset - 1 << "C";
этого это работает нормально.
Я также знаю об использовании CSI n G, который также отлично работает, но я хочу понять, что происходит с CSI n C/D. Может быть, это моя математическая ошибка, но не использовать cout << "x1b[" << 1 << "D";
, похоже, равносильно использованию cout << "x1b[" << offset - 1 << "C";
, так что это действительно сбивает меня с толку.
Комментарии:
1. Почему вы перемещаете курсор сначала назад, а затем вперед? И почему
offset - 1
— как только вы напишете цифру, вам придется вернуться еще на одну, так что это такoffset 1
. Оч — вы хотите, чтобы курсор «оставался» справа?2. После того, как
for
петли уже по N цифр в строке (е.G, если н = 5, то позиция курсора находится в 6), так что придется возвращатьсяoffset
раз (скажем, 3, поэтому курсор находится в 6 — 3 = 3 позиции), а затемcout
перемещает его 1 раз вперед (3 1 = 4), то у меня переместить егоoffset - 1
вперед (4 (3 — 1) = 6).
Ответ №1:
Кажется, что x1b[0C
курсор перемещается вправо, по крайней мере, на моем терминале (не знаю, указано ли это/требуемое поведение).
$ printf "ax1b[0Cbn"
a b
$ printf "ax1b[1Cbn"
a b
Проверьте offset - 1
, не равно ли нулю.
if (offset - 1) {
cout << "x1b[" << offset - 1 << "C";
}
Комментарии:
1. Большое спасибо, он действительно перемещает его 1 раз, если я делаю это, используя 0 в качестве
offset
значения (для CSI n D работает одинаково). Как я понимаю, это происходит, когдаoffset
равно 1, значитoffset - 1
, равно 0, поэтому CUF все равно перемещает его