Słyszałem, że powinieneś unikać prowadzenia nowych linii podczas korzystania printf
. Więc zamiast tego printf("\nHello World!")
powinieneś użyćprintf("Hello World!\n")
W tym konkretnym przykładzie powyżej nie ma to sensu, ponieważ wynik byłby inny, ale rozważ to:
printf("Initializing");
init();
printf("\nProcessing");
process_data();
printf("\nExiting");
w porównaniu do:
printf("Initializing\n");
init();
printf("Processing\n");
process_data();
printf("Exiting");
Nie widzę żadnych korzyści z końcowymi znakami nowej linii, poza tym, że wygląda lepiej. Czy jest jakiś inny powód?
EDYTOWAĆ:
Zajmę się głosowaniem w tej sprawie tutaj i teraz. Nie sądzę, że należy to do przepełnienia stosu, ponieważ to pytanie dotyczy głównie projektowania. Powiedziałbym również, że chociaż mogą to być opinie w tej sprawie, odpowiedź Kiliana Fotha i odpowiedź cmastera dowodzą, że rzeczywiście jedno podejście przynosi bardzo obiektywne korzyści.
init()
iprocess_data()
wydrukuj coś samodzielnie? Jak wyglądałby wynik, gdyby tak się stało?\n
jest terminatorem linii , a nie separatorem linii . Dowodem na to jest fakt, że pliki tekstowe w systemie UNIX prawie zawsze kończą się na\n
.Odpowiedzi:
Spora liczba terminali I / O jest buforowana w linii , więc kończąc komunikat \ n możesz mieć pewność, że zostanie on wyświetlony w odpowiednim czasie. W przypadku \ \ wiadomość może lub nie może być wyświetlana od razu. Często oznacza to, że każdy krok wyświetla komunikat postępu z poprzedniego kroku, co nie powoduje końca zamieszania i marnowania czasu, gdy próbujesz zrozumieć zachowanie programu.
źródło
fprintf(STDERR, …)
zamiast tego, który zasadniczo nie jest buforowany dla danych diagnostycznych.W systemach POSIX (w zasadzie każdy Linux, BSD, dowolny system oparty na otwartym kodzie źródłowym), linia jest zdefiniowana jako ciąg znaków zakończony znakiem nowej linii
\n
. Jest to podstawowe założenie wszystkich standardowych narzędzi wiersza poleceń opierać, w tym (ale nie tylko)wc
,grep
,sed
,awk
, ivim
. Jest to również powód, dla którego niektóre edytory (jakvim
) zawsze dodają znak\n
na końcu pliku i dlaczego wcześniejsze standardy C wymagały, aby nagłówki kończyły się\n
znakiem.Btw: Posiadanie
\n
zakończonych linii znacznie ułatwia przetwarzanie tekstu: Wiesz, że masz kompletną linię, kiedy masz ten terminator. I wiesz na pewno, że musisz spojrzeć na więcej postaci, jeśli jeszcze nie spotkałeś tego terminatora.Oczywiście dzieje się tak po stronie wejściowej programów, ale dane wyjściowe programu są bardzo często używane jako dane wejściowe programu. Twoje dane wyjściowe powinny być więc zgodne z konwencją, aby umożliwić płynne wprowadzanie danych do innych programów.
źródło
Oprócz tego, co inni wspominali, wydaje mi się, że istnieje znacznie prostszy powód: to standard. Ilekroć cokolwiek drukuje do STDOUT, prawie zawsze zakłada, że jest już w nowej linii, a zatem nie musi zaczynać nowej. Zakłada również, że następny wiersz, który ma zostać napisany, będzie działał w ten sam sposób, więc pomocnie kończy się, rozpoczynając nowy wiersz.
Jeśli wypiszesz linie wiodące nowego wiersza przeplecione ze standardowymi liniami końcowymi nowej linii, ”będzie to wyglądać następująco:
... który prawdopodobnie nie jest tym, czego chcesz.
Jeśli użyjesz tylko wiodących znaków nowej linii w swoim kodzie i uruchomisz go tylko w środowisku IDE, może się okazać, że jest w porządku. Jak tylko uruchomisz go w terminalu lub wprowadzisz kod innej osoby, który napisze STDOUT wraz z twoim kodem, zobaczysz niepożądane wyjście jak wyżej.
źródło
$PS1
, która będzie drażniąca po konwencjonalnych programach.Ponieważ wysoko głosowane odpowiedzi podały już doskonałe techniczne powody, dla których preferowane powinny być końcowe linie, podejdę do tego z innej perspektywy.
Moim zdaniem poniższe uwagi sprawiają, że program jest bardziej czytelny:
Z powyższych punktów możemy argumentować, że końcowe znaki nowej linii są lepsze. Newlines formatują „szum” w porównaniu do wiadomości, wiadomość powinna się wyróżniać, a zatem powinna być na pierwszym miejscu (może również pomóc wyróżnianie składni).
źródło
"ok\n"
jest znacznie lepszy niż"\nok"
..."\pFoobar"
.Korzystanie ze znaku nowej linii upraszcza późniejsze modyfikacje.
Jako (bardzo trywialny) przykład oparty na kodzie OP, załóżmy, że musisz wygenerować jakieś dane wyjściowe przed komunikatem „Inicjalizacja”, a dane wyjściowe pochodzą z innej logicznej części kodu, w innym pliku źródłowym.
Po uruchomieniu pierwszego testu i stwierdzeniu, że „Inicjalizacja” jest teraz dołączana na końcu wiersza innego wyjścia, należy przeszukać kod, aby znaleźć miejsce, w którym został wydrukowany, a następnie mieć nadzieję, że zmieni się „Inicjalizacja” na „\ nInicjalizacja „nie psuje formatu czegoś innego, w różnych okolicznościach.
Teraz zastanów się, jak poradzić sobie z faktem, że twoje nowe wyjście jest w rzeczywistości opcjonalne, więc zmiana na „\ nInicjowanie” czasami powoduje niechcianą pustą linię na początku wyjścia ...
Czy ustawiasz flagę globalną ( wstrząs? wcześniejsze dane wyjściowe i pozostawiają przyszłe czytniki kodów zastanawiające się, dlaczego ta „inicjalizacja” nie ma wiodącego „\ n”, tak jak wszystkie inne komunikaty wyjściowe?
Jeśli konsekwentnie wypisujesz końcowe znaki nowej linii, w miejscu, w którym wiesz, że dotarłeś do końca linii, która musi zostać zakończona, omijasz wszystkie te problemy. Zauważ, że może to wymagać osobnej instrukcji put ("\ n") na końcu jakiejś logiki, która generuje wiersz po kawałku, ale chodzi o to, że wypisujesz nowy wiersz w najwcześniejszym miejscu w kodzie, gdzie wiesz, że musisz rób to, nie gdzie indziej.
źródło
Dokładnie dopasuj specyfikację C
Biblioteka C definiuje linię jako kończącą się znakiem nowej linii
'\n'
.Kod, który zapisuje dane jako linie, będzie wówczas pasował do tej koncepcji biblioteki.
Re: ostatni wiersz wymaga zakończenia znaku nowej linii . Polecam zawsze pisać końcowy
'\n'
wynik i tolerować jego brak na wejściu.Sprawdzanie pisowni
Mój moduł sprawdzania pisowni narzeka. Być może twoje też.
źródło
ispell.el
aby lepiej sobie z tym poradzić. Przyznaję, że częściej\t
był to problem i można było tego uniknąć, dzieląc ciąg na wiele tokenów, ale był to tylko efekt uboczny bardziej ogólnej pracy polegającej na „ignorowaniu”, polegającej na selektywnym pomijaniu nietekstowych części HTML lub ciała wieloczęściowe MIME i części kodu bez komentarzy. Zawsze chciałem rozszerzyć go na przełączanie języków, w których są odpowiednie metadane (np.<p lang="de_AT">
LubContent-Language: gd
), ale nigdy nie otrzymałem Round Tuit. A opiekun całkowicie odrzucił moją łatkę. :-(ispell.el
.Wiodące znaki nowej linii często ułatwiają pisanie kodu, gdy występują warunki warunkowe, na przykład
(Ale jak zauważono w innym miejscu, może być konieczne opróżnienie bufora wyjściowego przed wykonaniem jakichkolwiek czynności, które zajmują dużo czasu procesora).
W związku z tym można przedstawić dobry przypadek dla obu sposobów zrobienia tego, jednak osobiście nie lubię printf () i użyłbym niestandardowej klasy do zbudowania wyniku.
źródło
"\nProcessing"
.printf
. Co jeśli chcesz warunkować całą linię „Inicjalizacja”? Musisz podać w tym stanie wiersz „Przetwarzanie”, aby wiedzieć, czy powinieneś przedrostkiem nowego wiersza, czy nie. Jeśli przed tobą jest inny wydruk i musisz uwarunkować wiersz „Przetwarzanie”, musisz również dołączyć następny wydruk w tym stanie, aby wiedzieć, czy powinieneś przedrostek z nowym znakiem nowej linii i tak dalej dla każdego wydruku.if ((addr & 0x0F)==0) printf("\n%08X:", addr);
I bezwarunkowo dodać nowy wiersz na końcu, niż użyć oddzielny kod dla nagłówka każdego wiersza i końcowego nowego wiersza.Wiodące znaki nowej linii nie działają dobrze z innych funkcji bibliotecznych, w szczególności
puts()
iperror
w Bibliotece standardzie, ale także każdej innej biblioteki najprawdopodobniej w użyciu.Jeśli chcesz wydrukować wcześniej napisaną linię (stałą lub już sformatowaną - np. Za pomocą
sprintf()
), toputs()
jest naturalny (i wydajny) wybór. Jednak nie ma sposobu,puts()
aby zakończyć poprzednią linię i napisać linię niezakończoną - zawsze zapisuje terminator linii.źródło