2011-01-24 19 views
11

Duplicar posible:
Should I use printf in my C++ code?printf vs std :: cout

Si sólo quiero imprimir una string en la pantalla, que puede hacer que el uso de estas dos maneras:

printf("abc"); 

std::cout << "abc" << std::endl; 

El caso es, y en los ejemplos que se muestran arriba, hay una ventaja de usar printf sobre std::cout, o, viceversa?

+6

Si está escribiendo código C++, en general, debería preferir las librerías y los géneros C++. –

+0

Depende del idioma en el que escribe su programa, ya sea C o C++. Estos dos métodos son de un lenguaje diferente, por lo que no se puede comparar directamente. –

+1

@Paul R. Gracias por su respuesta. Entonces, ¿no se considera "printf()" una expresión idiomática de C++? –

Respuesta

1

Esos dos ejemplos hacen cosas diferentes. Este último agregará un carácter de línea nueva y una salida de descarga (resultado de std::endl). std::cout también es más lento. Aparte de eso, printf y std::cout logran lo mismo y puede elegir lo que prefiera. Como cuestión de preferencia, usaría std::cout en código C++. Es más legible y más seguro.

Consulte this article si necesita formatear la salida usando std::cout.

+0

Gracias por su respuesta. ¿Por qué "std :: cout" como mencionas es más lento? ¿Qué se entiende por "más lento" aquí? En términos de qué, por ejemplo? Gracias. –

+0

@aali Es más lento por las razones que explican otras respuestas en detalle: hace más cosas. Depende mucho de tu compilador, pero he visto que las versiones anteriores de GCC son más de 10 veces más lentas en todos los casos. – marcog

+0

Con g ++ 4.x, en los casos de prueba que cometí, ostreams son tan rápidos como printfs, si 'sync_with_stdio (false)'. –

0

En general, debería preferir cout porque es mucho más seguro y más genérico. printf no es seguro para tipos, ni es genérico en absoluto. La única razón por la que puede preferir printf es la velocidad, desde la memoria, printf es mucho más rápido que cout.

+0

Gracias por su respuesta. Vi que "printf()" permite el formateo, ¿proporciona "cout" eso también? –

+0

¿Qué quiere decir cuando dice: "printf no es seguro para tipos, ni es genérico en absoluto. La única razón por la que podría preferir printf es la velocidad de memoria, printf es mucho más rápido que cout". ¿Puedes clarif sobre eso un poco? Gracias. –

+0

@aali: cout también proporciona formato de salida. –

26

Mientras cout es la forma correcta de C++, creo que algunas personas y empresas (incluyendo Google) continúan utilizando printf en código C++, ya que es mucho más fácil hacer una salida formateada con printf que con cout.

Aquí hay un ejemplo interesante que encontré here.

Compare:

printf("%-20s %-20s %5s\n" , "Name" , "Surname" , "Id"); 

y

cout << setw(-20) << "Name" << setw(20) << "Surname" << setw(5) << "Id" << endl; 
+3

+1, ha declarado una ventaja de printf, por lo que parece una respuesta válida para mí. – CashCow

+3

Un ejemplo que muestra que una línea de código más pequeña no siempre significa más legible. La versión 'std :: cout' explícitamente indica lo que está haciendo en cada paso del camino. 'printf' tiene una cadena de formateo críptica. –

+2

Eso es cierto, pero una vez que te acostumbras, podría argumentarse que printf es el más fácil de usar de los dos. Personalmente, siempre he encontrado que el formato de flujo es muy torpe. – dandan78

14

printf y sus amigos están asociados a funciones C. Funcionan en C++, pero no tienen el tipo de seguridad de C++ std::ostreams. Pueden surgir problemas en los programas que usan las funciones printf para formatear la salida según la entrada del usuario (o incluso la entrada de un archivo). Por ejemplo:

int main() 
{ 
    char[] a = {'1', '2', '3', '4'}; // a string that isn't 0-terminated 
    int i = 50; 
    printf("%s", a); // will continue printing characters until a 0 is found in memory 
    printf("%s", i); // will attempt to print a string, but this is actually an integer 
} 

C++ tiene la seguridad de tipos mucho más fuerte (y una clase std::string) para ayudar a prevenir problemas como estos.

+1

@Zac Howland. Gracias por su respuesta. ¿Por qué la cadena que declaras arriba no está terminada en 0? ¿Las cadenas no siempre terminan en 0? Y, ¿qué quieres decir con "tipo de seguridad"? Gracias. –

+0

No creo que esto sea muy relevante al imprimir un literal de cadena. – marcog

+3

