Pregunta

En el nuevo código de C++, tiendo a utilizar el C++ biblioteca iostream en lugar de la C stdio biblioteca.

Me he dado cuenta de algunos programadores parecen de palo stdio, insistiendo en que es más portátil.

Es este realmente el caso?¿Qué es mejor utilizar?

¿Fue útil?

Solución

Para responder a la pregunta original:
Cualquier cosa que se puede hacer uso de stdio se puede hacer uso de la biblioteca iostream.

Disadvantages of iostreams: verbose
Advantages    of iostreams: easy to extend for new non POD types.

El paso adelante del C++ hecho más de C era el tipo de seguridad.

  • iostreams fue diseñado para ser explícitamente el tipo de seguro.Por lo tanto la asignación a un objeto comprueba explícitamente el tipo (en el compilador de tiempo) del objeto al que se le asigna también la generación de un error de tiempo de compilación si se requiere).Por lo tanto prevenir la memoria en tiempo de ejecución la sobreproducción o la escritura de un valor de tipo float a un objeto char, etc.

  • scanf()/printf() y de la familia en el otro lado se basan en el programador de obtener la cadena de formato correcto y no había ningún tipo de comprobación (creo gcc tiene una extensión que ayuda).Como resultado de ello, fue la fuente de muchos errores (como los programadores son menos perfectas en su análisis de los compiladores [no voy a decir compiladores son perfectos mejor que los seres humanos]).

Sólo para aclarar los comentarios de Colin Jensen.

  • El iostream las bibliotecas se han mantenido estables desde el lanzamiento de la última estándar (no recuerdo el año, pero hace unos 10 años).

Para aclarar los comentarios por Mikael Jansson.

  • Los otros idiomas que él menciona que usan el formato de estilo explícitos, medidas de protección para evitar los peligrosos efectos secundarios de la C stdio biblioteca que puede (en C, pero no las lenguas mencionadas) causa un tiempo de ejecución de accidente.

N. B. Estoy de acuerdo en que la biblioteca iostream es un poco en el detallado lado.Pero estoy dispuesto a poner con el verboseness para garantizar el tiempo de ejecución de la seguridad.Pero podemos mitigar el nivel de detalle mediante el uso de Impulso De Las Bibliotecas En Formato.

#include <iostream>
#include <iomanip>
#include <boost/format.hpp>

struct X
{  // this structure reverse engineered from
   // example provided by 'Mikael Jansson' in order to make this a running example

    char*       name;
    double      mean;
    int         sample_count;
};
int main()
{
    X   stats[] = {{"Plop",5.6,2}};

    // nonsense output, just to exemplify

    // stdio version
    fprintf(stderr, "at %p/%s: mean value %.3f of %4d samples\n",
            stats, stats->name, stats->mean, stats->sample_count);

    // iostream
    std::cerr << "at " << (void*)stats << "/" << stats->name
              << ": mean value " << std::fixed << std::setprecision(3) << stats->mean
              << " of " << std::setw(4) << std::setfill(' ') << stats->sample_count
              << " samples\n";

    // iostream with boost::format
    std::cerr << boost::format("at %p/%s: mean value %.3f of %4d samples\n")
                % stats % stats->name % stats->mean % stats->sample_count;
}

Otros consejos

Es demasiado detallado.

Reflexionar sobre la iostream construir de la siguiente forma (de manera similar para scanf):

// nonsense output, just to examplify
fprintf(stderr, "at %p/%s: mean value %.3f of %4d samples\n",
    stats, stats->name, stats->mean, stats->sample_count);

Que requiere algo como:

std::cerr << "at " << static_cast<void*>(stats) << "/" << stats->name
          << ": mean value " << std::precision(3) << stats->mean
          << " of " << std::width(4) << std::fill(' ') << stats->sample_count
          << " samples " << std::endl;

El formato de cadena es un caso donde el objeto-orientedness puede y debe ser puesta a un lado en favor de un formato de DSL incrustado en las cadenas.Considere la posibilidad de Lisp del format, Python printf-formato de estilo, o PHP, Bash, Perl, Ruby y su cadena de intrapolation.

iostream para que el caso de uso es equivocada, en el mejor.

El Impulso De Las Bibliotecas En Formato proporciona un tipo de seguro, orientado a objetos alternativa para printf estilo de formato de cadena y es un complemento para los iostreams que no sufren de la habitual verborrea problemas por el uso inteligente de operador%.Recomiendo teniendo en cuenta sobre el uso de un simple C printf si no te gusta el formato con iostream del operador<<.

De vuelta en los viejos días, los Estándares de C++ comité mantuvo limpiando con la lengua y iostreams era un objetivo en movimiento.Si usted utiliza iostreams, que luego tuvieron la oportunidad de reescribir partes de su código de cada año o así.Debido a esto, siempre he utilizado stdio que no ha cambiado significativamente desde el año 1989.

