C語言中水平製表符 與退格鍵  的使用方法探索

在其渗透發表於2024-08-14

經個人實踐,C語言中使用轉義序列碼(\t)會輸出一個 8 個格數的組合,當 \t 之前的內容達到 8 * n 格時,後續內容出現在 8 * (n + 1) + 1 格。(式中 n >= 1,且為整數)

探索過程如下:
第一次在看到某大佬的科普中提到:

\b將輸出位置左移一位

\t表示一個tab的距離即1個大空格,相當於4個小空格

上述程式碼的理解:

  \t\b\t\b 表示前進四個空格然後回退一個空格,做兩次相同操作,於是數字1會定位到數字7對應的位置下方。

  \t\t\b\b 表示前進兩個大空格然後再回退兩個大空格,即將\t看成一個tab的效果,回退的是兩個tab,所以最後回到最初位置,也就是數字0對應的位置下方。

  1. 但可能是文章時間久遠,中間規範發生了變化,如今在個人的嘗試下未能重現,程式碼如下:
int main() {
    printf("1234567890123456789012345678901234567890\n");  //參考格數個位用
    printf("0        1         2         3         4\n");  //參考格數十位用
    printf("\t\ba\n");
    printf("\t\b\t\ba\n");
    printf("\t\b\t\b\t\ba\n");
    printf("\t\b\t\b\t\b\t\ba\n");
    printf("\t\t\b\b1\n");
    printf("\t\t\t\b\b\b1\n");
    printf("\t\t\t\t\b\b\b\b1\n");
    printf("\t\t\t\t\t\b\b\b\b\b1\n");
    printf("0        1         2         3         4\n");  //參考格數十位用
    printf("1234567890123456789012345678901234567890\n");  //參考格數個位用
    return 0;
}

得到的結果是:

1234567890123456789012345678901234567890
0        1         2         3         4
       a
       a
       a
       a
              1
                     1
                            1
                                   1
0        1         2         3         4
1234567890123456789012345678901234567890

結果中無論一行中 \t\b 出現幾次,內容 a 終會出現在第 8 格,而類 \t\t\b\b 的程式碼則會使內容 a 出現在 8 + 7 * n 格。結果明顯不符合預期之後懷疑是 \t 可能會在與其它轉義序列碼組合時發生變化,或者是可能會與前面內容的長度(格數)有關。

  1. 首先考慮是 \t 可能會在與其它轉義序列碼組合時發生變化,因此進行了組合嘗試,程式碼如下:
int main() {
    printf("12345678901234567890\n");
    printf("0        1         2\n");
    printf("\ta\n");
    printf("\ba\n");
    printf("\t\ba\n");
    printf("1234\t\ba\n");
    printf("12\b34\t\ba\n");
    printf("12\b34\ta\n");
    printf("12\a34\t\ba\n");
    printf("12\b\a34\t\ba\n");
    printf("12\a\b34\t\ba\n");
    printf("0        1         2\n");
    printf("12345678901234567890\n");
    return 0;
}

得到的結果是:

12345678901234567890
0        1         2
        a
a
       a
1234   a
134    a
134     a
1234   a
134    a
134    a
0        1         2
12345678901234567890

結果中如果不受 \t 後的轉義序列碼影響,內容 a 終會出現在第 8 格。因此可知,\t 後的內容並不會受到前面一部分的轉義序列碼影響。

  1. 既然前面猜想錯誤,那麼就可能會與前面內容的長度(格數)有關,因此咋去除了一般 \t 前後的 \b 後進行了長度測試,程式碼如下:
int main() {
    printf("12345678901234567890\n");
    printf("0        1         2\n");
    printf("123456\ta\n");
    printf("1234567\ta\n");
    printf("12345678\ta\n");
    printf("123456789\ta\n");
    printf("1234567890\ta\n");
    printf("123456789012345\ta\n");
    printf("1234567890123456\ta\n");
    printf("1234567890\ta12\tb\n");
    printf("1234567890\t\b\b\b\b\b\b\ba12\tb\n");
    printf("1234567890\t\b\b\b\b\b\b\b\b\b\ba12\tb\n");
    printf("1234567890\b\b\b\ba12\tb\n");
    printf("0        1         2         3\n");
    printf("123456789012345678901234567890\n");
    return 0;
}

結果如下:

12345678901234567890
0        1         2
123456  a
1234567 a
12345678        a
123456789       a
1234567890      a
123456789012345 a
1234567890123456        a
1234567890      a12     b
123456789a12    b
123456a120      b
123456a120      b
0        1         2         3
123456789012345678901234567890

結果中可以發現,當第一個 \t 前的內容少於 7 格時,內容 a 總會出現在第 9 格;當第一個 \t 前的內容大於等於 8 格小於等於 15 格時內容 a 會出現在第 17 格,因此可以類比得出:\t 會輸出一個 8 個格數的組合,當 \t 之前的內容達到 8 * n 格時,後續內容出現在 8 * (n + 1) + 1 格。

同時,根據最後三例結果:

123456789a12    b
123456a120      b
123456a120      b

可以得出:\b 會刪去該序列組合左側的空格,遇到非空格的內容會對該格進行覆蓋佔用,並在繼續向左佔用後恢復右側未佔用格中的內容。

探索仍在繼續,過程可能出現錯誤,如能指出則萬分感謝!

相關文章