@ aali Define una matriz de caracteres, que simplemente se pueden interpretar como cadenas en C, no agregará automáticamente un byte cero al final de una matriz. –

2

En realidad, para su ejemplo particular, debería haber preguntado cuál es preferible, poner o cout. printf imprime texto formateado pero solo está enviando texto sin formato a la consola.

Para uso general, las transmisiones (iostream, de las cuales cout es una parte) son más extensibles (puede imprimir sus propios tipos con ellas), y son más genéricas en cuanto a que puede generar funciones para imprimir en cualquier tipo de transmisión , no solo la consola (o la salida redirigida). Puede crear un comportamiento de flujo genérico con printf también usando fprintf, que toma un ARCHIVO * como un ARCHIVO * a menudo no es un archivo real, pero esto es más complicado.

Las transmisiones son "tipográficas" porque se sobrecarga con el tipo que está imprimiendo. printf no es seguro con su uso de puntos suspensivos por lo que podría obtener resultados indefinidos si coloca los tipos de parámetros incorrectos que no coinciden con la cadena de formato, pero el compilador no se quejará. Incluso puede obtener un comportamiento seg-fault/undefined (pero podría usar cout si se usa incorrectamente) si omite un parámetro o pasa uno malo (por ejemplo, un número para% s y lo trata como un puntero).

printf tiene algunas ventajas: puede plantilla una cadena de formato y luego reutilizar esa cadena de formato para datos diferentes, incluso si esos datos no están en una estructura, y usar manipulaciones de formateo para una variable no "pega" ese formato para su uso posterior porque especifica el formato para cada variable. printf también es conocido por ser threadsafe mientras que cout realmente no lo es.

boost ha combinado las ventajas de cada uno con su biblioteca boost :: format.

+0

+1 para mencionar boost :: formato – GrahamS

+0

+1 "_debe haber preguntado cuál es preferible,' puts' o 'cout'_". Estoy buscando en Google para encontrar quién llama quién internamente, puts() tiene una llamada 'cout' en él? – LoneXcoder

2

Lucho con esta misma pregunta yo mismo. printf es, en general, más fácil de usar para la impresión formateada, pero la función iostreams en C++ tiene la gran ventaja de que puede crear formateadores personalizados para objetos. Termino usando ambos en mi código según sea necesario.

El problema al usar ambos y mezclarlos es que los búferes de salida utilizados por printf y cout no son los mismos, así que, a menos que ejecute sin búfer o expulse explícitamente la salida, puede terminar con salida dañada.

Mi principal objeción a C++ es que no hay una función de formato de salida rápida similar a printf, por lo que no hay forma de controlar fácilmente la salida para el formato entero, hexadecimal y de coma flotante.

Java tenía este mismo problema; el lenguaje terminó obteniendo printf.

Wikipedia tiene una buena discusión sobre este tema en http://en.wikipedia.org/wiki/Printf#C.2B.2B_alternatives_to_sprintf_for_numeric_conversion.

2

El printf ha sido tomado prestado de C y tiene algunas limitaciones. La limitación mencionada más común de printf es seguridad de tipo, ya que depende del programador para que coincida correctamente con la cadena de formato con los argumentos. La segunda limitación que proviene nuevamente del entorno varargs es que no puede extender el comportamiento con los tipos definidos por el usuario. El printf sabe cómo imprimir un conjunto de tipos, y eso es todo lo que obtendrá de él. Aún así, por las pocas cosas para las que se puede usar, es más rápido y simple formatear cadenas con printf que con las secuencias C++.

Si bien la mayoría de los compiladores modernos son capaces de abordar el tipo de limitación de seguridad y al menos proporcionar advertencias (el compilador puede analizar el formato y verificar los argumentos proporcionados en la llamada), la segunda limitación no se puede superar. Incluso en el primer caso, hay cosas con las que el compilador no puede ayudar, como verificar la terminación nula, pero de nuevo, el mismo problema va con std::cout si lo usa para imprimir la misma matriz.

En el otro extremo, las corrientes (incluyendo std::cout) puede ser extendido para manejar tipos definidos por el usuario por medio de sobrecargado std::ostream& operator<<(std::ostream&, type const &) por cualquier usuario dado definido tipo type. Son seguros por sí mismos: si pasa un tipo que no tiene operator<< sobrecargado, el compilador se quejará. Son, por otro lado, más engorroso para producir salida formateada.

¿Qué debes usar? En general, prefiero usar transmisiones, ya que la sobrecarga de operator<< para mis propios tipos es simple y se pueden usar de manera uniforme con todos los tipos.

Cuestiones relacionadas