Si yo estuviera haciendo las cosas hoy en día, me gustaría utilizar iostreams.

Si, como yo, has aprendido C antes de aprender C++, el stdio las bibliotecas parecen más natural utilizar.Hay pros y contras para iostream vsstdio pero sí echo de menos printf() cuando se usa iostream.

En principio me gustaría utilizar iostreams, en la práctica no hacer demasiado formato de decimales, etc que hacen que iostreams demasiado ilegible, por lo que utilizar stdio.Boost::formato es una mejora, pero no es motivación suficiente para mí.En la práctica, stdio es casi typesafe ya que la mayoría de los compiladores modernos, hacer la comprobación de argumentos de todas formas.

Es un área donde todavía no estoy totalmente satisfecho con alguna de las soluciones.

Para los binarios de IO, que tienden a usar stdio del fread y fwrite.Para el formato de cosas que, por lo general, el uso de IO Corriente a pesar de que como dijo Mikael, no trivial (no por defecto?) el formato puede ser un pan de PITA.

Voy a ser la comparación de los dos integrar las bibliotecas de C++ estándar de la biblioteca.

Usted no debe usar C-estilo-formato de cadena de la cadena de procesamiento-rutinas en C++.

Existen varias razones para mit su uso:

  • No typesafe
  • No se puede pasar no POD tipos de variadic las listas de argumentos (es decir, ni a scanf+co., ni printf+co.), o entrar en la Oscura Fortaleza de un Comportamiento Indefinido
  • Fácil equivocarse:
    • Usted debe mantener la cadena de formato y el "valor-argumento-lista" en la sincronización
    • Usted debe mantener en sincronización correctamente

Pequeños errores introducidos en lugares remotos

No es sólo el printf en sí mismo que no es bueno.El Software se vuelve viejo y es refactorizado y modificados, y los errores pueden ser introducidos desde lugares remotos.Supongamos que usted tiene

.

// foo.h
...
float foo;
...

y en algún lugar ...

// bar/frob/42/icetea.cpp
...
scanf ("%f", &foo);
...

Y tres años más tarde descubre que foo debe ser de algún tipo personalizado ...

// foo.h
...
FixedPoint foo;
...

pero en algún lugar ...

// bar/frob/42/icetea.cpp
...
scanf ("%f", &foo);
...

...entonces su viejo printf/scanf todavía compilar, excepto que ahora obtiene al azar segfaults y no recuerdo por qué.

Verbosidad de iostreams

Si usted piensa que printf() es menos detallado, entonces hay una cierta probabilidad de que usted no usa su iostream completa de la fuerza.Ejemplo:

  printf ("My Matrix: %f %f %f %f\n"
          "           %f %f %f %f\n"
          "           %f %f %f %f\n"
          "           %f %f %f %f\n",
          mat(0,0), mat(0,1), mat(0,2), mat(0,3), 
          mat(1,0), mat(1,1), mat(1,2), mat(1,3), 
          mat(2,0), mat(2,1), mat(2,2), mat(2,3), 
          mat(3,0), mat(3,1), mat(3,2), mat(3,3));

Compare esto con el uso de iostreams derecho:

cout << mat << '\n';

Usted tiene que definir una adecuada sobrecarga de operador<< que tiene más o menos la estructura de las printf-cosita, pero la diferencia significativa es que ahora tiene algo re-utilizable y typesafe;por supuesto, usted también puede hacer algo de re-utilizable para printf le gusta, pero luego se han printf nuevo (lo que si se reemplaza la matriz de los miembros con el nuevo FixedPoint?), aparte de otros no nimiedades, por ejemplo,debe pasar el ARCHIVO* maneja alrededor.

C-el estilo de las cadenas de formato no son mejores para la I18N de iostreams

Tenga en cuenta que el formato de cadenas son a menudo el pensamiento de ser el rescate de la internacionalización, pero que no son en absoluto mejor que iostream a ese respecto:

printf ("Guten Morgen, Sie sind %f Meter groß und haben %d Kinder", 
        someFloat, someInt);

printf ("Good morning, you have %d children and your height is %f meters",
        someFloat, someInt); // Note: Position changed.

// ^^ not the best example, but different languages have generally different
//    order of "variables"

I. e., el antiguo estilo de C cadenas de formato de la falta de información de posición tanto como iostreams hacer.

Usted puede ser que desee considerar boost::formato de, que ofrece apoyo para que indique la posición en la cadena de formato de forma explícita.Desde su sección de ejemplos:

cout << format("%1% %2% %3% %2% %1% \n") % "11" % "22" % "333"; // 'simple' style.

Algunos printf-implementaciones de proporcionar argumentos posicionales, pero que no son estándar.

Debo nunca el uso de C-estilo de las cadenas de formato?

Aparte de desempeño (como señala Jan Hudec), no veo una razón.Pero hay que tener en mente:

