visual studio microsoft español descargar community c++ c++11 portability

studio - C++: ¿Existe una definición estándar para el final de línea en una constante de cadena de varias líneas?



visual studio installer (3)

Si tengo una cadena de varias líneas C ++ 11 constante de cadena como

R"""line 1 line 2 line3"""

¿Se define en qué carácter (s) está compuesto el terminador / separador de línea?


El estándar parece indicar que:

R"""line 1 line 2 line3"""

es equivalente a:

"line 1/nline 2/nline3"

Desde 2.14.5 literales de cadena del estándar C ++ 11:

4 [ Nota: una nueva línea de archivo fuente en un literal de cadena sin formato da como resultado una nueva línea en el literal de la cadena de ejecución resultante. Suponiendo que no hay espacios en blanco al comienzo de las líneas en el siguiente ejemplo, la afirmación tendrá éxito:

const char *p = R"(a/ b c)"; assert(std::strcmp(p, "a///nb/nc") == 0);

- nota final ]

5 [ Ejemplo: la cadena sin procesar

R"a( )/ a" )a"

es equivalente a "/n)///na/"/n" .


La intención es que una nueva línea en un literal de cadena sin formato se corresponda con un único carácter ''/n'' . Esta intención no se expresa tan claramente como debería ser, lo que ha llevado a cierta confusión.

Las citas son para el estándar ISO C ++ 2011.

Primero, aquí está la evidencia de que se asigna a un solo carácter ''/n'' .

Una nota en la sección 2.14.5 [lex.string] del párrafo 4 dice:

[ Nota: Una nueva línea de archivo fuente en un literal de cadena sin formato da como resultado una nueva línea en la cadena de ejecución resultante -literal . Suponiendo que no hay espacios en blanco al comienzo de las líneas en el siguiente ejemplo, la afirmación tendrá éxito:

const char *p = R"(a/ b c)"; assert(std::strcmp(p, "a///nb/nc") == 0);

- nota final ]

Esto indica claramente que una nueva línea está asignada a un único carácter ''/n'' . También coincide con el comportamiento observado de g ++ 6.2.0 y clang ++ 3.8.1 (pruebas realizadas en un sistema Linux que utiliza archivos de origen con terminaciones de estilo estilo Unix y Windows).

Dado el propósito claramente establecido en la nota y el comportamiento de dos compiladores populares, diría que es seguro confiar en esto, aunque sería interesante ver cómo otros compiladores realmente manejan esto.

Sin embargo, una lectura literal de la redacción normativa de la norma podría conducir fácilmente a una conclusión diferente, o al menos a cierta incertidumbre.

La Sección 2.5 [lex.pptoken] dice el párrafo 3 (énfasis agregado):

Entre los caracteres de comillas dobles inicial y final de la cadena sin formato, se revierten todas las transformaciones realizadas en las fases 1 y 2 (trigrafos, nombres de caracteres universales y empalme de líneas) ; esta reversión se aplicará antes de que se identifique cualquier d-char , r-char o delimitación entre paréntesis.

Las fases de la traducción se especifican en 2.2 [lex.phases]. En la fase 1:

Los caracteres del archivo de origen físico se asignan, de una manera definida por la implementación, al conjunto de caracteres de origen básico (introduciendo caracteres de nueva línea para los indicadores de fin de línea) si es necesario.

Si asumimos que el mapeo de los caracteres del archivo de origen físico al conjunto de caracteres básicos y la introducción de caracteres de nueva línea son " transformaciones ", podríamos concluir razonablemente que, por ejemplo, una nueva línea en el medio de un literal de cadena sin procesar en un El archivo fuente en formato Windows debe ser equivalente a una secuencia /r/n . (Puedo imaginar que sea útil para el código específico de Windows).

(Esta interpretación genera problemas con los sistemas en los que el indicador de fin de línea no es una secuencia de caracteres, por ejemplo, donde cada línea tiene un registro de ancho fijo. Esos sistemas son raros actualmente).

