Řetězec doslovný - String literal

Řetězec doslovný nebo anonymní řetězec je typ doslovný v programování pro reprezentaci řetězce hodnoty v rámci zdrojového kódu jednoho počítačového programu . Nejčastěji se v moderních jazycích jedná o citovanou posloupnost znaků (formálně „ hranaté oddělovače “), stejně jako v x = "foo"případě, kde "foo"je řetězec doslovný s hodnotou foo- uvozovky nejsou součástí hodnoty a je třeba použít metodu, jako jsou únikové sekvence aby se předešlo problému srážky oddělovače a umožnilo, aby samotné oddělovače byly vloženy do řetězce. Existuje však mnoho alternativních zápisů pro zadávání řetězcových literálů, zvláště komplikovanějších případů, a přesný zápis závisí na daném konkrétním programovacím jazyce . Přesto existuje několik obecných pokynů, kterými se většina moderních programovacích jazyků řídí.

Syntax

Oddělovače v závorkách

Většina moderních programovacích jazyků používá k určení řetězcových literálů oddělovače závorek (také vyvážené oddělovače ). Nejběžnějšími oddělovači citací jsou dvojité uvozovky :

 "Hi There!"

Prázdný řetězec je doslova napsán dvojicí uvozovek, mezi nimiž není žádný znak:

 ""

Některé jazyky buď povolují, nebo nařizují použití jednoduchých uvozovek místo dvojitých uvozovek (řetězec musí začínat a končit stejným druhem uvozovek a typ uvozovek může, ale nemusí dávat mírně odlišnou sémantiku):

 'Hi There!'

Tyto uvozovky jsou nepárové (stejný znak se používá jako otvírák a zavírač), což je kocovina technologie psacího stroje, která byla předchůdcem nejstarších počítačových vstupních a výstupních zařízení.

Pokud jde o regulární výrazy , základní citovaný literál řetězce je uveden jako:

"[^"]*"

To znamená, že řetězcový literál je zapsán jako: uvozovka, následovaná nulou, jednou nebo více znaky bez uvozovek, následovaná uvozovkou . V praxi je to často komplikované únikem, jinými oddělovači a vyloučením nových řádků.

Párované oddělovače