"Debemos olvidar los pequeños de la eficiencia, dicen que cerca del 97% del tiempo:prematuro de la optimización es la raíz de todos los males.Sin embargo, no debemos dejar pasar las oportunidades que la crítica del 3%.Un buen programador no se deje llevar por la complacencia por este tipo de razonamiento, que se sabia que mirar con cuidado las críticas del código;pero sólo después de que el código ha sido identificado" - Knuth

y

"Los cuellos de botella se producen en lugares sorprendentes, así que no trate de cuestionar y poner en un hack de velocidad hasta que haya comprobado que es donde está el cuello de botella es." - Lucio

Sí, printf-implementaciones son generalmente más rápido que iostreams son generalmente más rápido que el boost::format (a partir de un pequeño y específico de referencia escribí, pero se debe en gran medida dependen de la situación en particular:si printf=100%, entonces iostream=160%, y boost::format=220%)

Pero no ciegamente omitir pensando:¿Cuánto tiempo realmente gastar en procesamiento de texto?¿Cuánto tiempo su programa se ejecuta antes de salir?Es relevante en absoluto para volver a caer a C-estilo de las cadenas de formato, suelto, tipo de seguridad, disminución refactorbility, aumentar la probabilidad de muy sutiles errores que pueden ocultar por años y puede que sólo se revelan a la derecha en su lista de favoritos de los clientes de la cara?

Personalmente, no me caen de nuevo si no puedo ganar más de un 20% speedup.Pero debido a mis aplicaciones pasar prácticamente todo su tiempo en otras tareas de la cadena de procesamiento, nunca he tenido que.Algunos de los analizadores Escribí pasar prácticamente todo su tiempo en la cadena de procesamiento, pero el total de su tiempo de ejecución es tan pequeño que no vale la pena el de prueba y de verificación de esfuerzo.

Algunos de los acertijos

Por último, me gustaría predefinido algunos enigmas:

Encontrar todos los errores, porque el compilador no (sólo él puede sugerir si es simpático):

shared_ptr<float> f(new float);
fscanf (stdout, "%u %s %f", f)

Si nada más, ¿qué hay de malo con esto?

const char *output = "in total, the thing is 50%"
                     "feature  complete";
printf (output);

Mientras que hay un montón de beneficios para el C++ iostreams API, un importante problema que se tiene es de alrededor de i18n.El problema es que el orden de parámetro sustituciones pueden variar dependiendo de la cultura.El ejemplo clásico es algo así como:

// i18n UNSAFE 
std::cout << "Dear " << name.given << ' ' << name.family << std::endl;

Mientras que trabaja para el inglés, en Chino el nombre de la familia que sea que ocurra primero.

Cuando se trata de traducir el código para los mercados extranjeros, la traducción de los fragmentos está llena de peligros por lo que los nuevos l10ns puede requerir cambios en el código y no sólo diferentes cadenas.

boost::formato en el que parece combinar lo mejor de stdio (una sola cadena de formato que puede utilizar los parámetros en un orden diferente, a continuación, aparecen) y iostreams (tipo de seguridad, la extensibilidad).

Yo uso iostreams, principalmente debido a que hace que sea más fácil jugar con la corriente más adelante (si la necesito).Por ejemplo, usted podría encontrar que usted desea mostrar el resultado en algunos ventana de seguimiento -- esto es relativamente fácil de hacer con cout y cerr.Usted puede, por supuesto, jugar con los tubos y cosas en unix, pero que no es tan portátil.

Me encanta printf-al igual que el formato, así que por lo general el formato de una cadena en primer lugar, y a continuación, enviar el buffer.Con Qt, yo uso a menudo QString::sprintf (aunque ellos recomiendan usar QString::arg en su lugar).He mirado en boost.formato así, pero realmente no podía acostumbrarse a la sintaxis (demasiados %'s).Realmente debería darle un vistazo, aunque.

Lo que echo de menos acerca de la iolibraries es el formato de entrada.

iostreams no tienen una buena forma para replicar scanf() e incluso aumentar no tiene la extensión requerida para la entrada.

stdio es mejor para la lectura de archivos binarios (como freading bloques en un vector<unsigned char=""> y el uso .resize (), etc.).Ver el read_rest función en el archivo.hh en http://nuwen.net/libnuwen.html para un ejemplo.

C++ corrientes se pueden ahogar en un montón de bytes cuando la lectura de los archivos binarios de causar una falsa ef.

Desde iostreams se han convertido en un estándar debe usar de ellos sabiendo que el código de trabajo para asegurarse de que con las nuevas versiones de compilador.Supongo que hoy en día la mayoría de los compiladores saben muy bien acerca de los iostreams y no debería haber ningún problema con ellos.

Pero si quieres seguir con *printf funciones no se puede no hay problema, en mi opinión.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top