Como señala "Cheers and hth. - la respuesta de Alf" , hay un informe de defectos abierto para este tema. Fue presentado en 2013 y aún no se ha resuelto.

Personalmente, creo que la raíz de la confusión es la palabra "cualquiera" (énfasis agregado como antes):

Entre los caracteres de comillas dobles inicial y final de la cadena sin formato, se revierten todas las transformaciones realizadas en las fases 1 y 2 (trigrafos, nombres de caracteres universales y empalme de líneas) ; esta reversión se aplicará antes de que se identifique cualquier d-char , r-char o delimitación entre paréntesis.

Seguramente, el mapeo de los caracteres del archivo de origen físico al conjunto básico de caracteres fuente puede considerarse razonablemente como una transformación . La cláusula entre paréntesis "(trigraphs, universal-character-names, y splicing de línea)" parece estar destinada a especificar qué transformaciones se deben revertir, pero eso intenta cambiar el significado de la palabra "transformations" (que el estándar hace no formalmente definido) o contradice el uso de la palabra "cualquiera".

Sugiero que cambiar la palabra "cualquiera" por "cierto" expresaría la intención aparente mucho más claramente:

Entre los caracteres de comillas dobles iniciales y finales de la cadena sin formato, se revierten ciertas transformaciones realizadas en las fases 1 y 2 (trigrafos, nombres de caracteres universales y empalme de líneas); esta reversión se aplicará antes de que se identifique cualquier d-char , r-char o delimitación entre paréntesis.

Esta redacción aclararía mucho más que "trigraphs, universal-character-names, y splicing de línea" son las únicas transformaciones que se deben revertir. (No todo lo hecho en las fases de traducción 1 y 2 se revierte, solo esas transformaciones específicas enumeradas).


Nota: la pregunta ha cambiado sustancialmente desde que se publicaron las respuestas. Solo queda la mitad, es decir, el aspecto C ++ puro. El enfoque de red en esta respuesta responde a la pregunta original "enviar una cadena de varias líneas a un servidor con requisitos de fin de línea bien definidos". No persigo la evolución de la pregunta en general.

Internamente en el programa, el estándar C ++ para newline es /n . Esto se usa también para nueva línea en un literal en bruto. No hay una convención especial para los literales en bruto.

Por lo general, /n asigna al salto de línea ASCII, que es el valor 10.

No estoy seguro de qué se asigna en EBCDIC, pero puede verificarlo si es necesario.

En el cable, sin embargo, tengo la impresión de que la mayoría de los protocolos utilizan retorno de carro ASCII más avance de línea, es decir, 13 seguido de 10. Esto a veces se llama CRLF , después de las abreviaturas ASCII CR para retorno de carro y LF para avance de línea. Cuando los escapes de C ++ se asignan a ASCII, esto simplemente es /r/n en C ++.

Debe cumplir con los requisitos del protocolo que está utilizando.

Para archivo / secuencia ordinaria, la biblioteca estándar de C ++ se encarga de correlacionar el interno /n con cualquier convención que utilice el entorno host. Esto se llama modo de texto , a diferencia del modo binario donde no se realiza la asignación.

Para la red i / o, que no está cubierta por la biblioteca estándar, el código de la aplicación debe hacerlo solo, ya sea directamente o a través de algunas funciones de la biblioteca.

Existe un problema activo acerca de este, el informe de defectos del lenguaje central # 1655 "Terminaciones de línea en literales sin procesar", enviado por Mike Miller el 24-04-2013, donde pregunta:

" ¿Se pretende que, por ejemplo, un CRLF en el origen de un literal de cadena sin formato se represente como un carácter de nueva línea o como los caracteres originales?

Dado que los valores de terminación de línea difieren según la codificación del archivo original, y considerando que en algunos sistemas de archivos no hay una codificación de terminaciones de línea, sino líneas como registros, está claro que la intención no es representar el contenido del archivo como ... es - ya que eso es imposible de hacer en todos los casos. Pero, por lo que puedo ver, este DR aún no se ha resuelto.