Znak zmiany znaczenia „Backspace” „\ b”: nieoczekiwane zachowanie?

101

Więc ja wreszcie czytanie przez K & R , a ja nauczyłem się czegoś w ciągu pierwszych kilku stronach, że istnieje postać ucieczka Backspace \b.

Więc idę to przetestować i jest bardzo dziwne zachowanie:

#include <stdio.h>

main ()
{
    printf("hello worl\b\bd\n");
}

Wynik jest

hello wodl

Czy ktoś może to wyjaśnić?

OregonTrail
źródło

Odpowiedzi:

145

Twój wynik będzie się różnić w zależności od rodzaju terminala lub programu konsoli, na którym się znajdujesz, ale tak, w większości przypadków \bjest to nieniszczący backspace. Przesuwa kursor do tyłu, ale nie usuwa tego, co tam jest.

Tak więc w przypadku hello worlczęści kod wyprowadza

witaj świecie
          ^

... (gdzie ^pokazuje, gdzie jest kursor) Następnie wypisuje dwa \bznaki, które przesuwają kursor do tyłu o dwa miejsca bez usuwania (na twoim terminalu):

witaj świecie
        ^

Zwróć uwagę, że kursor znajduje się teraz na r. Następnie wypisuje d, co nadpisuje ri daje nam:

cześć wodl
         ^

Na koniec wyświetla \n, co jest nieniszczącą nową linią (znowu na większości terminali, w tym najwyraźniej na twoim), więc lpozostaje niezmieniona, a kursor jest przenoszony na początek następnej linii.

TJ Crowder
źródło
1
Jeśli nie jest usuwany, to dlaczego zniknęło „r”?
cesoid
1
@cesoid: „Wynik będzie różny w zależności od
TJ Crowder
Po prostu twój przykład nie pasuje do wyniku, więc nie jest przykładem możliwego wyjaśnienia.
cesoid
5
@cesoid The rjest zastępowane przez d. Wyjaśnienie wciąż pasuje.
syockit
1
@cesoid: Interesujące informacje o terminalu. W systemie Windows, cmd.exea command.comterminale nie zawsze wstawić (można użyć klawisza Ins, aby włączyć zachowanie). Zaskoczyło mnie, że Terminal Gnome na moim głównym komputerze * nix zawsze wstawia, wydaje się, że nawet nie preferuje go, a tym bardziej przełączania na podstawie klucza Ins. Nigdy wcześniej tego nie zauważyłem. Najwyraźniej prawie nigdy nie chcę pisać na maszynie. :-)
TJ Crowder
122
..........
^ <= wskaźnik do „głowicy drukującej”
            /* part1 */
            printf("hello worl");
witaj świecie
          ^ <= wskaźnik do „głowicy drukującej”
            /* part2 */
            printf("\b");
witaj świecie
         ^ <= wskaźnik do „głowicy drukującej”
            /* part3 */
            printf("\b");
witaj świecie
        ^ <= wskaźnik do „głowicy drukującej”
            /* part4 */
            printf("d\n");
cześć wodl

^ <= wskaźnik do "głowicy drukującej" w następnym wierszu
pmg
źródło
Jeśli kursor po części 4 znajduje się na literze „l”, czy nie należy go zastąpić znakiem „\ n”? (co skutkuje "hello wor")
lucas_turci
@lucas_turci: chodzi o to, że '\n'nie ma reprezentacji na ekranie. To, co już jest, pozostaje takie samo; nie jest zastępowana spacją ani żadną inną reprezentacją znaku.
pmg
44

Jeśli chcesz destrukcyjnego backspace, potrzebujesz czegoś takiego

"\b \b"

tj. backspace, spacja i inny backspace.

Peter K.
źródło
To wciąż pozostawia znak kosmiczny, prawda?
Pacerier
Cóż, tak, ale następny \bbędzie oznaczał, że następny znak wyjściowy go nadpisze.
Peter K.
1
A jeśli nie ma kolejnego znaku?
Pacerier
Więc to nie ma znaczenia, prawda?
Peter K.
1
Hmm. Jeśli twoje urządzenie nie implementuje opcji „usuń ostatni znak” (np. DEL / 0x7f), jestem zaskoczony.
Peter K.
8

Nie jest to zbyt trudne do wyjaśnienia ... To jest jak pisanie hello worl, dwukrotne naciśnięcie klawisza strzałki w lewo, pisanie di naciskanie klawisza strzałki w dół.

Przynajmniej tak wnioskowałem, że twój terminal interpretuje kody \bi \n.

Przekieruj wyjście do pliku, a założę się, że otrzymasz coś zupełnie innego. Chociaż być może będziesz musiał spojrzeć na bajty pliku, aby zobaczyć różnicę.

[edytować]

Aby trochę rozwinąć, printfemituje sekwencję bajtów:, hello worl^H^Hd^Jgdzie^H jest znak ASCII nr 8, a ^Jjest to znak ASCII nr 10. To, co widzisz na ekranie, zależy od tego, jak terminal interpretuje te kody kontrolne.

Nemo
źródło
1

Użyj jednego znaku cofnięcia po każdym znaku printf("hello wor\bl\bd\n");

Dorothea
źródło
"cześć, \ n"? Co to znaczy?
Elias Hasle