¿Hay alguna manera de tener texto plano de varias líneas, literales constantes en C ++, a la Perl? Tal vez algún truco de análisis con #include
un archivo? No puedo pensar en uno, pero chico, eso sería bueno. Sé que estará en C ++ 0x.
¿Hay alguna manera de tener texto plano de varias líneas, literales constantes en C ++, a la Perl? Tal vez algún truco de análisis con #include
un archivo? No puedo pensar en uno, pero chico, eso sería bueno. Sé que estará en C ++ 0x.
Respuestas:
Especie de. Lo más fácil es usar el hecho de que el compilador concatena literales de cadena adyacentes:
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.";
La sangría no importa, ya que no está dentro de las comillas.
También puede hacerlo, siempre y cuando tenga cuidado de escapar de la nueva línea incrustada. De lo contrario, como lo hizo mi primera respuesta, no se compilará:
const char * text2 = "Aquí, por otro lado, me he vuelto loco \ y realmente dejo que el literal abarque varias líneas, \ sin molestarse en citar cada línea contenido. Esto funciona, pero no puede sangrar ";
Nuevamente, tenga en cuenta esas barras invertidas al final de cada línea, deben estar inmediatamente antes de que la línea termine, están escapando de la nueva línea en la fuente, de modo que todo actúe como si la nueva línea no estuviera allí. No obtienes nuevas líneas en la cadena en los lugares donde tenías barras invertidas. Con este formulario, obviamente no puede sangrar el texto, ya que la sangría pasaría a formar parte de la cadena y la confinaría con espacios aleatorios.
En C ++ 11 tiene literales de cadena sin formato. Algo así como texto aquí en shells y lenguajes de script como Python y Perl y 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 los espacios y sangría y las nuevas líneas en la cadena se conservan.
También pueden ser utf-8 | 16 | 32 o wchar_t (con los prefijos habituales).
Debo señalar que la secuencia de escape, V0G0N, no es realmente necesaria aquí. Su presencia permitiría poner) "dentro de la cadena. En otras palabras, podría haber puesto
"(by Prostetnic Vogon Jeltz; see p. 56/57)"
(tenga en cuenta las comillas adicionales) y la cadena anterior aún sería correcta. De lo contrario, podría haber usado
const char * vogon_poem = R"( ... )";
Todavía se necesitan los parens dentro de las comillas.
#if 0
... #endif
para comentar bloques de código. Nidos también.
#define MULTILINE(...) #__VA_ARGS__
Consume todo entre paréntesis.
Reemplaza cualquier cantidad de caracteres de espacio en blanco consecutivos por un solo espacio.
\n
si necesita nuevas líneas
` (and hence
\ n ) is copied literally, but
"` se convierte en \"
. Por lo tanto, MULTILINE(1, "2" \3)
rinde "1, \"2\" \3"
.
Una forma probablemente conveniente de ingresar cadenas de varias líneas es mediante el uso de macros. Esto solo funciona si las comillas y paréntesis están equilibrados y no contiene comas de 'nivel 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 con gcc 4.6 o g ++ 4.6, esto produce: [[Using this trick(,) you don't need to use quotes. Though newlines and multiple white spaces will be replaced by a single whitespace.]]
Tenga en cuenta que ,
no puede estar en la cadena, a menos que esté entre paréntesis o comillas. Las comillas simples son posibles, pero crean advertencias del compilador.
Editar: como se menciona en los comentarios, #define MULTI_LINE_STRING(...) #__VA_ARGS__
permite el uso de ,
.
#define MULTILINE(...) #__VA_ARGS__
si desea que su cadena contenga comas.
\n
y \r
), lo que es útil para algunos casos y fatal para otros.
También puedes hacer esto:
const char *longString = R""""(
This is
a very
long
string
)"""";
char longString[] = R""""( This is a very long string )"""";
también funciona para mí.
Dado que una onza de experiencia vale un montón de teoría, probé un pequeño programa de prueba 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 este fragmento con cpp -P -std=c++11 filename
para reproducir.
El truco detrás #__VA_ARGS__
es que __VA_ARGS__
no procesa el separador de coma. Para que pueda pasarlo al operador de encadenamiento. Los espacios iniciales y finales se recortan, y los espacios (incluidas las nuevas líneas) entre palabras se comprimen en un solo espacio. Los paréntesis deben ser equilibrados. Creo que estas deficiencias explican por qué los diseñadores de C ++ 11, a pesar de eso #__VA_ARGS__
, vieron la necesidad de literales de cadena sin formato.
Solo para dilucidar un poco sobre el comentario de @emsr en la respuesta de @windind, si uno no tiene la suerte de tener un compilador de C ++ 11 (por ejemplo, GCC 4.2.1), y quiere insertar las nuevas líneas en la cadena (ya sea char * o cadena de clase), se puede escribir algo como esto:
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.";
Muy obvio, cierto, pero el breve comentario de @emsr no me llamó la atención cuando lo leí la primera vez, así que tuve que descubrirlo por mí mismo. Con suerte, he salvado a otra persona unos 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";
Opción 1. Usando la biblioteca de impulso, puede declarar la cadena de la siguiente manera
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);
Opción 2. Si boost no está disponible en su proyecto, puede usar std :: string_view () en C ++ moderno.