Existe alguma maneira de ter texto simples com várias linhas, literais constantes em C ++, à Perl? Talvez algum truque de análise de #include
um arquivo? Eu não consigo pensar em um, mas garoto, isso seria legal. Eu sei que será em C ++ 0x.
Existe alguma maneira de ter texto simples com várias linhas, literais constantes em C ++, à Perl? Talvez algum truque de análise de #include
um arquivo? Eu não consigo pensar em um, mas garoto, isso seria legal. Eu sei que será em C ++ 0x.
Respostas:
Bem ... Mais ou menos. O mais fácil é usar apenas o fato de que literais de string adjacentes são concatenados pelo compilador:
const char *text =
"This text is pretty long, but will be "
"concatenated into just a single string. "
"The disadvantage is that you have to quote "
"each part, and newlines must be literal as "
"usual.";
O recuo não importa, pois não está dentro das aspas.
Você também pode fazer isso, contanto que evite a nova linha incorporada. Não fazer isso, como minha primeira resposta, não compilará:
const char * text2 = "Aqui, por outro lado, eu fiquei louco \ e realmente deixar o literal abranger várias linhas, \ sem se preocupar em citar \ cada linha conteúdo. Isso funciona, mas você não pode recuar. ";
Novamente, observe as barras invertidas no final de cada linha; elas devem estar imediatamente antes do final da linha; elas estão escapando da nova linha na fonte, para que tudo funcione como se a nova linha não estivesse lá. Você não recebe novas linhas na string nos locais em que havia barras invertidas. Com esse formulário, você obviamente não pode recuar o texto, pois o recuo se tornaria parte da string, exibindo-o em espaços aleatórios.
No C ++ 11, você tem literais de cadeia bruta. Mais ou menos como o texto aqui em shell e linguagens de script como Python, Perl e Ruby.
const char * vogon_poem = R"V0G0N(
O freddled gruntbuggly thy micturations are to me
As plured gabbleblochits on a lurgid bee.
Groop, I implore thee my foonting turlingdromes.
And hooptiously drangle me with crinkly bindlewurdles,
Or I will rend thee in the gobberwarts with my blurlecruncheon, see if I don't.
(by Prostetnic Vogon Jeltz; see p. 56/57)
)V0G0N";
Todos os espaços e recuo e as novas linhas na sequência são preservados.
Eles também podem ser utf-8 | 16 | 32 ou wchar_t (com os prefixos comuns).
Devo salientar que a sequência de escape, V0G0N, não é realmente necessária aqui. Sua presença permitiria colocar) "dentro da string. Em outras palavras, eu poderia ter colocado
"(by Prostetnic Vogon Jeltz; see p. 56/57)"
(observe aspas extras) e a sequência acima ainda estaria correta. Caso contrário, eu poderia muito bem ter usado
const char * vogon_poem = R"( ... )";
As parênteses dentro das aspas ainda são necessárias.
#if 0
… #endif
para comentar os blocos de código. Ninhos também.
#define MULTILINE(...) #__VA_ARGS__
Consome tudo entre parênteses.
Substitui qualquer número de caracteres consecutivos de espaço em branco por um único espaço.
\n
se você precisar de novas linhas
` (and hence
\ n ) is copied literally, but
"` é convertido em \"
. Então, MULTILINE(1, "2" \3)
produz "1, \"2\" \3"
.
Uma maneira provavelmente conveniente de inserir seqüências de várias linhas é usando macro. Isso só funciona se aspas e parênteses estiverem equilibrados e não contiver vírgulas de nível superior:
#define MULTI_LINE_STRING(a) #a
const char *text = MULTI_LINE_STRING(
Using this trick(,) you don't need to use quotes.
Though newlines and multiple white spaces
will be replaced by a single whitespace.
);
printf("[[%s]]\n",text);
Compilado com o gcc 4.6 ou g ++ 4.6, isso produz: [[Using this trick(,) you don't need to use quotes. Though newlines and multiple white spaces will be replaced by a single whitespace.]]
Observe que ,
não pode estar na sequência, a menos que esteja entre parênteses ou aspas. Aspas simples são possíveis, mas cria avisos do compilador.
Editar: Como mencionado nos comentários, #define MULTI_LINE_STRING(...) #__VA_ARGS__
permite o uso de ,
.
#define MULTILINE(...) #__VA_ARGS__
se quiser que sua string contenha vírgulas.
\n
e \r
), o que é útil para alguns casos e fatal para outros.
Você também pode fazer isso:
const char *longString = R""""(
This is
a very
long
string
)"""";
char longString[] = R""""( This is a very long string )"""";
também funciona para mim.
Você pode fazer isso:
const char *text = "This is my string it is "
"very long";
Como uma onça de experiência vale uma tonelada de teoria, tentei um pequeno programa de teste para MULTILINE
:
#define MULTILINE(...) #__VA_ARGS__
const char *mstr[] =
{
MULTILINE(1, 2, 3), // "1, 2, 3"
MULTILINE(1,2,3), // "1,2,3"
MULTILINE(1 , 2 , 3), // "1 , 2 , 3"
MULTILINE( 1 , 2 , 3 ), // "1 , 2 , 3"
MULTILINE((1, 2, 3)), // "(1, 2, 3)"
MULTILINE(1
2
3), // "1 2 3"
MULTILINE(1\n2\n3\n), // "1\n2\n3\n"
MULTILINE(1\n
2\n
3\n), // "1\n 2\n 3\n"
MULTILINE(1, "2" \3) // "1, \"2\" \3"
};
Compile esse fragmento com cpp -P -std=c++11 filename
para reproduzir.
O truque #__VA_ARGS__
é que __VA_ARGS__
não processa o separador de vírgulas. Então você pode passá-lo para o operador de stringing. Os espaços à esquerda e à direita são aparados e os espaços (incluindo novas linhas) entre as palavras são compactados em um único espaço. Os parênteses precisam ser equilibrados. Acho que essas deficiências explicam por que os designers do C ++ 11, apesar de tudo #__VA_ARGS__
, viram a necessidade de literais de strings brutos.
Apenas para elucidar um pouco o comentário do @ emsr na resposta do @ unbind, se alguém não tiver a sorte de ter um compilador C ++ 11 (por exemplo, GCC 4.2.1) e quiser incorporar as novas linhas na string (ou char * ou string de classe), pode-se escrever algo como isto:
const char *text =
"This text is pretty long, but will be\n"
"concatenated into just a single string.\n"
"The disadvantage is that you have to quote\n"
"each part, and newlines must be literal as\n"
"usual.";
Muito óbvio, é verdade, mas o breve comentário do @ emsr não me chamou atenção quando li isso pela primeira vez, então tive que descobrir isso sozinho. Felizmente, salvei outra pessoa por alguns minutos.
// C++11.
std::string index_html=R"html(
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VIPSDK MONITOR</title>
<meta http-equiv="refresh" content="10">
</head>
<style type="text/css">
</style>
</html>
)html";
Opção 1. Usando a biblioteca de reforço, você pode declarar a sequência como abaixo
const boost::string_view helpText = "This is very long help text.\n"
"Also more text is here\n"
"And here\n"
// Pass help text here
setHelpText(helpText);
Opção 2. Se o boost não estiver disponível no seu projeto, você poderá usar std :: string_view () no C ++ moderno.