¿Por qué se eligió el signo de porcentaje (%) como el especificador de formato para la familia de funciones printf?

27

Todo el mundo sabe que, al menos en C, utiliza la printffamilia de funciones para imprimir una cadena formateada. Y estas funciones usan un signo de porcentaje ( %) para indicar el comienzo de un especificador de formato. Por ejemplo, %dsignifica imprimir un inty %usignifica imprimir un unsigned int. Si no está familiarizado con el printffuncionamiento de los marcadores de posición de función y formato, o simplemente necesita un repaso, el artículo de Wikipedia es un buen lugar para comenzar.

Mi pregunta es, ¿hay alguna razón particularmente convincente por la cual esto fue originalmente o debería elegirse en el futuro como el especificador de formato?

Obviamente, la decisión se tomó hace mucho tiempo (muy probablemente para un predecesor incluso del lenguaje C), y desde entonces ha sido más o menos "estándar" (no solo en C, sino también en una amplia gama de otros lenguajes que han adoptado su sintaxis en diversos grados), por lo que es demasiado tarde para cambiar. Pero todavía tengo curiosidad por saber si alguien tiene alguna idea de por qué esta elección podría haberse hecho en primer lugar, y si todavía tiene sentido como la elección si uno está diseñando un nuevo lenguaje con una funcionalidad similar.

Por ejemplo, con C # (y la otra familia de lenguajes .NET), Microsoft tomó una decisión ligeramente diferente con respecto al funcionamiento de las funciones de formato de cadena. Aunque se puede aplicar cierto grado de seguridad de tipo allí (a diferencia de la implementación de printfen C), y por lo tanto no es necesario incluir una indicación del tipo del parámetro correspondiente, decidieron usar pares de llaves rizadas indexadas a cero ( {}) como especificadores de formato, así:

string output = String.Format("In {0}, the temperature is {1} degrees Celsius.",
                              "Texas", 37);
Console.WriteLine(output);

// Output:
//     In Texas, the temperature is 37 degrees Celsius.

La documentación del String.Formatmétodo contiene más información, al igual que este artículo sobre el formato compuesto en general , pero los detalles exactos no son importantes. El punto es simplemente que abandonaron la práctica de usar desde hace mucho tiempo %para indicar el comienzo de un especificador de formato. El lenguaje C simplemente podría haber usado fácilmente {d}y {u}, pero no fue así. ¿Alguien tiene alguna idea sobre por qué, si esta decisión tiene sentido en retrospectiva, y si las nuevas implementaciones deberían seguirla?

Obviamente, no se puede elegir un personaje que no tenga que ser evitable para que pueda incluirse en la cadena en sí, pero ese problema ya está bastante bien resuelto con solo usar dos de ellos. ¿Qué otras consideraciones son relevantes?

Cody Gray
fuente
55
El problema de escape no se resuelve mediante el uso de dos caracteres. Simplemente significa que tienes un personaje más para escapar.
JJJ
2
Tengo curiosidad Ciertamente, sería posible usar en {u}lugar de, %upero ¿tendría alguna ventaja significativa? Parece una elección en gran medida arbitraria.
CB Bailey
12
@JarrodRoberson, ¿está diciendo que eligieron deliberadamente la {}sintaxis para que las personas que aprenden C # no comiencen a aprender nada más? Me resulta muy difícil creer que fue una parte importante, o incluso alguna, de su decisión de diseño. ¿Puedes respaldar tu declaración de alguna manera?
stijn
66
Curiosamente, Python abandonó el %formato (una forma muy superior) en favor de algo similar al {}formato de .NET porque este último ofrece más flexibilidad.
Konrad Rudolph el
3
¿Por qué el cielo es azul y por qué la palabra "azul" se llama azul? Tenían que escoger algo.

Respuestas:

12

Como señala @Secure, la printffunción de C está inspirada en la writeffunción de BCPL . Y si nos fijamos en la página de Wikipedia para BCPL , tiene un ejemplo que muestra que BCPL writeftambién solía %introducir un especificador de formato.

Entonces podemos inferir que C se usó %porque BCPL lo hizo, o por las mismas razones que BCPL lo hizo. Mi intuición es que era simplemente %uno de los caracteres ASCII menos utilizados ... o eso pensaban los autores. También es probable que no hayan pasado mucho tiempo sopesando las diversas alternativas. En ese momento, tanto BCPL como C eran lenguajes oscuros, y los autores probablemente tenían cosas más importantes con las que lidiar.

Sin embargo, hay una llave menor en las obras. Si bien C se inspiró en BCPL, no está del todo claro si C tomó prestadas bibliotecas de E / S BCPL o al revés. Recuerdo vagamente que las bibliotecas de E / S de BCPL pasaron por un proceso de evolución en el momento en que el operador de indexación de bytes de infijo se agregó al lenguaje. (En realidad, creo que sé quién sabría sobre eso).

Stephen C
fuente
3
"En realidad, creo que sé quién sabría sobre eso" ... y? ... y? .. No nos dejes con un colgador de acantilado ...
Mawg
2
@Mawg - Brian Knight probablemente lo haría. Ian Wilson probablemente lo haría. Martin Richards definitivamente lo haría. HTH
Stephen C
6

La entrada de Wikipedia no contiene mucha información histórica, no específica para printf, pero para escapar de los personajes en general.

http://en.wikipedia.org/wiki/Escape_character

La referencia temprana al término "personaje de escape" se encuentra en las publicaciones técnicas de IBM de Bob Bemer. Aparentemente, fue él quien inventó este mecanismo, durante su trabajo en el conjunto de caracteres ASCII.

Mi suposición es: la barra invertida ya se usaba para los literales de cadena y se necesitaba otro carácter para las cadenas de formato. Lo más probable es que eligieron el personaje con la menor frecuencia de uso y ocurrencia normal.

Por cierto, otro artículo relacionado está vinculado allí con un término que nunca antes había escuchado:

http://en.wikipedia.org/wiki/Leaning_toothpick_syndrome

El artículo printftiene algunos fragmentos de información más, pero no sobre las razones.

http://en.wikipedia.org/wiki/Printf

Printf variadic de C tiene su origen en la función writef de BCPL.

Seguro
fuente