Jaka jest składnia wielowierszowego literału ciągu?

135

Trudno mi zrozumieć, jak działa składnia napisów w Rust. W szczególności próbuję dowiedzieć się, jak utworzyć ciąg wielu wierszy.

Dumbapples
źródło
2
Możliwy duplikat Jak napisać ciąg wieloliniowy w Rust?
Jo Liss

Odpowiedzi:

173

Wszystkie literały łańcuchowe można podzielić na kilka linii; na przykład:

let string = "line one
line two";

jest łańcuchem "line one\nline two"składającym się z dwóch wierszy, tym samym co (oczywiście można \nteż bezpośrednio użyć znaku nowego wiersza). Jeśli chcesz po prostu podzielić ciąg w wielu wierszach ze względu na formatowanie, możesz pominąć nową linię i początkowe białe spacje za pomocą \; na przykład:

let string = "one line \
    written over \
    several";

jest taki sam jak "one line written over several".

Jeśli chcesz, aby w ciągu znaków występowały podziały wierszy, możesz je dodać przed \:

let string = "multiple\n\
              lines\n\
              with\n\
              indentation";

To jest to samo co "multiple\nlines\nwith\nindentation";

huon
źródło
2
Jeśli problemem jest tylko czytelność, chciałbym dodać concat!()makro, aby uzupełnić podane opcje ( doc.rust-lang.org/std/macro.concat.html )
hakononakani
82

Jeśli chcesz zrobić coś nieco dłużej, co może zawierać cudzysłowy, ukośniki odwrotne itp., Użyj nieprzetworzonej notacji literału ciągu :

let shader = r#"
    #version 330

    in vec4 v_color;
    out vec4 color;

    void main() {
        color = v_color;
    };
"#;

Jeśli masz sekwencje podwójnych cudzysłowów i symboli krzyżyka w swoim ciągu, możesz oznaczyć dowolną liczbę skrótów jako separator:

let crazy_raw_string = r###"
    My fingers #"
    can#"#t stop "#"" hitting
    hash##"#
"###;
c0g
źródło
Ale ... musisz zmienić znaki nowej linii tylko wtedy, gdy nie chcesz, aby w wyniku pojawiły się znaki nowej linii, a nieprzetworzone łańcuchy nie pomagają w tym.
bilard
Surowe łańcuchy po prostu zapobiegają konieczności dodawania znaku '\' na końcu każdej linii, jeśli nie przejmujesz się nowymi wierszami (na przykład gdy osadzasz kod, który jest agnostyczny dla nowej linii, jak shadery i jądra) lub, jak wspomniałeś do, kiedy nowe linie są rzeczywiście potrzebne. Ułatwia to tylko osadzanie kodu, który możesz chcieć edytować, i nie musisz męczyć się z „\” na końcu każdej linii. To wszystko.
c0g
1
Jeśli chcesz (lub nie masz nic przeciwko) znakom nowej linii w wynikowym ciągu, zwykłe łańcuchy w podwójnych cudzysłowach sprawdzą się doskonale, jak pokazano w innych przykładach. Jeśli chcesz uniknąć znaków nowej linii, nieprzetworzone łańcuchy nie są dobre. Naprawdę pomagają tylko wtedy, gdy tekst zawiera cudzysłowy, ukośniki odwrotne itp. - co może się zdarzyć w osadzonym źródle.
poolie
2
Rozumiem, do czego teraz zmierzasz i masz absolutną rację.
c0g
1
Pomogłoby pokazać wynik drukowania tych ciągów. Z samej odpowiedzi nie mogę powiedzieć, co się stanie z nowymi wierszami i jak obsługiwane są wcięcia.
bluenote10
48

Odpowiedź Huona jest poprawna, ale jeśli przeszkadza ci wcięcie, rozważ użycie indoc, które jest makrem proceduralnym dla ciągów wieloliniowych z wcięciem . Oznacza „dokument z wcięciem”. Udostępnia makro o nazwie, indoc!()które pobiera wielowierszowy literał ciągu i usuwa wcięcia, tak aby skrajny lewy znak niebędący spacją znalazł się w pierwszej kolumnie.

let s = indoc! {"
    line one
    line two
"};

Wynik jest "line one\nline two\n".

Biała spacja jest zachowywana względem skrajnego lewego znaku innego niż spacja w dokumencie, więc poniższy wiersz ma wcięcie w drugim wierszu o 3 spacje względem pierwszego wiersza:

let s = indoc! {"
    line one
       line two
"};

Wynik jest "line one\n line two\n".

dtolnay
źródło
8

Jeśli chcesz wciąć tekst wielowierszowy w swoim kodzie:

let s = "first line\n\
    second line\n\
    third line";

println!("Multiline text goes next:\n{}", s);

Wynik będzie następujący:

Multiline text goes next:
first line
second line
third line
Igor
źródło
Proszę wyraźnie określić , używając prozy, który fragment kodu jest ważny dla tego zachowania.
Shepmaster
W tej chwili wydaje się, że nie dodaje to niczego nowego do zaakceptowanej odpowiedzi , która stwierdza: można użyć \nznaku nowego wiersza [...], można uciec od nowej linii i początkowych białych spacji za pomocą{backslash} . (wydaje się, że bardzo trudno jest wpisać odwrotny ukośnik w kodzie w komentarzu.)
Shepmaster
2
Ten komentarz sugeruje sposób połączenia tych dwóch punktów w akceptowanej odpowiedzi: w jaki sposób można utworzyć ciąg wieloliniowy, zapisany jako wielokrotność wierszy w kodzie, ale jednocześnie można - ze względów stylistycznych lub czytelności - uzyskać własne wcięcie w kodzie, bez tego wcięcia kończącego się końcowym napisem. Nie jest to jasno określone w tekście, ale jest to typowy przypadek użycia, a zatem cenna sugestia imho. (Zobacz odpowiedź dtolnay dla wersji skrzynkowej tego.)
Dato