Několik jazyků poskytuje spárované oddělovače, kde se otevírací a zavírací oddělovače liší. Ty také často umožňují vnořené řetězce, takže oddělovače mohou být vloženy, pokud jsou spárovány, ale přesto vedou ke srážce oddělovače pro vložení nepárového zavíracího oddělovače. Mezi příklady patří PostScript , který používá závorky, jako in (The quick (brown fox))a m4 , který používá backtick (`) jako počáteční oddělovač a apostrof (') jako koncový oddělovač. Tcl umožňuje jak uvozovky (pro interpolované řetězce), tak složené závorky (pro surové řetězce), jako v "The quick brown fox"nebo {The quick {brown fox}}; toto je odvozeno z jednoduchých uvozovek v unixových skořepinách a použití složených závorek v C pro složené příkazy, protože bloky kódu jsou v Tcl syntakticky totéž jako řetězcové literály - že oddělovače jsou spárovány, je zásadní pro to, aby to bylo možné.

Zatímco znaková sada Unicode obsahuje spárované (oddělené otevírání a zavírání) verze jednoduchých i dvojitých uvozovek, používané v textu, většinou v jiných jazycích než v angličtině, v programovacích jazycích se používají jen zřídka (protože je upřednostňován ASCII a tyto nejsou zahrnuty) v ASCII):

 “Hi There!”
 ‘Hi There!’
 „Hi There!“
 «Hi There!»

Párované dvojité uvozovky lze použít v jazyce Visual Basic .NET , ale mnoho dalších programovacích jazyků je nepřijme. Z důvodu kompatibility jsou upřednostňovány nespárované značky, protože je lze snáze psát na široké škále klávesnic, a tak i v jazycích, kde jsou povoleny, mnoho projektů jejich použití pro zdrojový kód zakazuje.

Oddělovače mezer

Řetězcové literály mohou být ukončeny novými řádky.

Jedním z příkladů jsou parametry šablony MediaWiki .

 {{Navbox
 |name=Nulls
 |title=[[wikt:Null|Nulls]] in [[computing]]
 }}

Pro víceřádkové řetězce může existovat speciální syntaxe.

V YAML mohou být řetězcové literály určeny relativním umístěním mezer a odsazením.

    - title: An example multi-line string in YAML
      body : |
        This is a multi-line string.
        "special" metacharacters may
        appear here. The extent of this string is
        represented by indentation.

Žádné oddělovače

Některé programovací jazyky, například Perl a PHP, umožňují v některých kontextech řetězcové literály bez jakýchkoli oddělovačů. V následujícím programu Perl, například red, greena bluejsou řetězcové literály, ale neuvedena:

%map = (red => 0x00f, blue => 0x0f0, green => 0xf00);

Perl považuje nevyhrazené sekvence alfanumerických znaků za řetězcové literály ve většině kontextů. Následující dva řádky Perlu jsou například ekvivalentní:

$y = "x";
$y = x;

Deklarativní zápis

V původním programovacím jazyce FORTRAN (například) byly řetězcové literály psány takzvanou Hollerithovou notací , kde za desetinným počtem znaků následovalo písmeno H a poté znaky řetězce:

35HAn example Hollerith string literal

Tento deklarativní styl zápisu je v kontrastu s uvozovkami s oddělovačem v závorkách , protože nevyžaduje použití vyvážených „složených“ znaků na obou stranách řetězce.

Výhody:

  • eliminuje vyhledávání textu (pro znak oddělovače), a proto vyžaduje výrazně menší režii
  • vyhýbá se problému srážky oddělovače
  • umožňuje zahrnutí metaznaků, které by jinak mohly být mylně považovány za příkazy
  • lze použít pro docela efektivní kompresi dat řetězců prostého textu

Nevýhody:

  • tento typ zápisu je náchylný k chybám, pokud jej programátoři používají jako ruční zadávání
  • zvláštní péče je nutná v případě vícebajtového kódování

To však není nevýhoda, když je předpona generována algoritmem, jak je velmi pravděpodobné.

Funkce konstruktoru

C ++ má dva styly řetězců, jeden zděděný z C (oddělený ") a bezpečnější std::stringve standardní knihovně C ++. std::stringTřída je často používán stejným způsobem řetězec doslovný by být použit v jiných jazycích, a je často přednost řetězce C-styl pro svou flexibilitu a bezpečnost vyšší. Ale přichází s výkonnostní penalizací za řetězcové literály, protože std::stringobvykle přiděluje paměť dynamicky, a musí za běhu kopírovat doslovný řetězcový literál.

Před C ++ 11 neexistoval žádný literál pro řetězce C ++ (C ++ 11 umožňuje "this is a C++ string"ss sna konci literálu), takže byla použita normální syntaxe konstruktoru, například:

  • std::string str = "initializer syntax";
  • std::string str("converting constructor syntax");
  • std::string str = string("explicit constructor syntax");

všechny mají stejný výklad. Od C ++ 11 existuje také nová syntaxe konstruktoru:

  • std::string str{"uniform initializer syntax"};
  • auto str = "constexpr literal syntax"s;

Srážka oddělovače

Při používání uvozovek, pokud si někdo přeje reprezentovat samotný oddělovač v řetězcovém doslovu, narazí na problém kolize oddělovače . Pokud je například oddělovačem uvozovka, nelze jednoduše reprezentovat samotnou dvojitou uvozovku literálem, """protože druhá uvozovka je interpretována jako konec řetězcového literálu, nikoli jako hodnota řetězce, a podobně nelze psát "This is "in quotes", but invalid."jako střední část v uvozovkách je místo toho interpretována jako mimo uvozovky. Existují různá řešení, z nichž nejobecnější je použití únikových sekvencí, jako "\""nebo "This is \"in quotes\" and properly escaped.", ale existuje mnoho dalších řešení.

Párované uvozovky, jako jsou složené závorky v Tcl, umožňují vnořené řetězce, jako například, {foo {bar} zork}ale jinak problém srážky oddělovače nevyřeší, protože nevyvážený zavírací oddělovač nelze jednoduše zahrnout, jako v {}}.

Zdvojnásobení

Řada jazyků, včetně Pascal , BASIC , DCL , Smalltalk , SQL , J a Fortran , se vyhýbá kolizím oddělovačů zdvojnásobením uvozovek, které mají být součástí samotného řetězcového literálu:

  'This Pascal string''contains two apostrophes'''
  "I said, ""Can you hear me?"""

Duální citace

Některé jazyky, například Fortran , Modula-2 , JavaScript , Python a PHP, umožňují více než jeden oddělovač citací; v případě dvou možných oddělovačů se to nazývá duální citování . Typicky to spočívá v tom, že programátorovi umožní zaměnitelné buď jednoduché nebo dvojité uvozovky - každý literál musí použít jeden nebo druhý.

  "This is John's apple."
  'I said, "Can you hear me?"'

To však neumožňuje mít jediný literál s oběma oddělovači. To lze obejít pomocí několika literálů a zřetězení řetězců :

  'I said, "This is ' + "John's" + ' apple."'

Python má řetězcové doslovné zřetězení , takže po sobě jdoucí řetězcové literály jsou zřetězeny i bez operátoru, takže to lze redukovat na:

  'I said, "This is '"John's"' apple."'

D podporuje několik oddělovačů uvozovek, přičemž takové řetězce začínají q"[a končí ]"nebo podobně pro jiný znak oddělovače (libovolný z () <> {} nebo []). D zde také podporuje řetězce ve stylu dokumentu prostřednictvím podobné syntaxe.

V některých programovacích jazycích, jako jsou sh a Perl , existují různé oddělovače, s nimiž se zachází odlišně, například s interpolací řetězce nebo ne, a proto je třeba dávat pozor při výběru oddělovače, který použít; viz různé druhy řetězců níže.

Vícenásobné citace

Dalším rozšířením je použití vícenásobného uvozování , které umožňuje autorovi zvolit, které znaky by měly určit hranice řetězcového literálu.

Například v Perlu :

qq^I said, "Can you hear me?"^
qq@I said, "Can you hear me?"@
qq§I said, "Can you hear me?"§

všechny produkují požadovaný výsledek. Ačkoli je tento zápis flexibilnější, podporuje jej jen málo jazyků; jiné než Perl, Ruby (ovlivněné Perlem) a C ++ 11 je také podporují. V C ++ 11 mohou mít nezpracované řetězce různé oddělovače, počínaje R"delimiter(a konče )delimiter". Oddělovač může mít délku od 0 do 16 znaků a může obsahovat libovolného člena základní zdrojové znakové sady kromě prázdných znaků, závorek nebo zpětného lomítka. Varianta vícenásobného citování je použití řetězců ve stylu zde dokumentu .

Lua (od 5.1) poskytuje omezenou formu hromadného citování, zejména aby umožnilo vnořování dlouhých komentářů nebo vložených řetězců. Obvykle se používá [[a ]]k oddělení doslovných řetězců (počáteční nový řádek odstraněn, jinak nezpracovaný), ale úvodní závorky mohou obsahovat libovolný počet stejných znamének a řetězec uzavírají pouze uzavírací závorky se stejným počtem znaků. Například:

local ls = [=[
This notation can be used for Windows paths: 
local path = [[C:\Windows\Fonts]]
]=]

Vícenásobné uvozovky jsou zvláště užitečné u regulárních výrazů, které obsahují obvyklé oddělovače, jako jsou uvozovky, protože se tak vyhnete nutnosti je opustit. Raný příklad je sed , kde v příkazu nahrazení lze výchozí oddělovače lomítka nahradit jiným znakem, jako v . s/regex/replacement//s,regex,replacement,

Funkce konstruktoru

Další možností, která se v moderních jazycích používá jen zřídka, je použít funkci k sestavení řetězce, nikoli jej reprezentovat přes literál. To se v moderních jazycích obecně nepoužívá, protože výpočet se provádí za běhu, nikoli v čase analýzy.

Například rané formy BASIC neobsahovaly únikové sekvence nebo jiná zde uvedená alternativní řešení, a proto bylo místo toho nutné použít CHR$funkci, která vrací řetězec obsahující znak odpovídající jeho argumentu. V ASCII má uvozovka hodnotu 34, takže pro reprezentaci řetězce s uvozovkami v systému ASCII by člověk napsal

"I said, " + CHR$(34) + "Can you hear me?" + CHR$(34)

V jazyce C je podobné zařízení k dispozici prostřednictvím sprintfa %cspecifikátoru formátu „znak“, ačkoli v přítomnosti jiných řešení se toto obecně nepoužívá:

sprintf("This is %cin quotes.%c", 34, 34);

Tyto funkce konstruktoru lze také použít k reprezentaci netisknutých znaků, ačkoli se místo toho obecně používají únikové sekvence. Podobnou techniku ​​lze použít v C ++ s std::stringoperátorem stringifikace.

Únikové sekvence

Únikové sekvence jsou obecnou technikou pro reprezentaci znaků, které je jinak obtížné přímo reprezentovat, včetně oddělovačů, netisknutých znaků (například backspace), nových řádků a prázdných znaků (které jinak nelze vizuálně rozlišit) a mají dlouhou historii. Proto jsou široce používány v řetězcových literálech a přidání únikové sekvence (buď k jednomu znaku, nebo do celého řetězce) je známé jako únikové .

Jeden znak je vybrán jako předpona pro kódování znaků, které je obtížné nebo nemožné zahrnout přímo. Nejčastěji se jedná o zpětné lomítko ; kromě jiných znaků je klíčovým bodem to, že samotné zpětné lomítko může být kódováno jako dvojité zpětné lomítko \\a pro oddělené řetězce může být samotný oddělovač kódován únikem, řekněme \"pro ". Regulární výraz pro takto uniklé řetězce lze zadat následovně , jak je uvedeno ve specifikaci ANSI C :

"(\\.|[^\\"])*"

znamená „citát; následuje nula nebo více buď uniklého znaku (zpětné lomítko následované něčím, případně zpětné lomítko nebo uvozovka), nebo neunikající, necitující znak; končící uvozovkou“-jediným problémem je rozlišení ukončovací citát z citátu, kterému předchází zpětné lomítko, kterému lze sám uniknout. Zpětné lomítko může sledovat více znaků, například v \uFFFFzávislosti na schématu úniku.

Řetězec, který unikl, pak musí být sám lexikálně analyzován a převeden řetězec, který unikl, na řetězec bez kódování, který představuje. To se provádí během fáze vyhodnocování celkového lexingu počítačového jazyka: hodnotitel lexeru celkového jazyka provede vlastní lexer pro řetězcové literály uniklé.

Mimo jiné musí být možné zakódovat znak, který normálně ukončuje řetězcovou konstantu, a navíc musí existovat nějaký způsob, jak určit samotný únikový znak. Únikové sekvence nejsou vždy hezké nebo snadno použitelné, takže mnoho překladačů nabízí i jiné způsoby řešení běžných problémů. Únikové sekvence však vyřeší každý problém s oddělovačem a většina překladačů interpretuje únikové sekvence. Když je únikový znak uvnitř řetězcového literálu, znamená to „toto je začátek únikové sekvence“. Každá úniková sekvence určuje jeden znak, který má být umístěn přímo do řetězce. Skutečný počet znaků požadovaný v sekvenci escape se liší. Únikový znak je v horní/levé části klávesnice, ale editor jej přeloží, a proto není možné jej přímo páskovat do řetězce. Zpětné lomítko se používá k reprezentaci únikového znaku v řetězcovém literálu.

Mnoho jazyků podporuje použití metaznaků uvnitř řetězcových literálů. Metaznaky mají různé interpretace v závislosti na kontextu a jazyce, ale obecně jsou jakýmsi „zpracovatelským příkazem“ pro reprezentaci tiskových nebo netisknutých znaků.

Například v doslovném řetězci C , pokud za zpětným lomítkem následuje písmeno jako „b“, „n“ nebo „t“, pak to představuje netisknutelný znak backspace , nový řádek nebo tabulátor . Nebo pokud za zpětným lomítkem následují 1-3 osmičkové číslice, pak je tato sekvence interpretována jako reprezentující libovolný znak se zadaným kódem ASCII . Toto bylo později rozšířeno, aby umožnilo modernější zápis hexadecimálního znakového kódu:

"I said,\t\t\x22Can you hear me?\x22\n"
Úniková sekvence Unicode Doslovné znaky umístěny do řetězce
\ 0 U+0000 nulový znak
(obvykle jako zvláštní případ \ ooo osmičkové notace)
\A U+0007 výstraha
\ b U+0008 backspace
\F U+000C krmivo
\ n U+000A posuv řádku (nebo nový řádek v POSIX)
\ r U+000D návrat vozíku (nebo nový řádek v systému Mac OS 9 a starších)
\ t U+0009 vodorovná tab
\proti U+000B svislá tab
\E U+001B únikový znak ( GCC , clang a tcc )
\ u ##### U+#### 16bitový znak Unicode, kde #### jsou čtyři hexadecimální číslice
\ U ########## U+####### 32bitový znak Unicode, kde ######## je osm hexadecimálních číslic (znakový prostor Unicode je v současné době široký pouze 21 bitů, takže první dvě hexadecimální číslice budou vždy nulové)
\ u {#######} U+####### 21bitový znak Unicode, kde ###### je proměnný počet hexadecimálních číslic
\X## U+00 ## Specifikace 8bitových znaků, kde # je šestnáctková číslice
\ ooo U+0 ### Specifikace 8bitových znaků, kde o je osmičkové číslo
\ " U+0022 dvojité uvozovky (")
\ & non-character used to delimit numeric escape in Haskell
\ ' U+0027 jeden citát (')
\\ U+005C zpětné lomítko (\)
\? U+003F otazník (?)

Poznámka: Ne všechny sekvence v seznamu podporují všechny analyzátory a mohou existovat i jiné únikové sekvence, které v seznamu nejsou.

Vnořený útěk

Když je kód v jednom programovacím jazyce vložen do jiného, ​​mohou vložené řetězce vyžadovat více úrovní úniku. To je obzvláště běžné u regulárních výrazů a dotazů SQL v jiných jazycích nebo jiných jazycích uvnitř skriptů prostředí. Toto dvojité uniknutí je často obtížně čitelné a autorské.

Nesprávné citace vnořených řetězců může představovat chybu zabezpečení. Použití nedůvěryhodných dat, jako v datových polích dotazu SQL, by mělo použít připravené příkazy, aby se zabránilo útoku na vložení kódu . V PHP 2 až 5.3 existovala funkce zvaná magické uvozovky, která automaticky unikla řetězcům (pro pohodlí a bezpečnost), ale kvůli problémům byla od verze 5.4 odstraněna.

Surové struny

Několik jazyků poskytuje způsob, jak určit, že literál má být zpracován bez jazykově specifické interpretace. Tím se vyhnete potřebě uniknout a získáte čitelnější řetězce.

Nezpracované řetězce jsou zvláště užitečné, když je třeba uniknout běžnému znaku, zejména v regulárních výrazech (vnořené jako řetězcové literály), kde \je široce používáno zpětné lomítko , a v cestách DOS/Windows , kde je zpětné lomítko používáno jako oddělovač cest. Hojnost zpětných lomítek je známá jako syndrom šikmého párátka a lze ji omezit použitím surových strun. Porovnejte uniklé a nezpracované názvy cest v C#:

 "The Windows path is C:\\Foo\\Bar\\Baz\\"
 @"The Windows path is C:\Foo\Bar\Baz\"

Extrémní příklady nastanou, když jsou zkombinovány - cesty Uniform Naming Convention začínají na \\, a proto uniklý regulární výraz odpovídající názvu UNC začíná 8 zpětnými lomítky "\\\\\\\\", kvůli potřebě uniknout řetězci a regulárnímu výrazu. Použití nezpracovaných řetězců toto sníží na 4 (unikající v regulárním výrazu), jako v C# @"\\\\".

V dokumentech XML oddíly CDATA umožňují použití znaků, jako jsou & a <, aniž by se analyzátor XML pokoušel interpretovat je jako součást struktury samotného dokumentu. To může být užitečné při zahrnutí doslovného textu a skriptovacího kódu, aby byl dokument dobře tvarovaný .

<![CDATA[  if (path!=null && depth<2) { add(path); }  ]]>

Víceřádkové řetězcové literály

V mnoha jazycích mohou řetězcové literály obsahovat doslovné nové řádky zahrnující několik řádků. Alternativně lze uniknout novým řádkům, nejčastěji jako \n. Například:

echo 'foo
bar'

a

echo -e "foo\nbar"

jsou oba platné bash, produkující:

foo
bar

Mezi jazyky, které umožňují doslovné nové řádky, patří bash, Lua, Perl, PHP, R a Tcl. V některých jiných jazycích řetězcové literály nemohou obsahovat nové řádky.

Dva problémy s víceřádkovými řetězcovými literály jsou úvodní a koncové nové řádky a odsazení. Pokud jsou počáteční nebo konečné oddělovače na samostatných řádcích, existují další nové řádky, a pokud nejsou, oddělovač ztěžuje čtení řetězce, zejména pro první řádek, který je často odsazen odlišně od ostatních. Dále musí být literál nezrušený, protože je zachována mezera - to přeruší tok kódu, pokud se literál vyskytuje v rámci odsazeného kódu.

Nejběžnějším řešením těchto problémů je zde řetězcový literál ve stylu dokumentu . Formálně řečeno, dokument zde není řetězcový literál, ale místo toho literál proudu nebo literál souboru. Ty pocházejí ze skriptů prostředí Shell a umožňují vkládání literálu jako vstupu do externího příkazu. Otvor oddělovač <<END, kde ENDmůže být nějaké slovo, a uzavírací oddělovač je ENDna řádku samostatně, slouží jako obsah hranice - za <<je vzhledem k přesměrování stdin z doslovný. Vzhledem k tomu, že oddělovač je libovolný, vyhýbají se také problému srážky oddělovače. Ty také umožňují odstranění počátečních záložek prostřednictvím syntaxe varianty, <<-ENDačkoli úvodní mezery nejsou odstraněny. Stejná syntaxe byla od té doby přijata pro víceřádkové řetězcové literály v řadě jazyků, zejména v jazyce Perl, a jsou také označovány jako dokumenty zde, a zachovávají syntaxi, přestože jsou řetězce a nezahrnují přesměrování. Stejně jako u jiných řetězcových literálů může mít někdy jiné specifikované chování, například interpolaci proměnných.

Python, jehož obvyklé řetězcové literály nedovolují doslovné nové řádky, má místo toho speciální formu řetězce, navrženou pro víceřádkové literály, nazývanou triple quoting . Ty používají ztrojnásobený oddělovač, buď '''nebo """. Tyto literály se používají zejména pro vloženou dokumentaci známou jako docstrings .

Tcl umožňuje doslovné nové řádky v řetězcích a nemá žádnou speciální syntaxi, která by pomáhala s víceřádkovými řetězci, ačkoli oddělovače mohou být umístěny na řádky samy a nové a koncové nové řádky odstraněny pomocí string trim, zatímco string mapmohou být použity k odstranění odsazení.

Řetězcové doslovné zřetězení

Několik jazyků poskytuje řetězcové doslovné zřetězení , kde jsou sousední řetězcové literály implicitně spojeny do jednoho literálu v době kompilace. Jedná se o funkci C, C ++, D, Ruby a Python, která ji zkopírovala z C. Toto zřetězení se děje zejména v době kompilace, během lexikální analýzy (jako fáze po počáteční tokenizaci) a je v kontrastu s dobou běhu. zřetězení řetězců (obecně s +operátorem) a zřetězení během konstantního skládání , ke kterému dochází v době kompilace, ale v pozdější fázi (po frázové analýze nebo „analýze“). Většina jazyků, jako je C#, Java a Perl, nepodporuje implicitní řetězcové doslovné zřetězení a místo toho vyžaduje explicitní zřetězení, například s +operátorem (to je také možné v D a Pythonu, ale nezákonné v C/C ++ - viz níže) ; v tomto případě může dojít ke zřetězení v době kompilace, prostřednictvím konstantního skládání, nebo může být odloženo na dobu běhu.

Motivace

V C, kde pochází koncept a termín, bylo zavedeno řetězcové doslovné zřetězení ze dvou důvodů:

  • Umožnit dlouhým řetězcům překlenout více řádků se správným odsazením na rozdíl od pokračování řádku, které zničí schéma odsazení; a
  • Chcete -li povolit konstrukci řetězcových literálů pomocí maker (prostřednictvím stringizace ).

Prakticky to umožňuje zřetězení řetězců v raných fázích kompilace („překlad“, konkrétně jako součást lexikální analýzy), aniž by bylo zapotřebí frázové analýzy nebo neustálého skládání. Následující platné jsou například C/C ++:

char *s = "hello, " "world";
printf("hello, " "world");

Následující položky jsou však neplatné:

char *s = "hello, " + "world";
printf("hello, " + "world");

To je proto, že řetězec literály mají typ pole , (C) nebo (C ++), která nemůže být přidána; ve většině ostatních jazyků to není omezení. char [n]const char [n]

To je zvláště důležité při použití v kombinaci s preprocesorem C , aby bylo možné řetězce vypočítat po předzpracování, zejména v makrech. Jako jednoduchý příklad:

char *file_and_message = __FILE__ ": message";

se (pokud se soubor nazývá ac) rozbalí na:

char *file_and_message = "a.c" ": message";

který je potom zřetězen, což odpovídá:

char *file_and_message = "a.c: message";

Běžným případem použití je konstrukce řetězců formátu printf nebo scanf , kde jsou specifikátory formátu dány makry.

Složitější příklad používá stringifikaci celých čísel (preprocesorem) k definování makra, které se rozbalí na sekvenci řetězcových literálů, které jsou poté zřetězeny do jednoho řetězcového literálu s názvem souboru a číslem řádku:

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ ":" TOSTRING(__LINE__)

Kromě syntaktických požadavků C/C ++ je implicitní zřetězení formou syntaktického cukru , což usnadňuje rozdělení řetězcových literálů na několik řádků, vyhýbá se potřebě pokračování řádku (pomocí zpětných lomítek) a umožňuje přidávat komentáře k částem řetězců. Například v Pythonu lze regulární výraz komentovat tímto způsobem:

re.compile("[A-Za-z_]"       # letter or underscore
           "[A-Za-z0-9_]*"   # letter, digit or underscore
          )

Problémy

Implicitní zřetězení řetězců není vyžadováno moderními kompilátory, které implementují konstantní skládání, a způsobuje těžko rozpoznatelné chyby v důsledku neúmyslného zřetězení z vynechání čárky, zejména ve svislých seznamech řetězců, jako v:

l = ['foo',
     'bar'
     'zork']

V souladu s tím se nepoužívá ve většině jazyků a bylo navrženo k ukončení podpory z D a Pythonu. Odebráním funkce se však naruší zpětná kompatibilita a její nahrazení operátorem zřetězení zavádí problémy přednosti - řetězcové doslovné zřetězení nastává během lexingu, před hodnocením operátora, ale zřetězení prostřednictvím explicitního operátoru probíhá současně s jinými operátory, proto má přednost je problém, který potenciálně vyžaduje závorky k zajištění požadovaného pořadí vyhodnocení.

Jemnější problém je, že v C a C ++ existují různé typy řetězcových literálů a jejich zřetězení má chování definované implementací, což představuje potenciální bezpečnostní riziko.

Různé druhy strun

Některé jazyky poskytují více než jeden druh doslovného textu, které mají odlišné chování. To se používá zejména k označení nezpracovaných řetězců (bez úniku) nebo k deaktivaci nebo povolení interpolace proměnných, ale má i jiné využití, například rozlišování znakových sad. Nejčastěji se to děje změnou uvozovek nebo přidáním předpony nebo přípony. To je srovnatelné s předponami a příponami k celočíselným literálům , například k označení hexadecimálních čísel nebo dlouhých celých čísel.

Jeden z nejstarších příkladů je ve skriptech shellu, kde jednoduché uvozovky označují nezpracovaný řetězec nebo „doslovný řetězec“, zatímco uvozovky mají únikové sekvence a variabilní interpolaci.

Například v Pythonu předchází nezpracovaným řetězcům znak rnebo R- porovnání 'C:\\Windows's r'C:\Windows'(ačkoli nezpracovaný řetězec Pythonu nemůže končit lichým počtem zpětných lomítek). Python 2 také rozlišuje dva typy řetězců: 8bitové řetězce ASCII („bajty“) (výchozí), výslovně označené předponou a bnebo B, a řetězce Unicode označené předponou unebo U. zatímco v Pythonu 3 jsou řetězce ve výchozím nastavení Unicode a bajty jsou samostatný bytestyp, který při inicializaci uvozovkami musí mít předponu b.

Zápis C# pro surové řetězce se nazývá @-citování.

@"C:\Foo\Bar\Baz\"

I když to zakáže únik, umožňuje zdvojnásobení uvozovek, které umožňují reprezentovat uvozovky v řetězci:

@"I said, ""Hello there."""

C ++ 11 umožňuje nezpracované řetězce, řetězce unicode (UTF-8, UTF-16 a UTF-32) a široké znakové řetězce určené předponami. Přidává také literály pro stávající C ++ string, což je obecně upřednostňováno před existujícími řetězci ve stylu C.

V Tcl jsou řetězce oddělené závorkami doslovné, zatímco řetězce oddělené uvozovkami mají únik a interpolaci.

Perl má širokou škálu řetězců, které jsou formálně považovány za operátory, a jsou známé jako uvozovky a podobné uvozovky . Patří sem jak obvyklá syntaxe (pevné oddělovače), tak obecná syntaxe, která umožňuje výběr oddělovačů; tyto zahrnují:

''  ""  ``  //  m//  qr//  s///  y///
q{}  qq{}  qx{}  qw{}  m{}  qr{}  s{}{}  tr{}{}  y{}{}

REXX používá znaky přípon k určení znaků nebo řetězců pomocí hexadecimálního nebo binárního kódu. Např,

'20'x
"0010 0000"b
"00100000"b

všechny poskytují znak mezery , vyhýbají se volání funkce X2C(20).

Variabilní interpolace

Jazyky se liší v tom, zda a jak interpretovat řetězcové literály jako „nezpracované“ nebo „proměnné interpolované“. Interpolace proměnných je proces vyhodnocení výrazu obsahujícího jednu nebo více proměnných a vrácení výstupu, kde jsou proměnné nahrazeny jejich odpovídajícími hodnotami v paměti. Ve skořepinových unixových shellech (stejně jako Perl a Ruby) jsou řetězce oddělené uvozovkami (") interpolovány, zatímco řetězce oddělené apostrofem (') nikoli. Například následující kód Perl :

$name     = "Nancy";
$greeting = "Hello World";
print "$name said $greeting to the crowd of people.";

produkuje výstup:

Nancy said Hello World to the crowd of people.

Znak sigil ($) je interpretován tak, aby indikoval proměnnou interpolaci.

Podobně printffunkce produkuje stejný výstup pomocí zápisu, jako například:

printf "%s said %s to the crowd of people.", $name, $greeting;

Metaznaky (%s) označují proměnnou interpolaci.

To je v kontrastu se „surovými“ řetězci:

print '$name said $greeting to the crowd of people.';

které produkují výstup jako:

$name said $greeting to the crowd of people.

Zde znaky $ nejsou sigily a nejsou interpretovány tak, aby měly jiný význam než prostý text.

Vložení zdrojového kódu do řetězcových literálů

Jazyky, kterým chybí flexibilita při zadávání řetězcových literálů, činí psaní programovacího kódu, který generuje další programovací kód, obzvláště těžkopádné. To platí zejména tehdy, když je generační jazyk stejný nebo podobný výstupnímu jazyku.

Například:

  • psaní kódu k produkci quines
  • generování výstupního jazyka z webové šablony ;
  • pomocí XSLT ke generování XSLT nebo SQL pro generování více SQL
  • generování postskriptové reprezentace dokumentu pro tiskové účely z aplikace pro zpracování dokumentů napsané v jazyce C nebo jiném jazyce.
  • psací shadery

Některé jazyky jsou však obzvláště dobře přizpůsobeny k produkci tohoto druhu výstupů podobných sobě samým, zejména ty, které podporují více možností, jak se vyhnout kolizi oddělovače.

Použití řetězcových literálů jako kódu generujícího jiný kód může mít nepříznivé důsledky pro zabezpečení, zvláště pokud je výstup alespoň částečně založen na nedůvěryhodném vstupu uživatele. To je obzvláště akutní v případě webových aplikací, kde uživatelé se zlými úmysly mohou využít těchto slabých stránek k podvracení provozu aplikace, například připojením útoku s injekcí SQL .

Viz také

Poznámky

Reference

externí odkazy