cpp-salida-consola-printf-print

Salida por consola en C++: de printf a std::print

  • 5 min

La salida por consola en C++ es la forma básica de mostrar información al usuario desde un programa, ya sea para enseñar resultados, depurar o simplemente comprobar que algo está funcionando.

Lo normal al empezar es usar std::cout, pero en C++ conviven varias formas de imprimir texto: printf, std::cout, std::format y std::print. Cada una tiene su sitio, sus ventajas y sus pequeñas trampas.

En este artículo vamos a ver al viejo conocido printf, el flujo clásico std::cout, y las alternativas modernas std::format y std::print.

Comparativa rápida

Característicaprintfstd::coutstd::formatstd::print
EstándarC / C++C++98C++20C++23
Seguridad de tiposBajaAltaAltaAlta
SintaxisCompactaVerbosaModernaModerna
Imprime directamenteNo
Uso típicoC, legacy, embebidosC++ clásicoFormatear cadenasConsola moderna

El clásico: printf

printf (print formatted) viene del lenguaje C y está disponible en C++ a través de la cabecera <cstdio>. A pesar de tener ya unos cuantos años encima, sigue siendo muy habitual en código legacy, sistemas embebidos y ejemplos rápidos.

Su funcionamiento se basa en una cadena de formato que contiene texto y huecos que empiezan por %. Después pasamos los valores que rellenan esos huecos.

#include <cstdio>

int main() {
    int edad = 35;
    double altura = 1.75;

    printf("Tengo %d años y mido %.2f metros\n", edad, altura);
}
Copied!

Fíjate en que queda bastante compacto. La pega es importante: printf no comprueba los tipos con la misma seguridad que las herramientas modernas de C++.

Especificadores habituales

Para usar printf, necesitamos conocer los especificadores de formato. Si nos equivocamos, el programa puede imprimir basura o comportarse de forma indefinida (y eso nunca es una tarde divertida).

EspecificadorTipo habitualEjemplo
%d o %iEntero con signo (int)10, -5
%uEntero sin signo (unsigned int)20
%fFlotante (float, double)3.14159
%cCarácter (char)'A'
%sCadena estilo C (const char*)"Hola"
%x / %XHexadecimalfa, FA
%pPunterodirección de memoria

Cuidado con std::string

printf no entiende objetos C++ como std::string. Espera cadenas de C, es decir, punteros const char*.

#include <cstdio>
#include <string>

int main() {
    std::string nombre = "Luis";

    // Incorrecto: printf espera const char*, no std::string
    // printf("Hola %s\n", nombre);

    // Correcto
    printf("Hola %s\n", nombre.c_str());
}
Copied!

Si usas printf con tipos de C++, convierte explícitamente a tipos que C pueda entender. Con std::string, eso significa usar .c_str().

std::cout

std::cout vive en <iostream> y es la forma clásica de C++ para escribir por consola. Usa el operador <<, igual que vimos en los primeros ejemplos del curso.

#include <iostream>
#include <string>

int main() {
    std::string nombre = "Luis";
    int edad = 35;

    std::cout << "Hola " << nombre << ", tienes " << edad << " años.\n";
}
Copied!

La ventaja de std::cout es que trabaja bien con tipos de C++ y evita muchos errores típicos de printf. La desventaja es que, cuando hay mucho formato, puede quedarse bastante verboso.

std::format

C++20 introdujo std::format, que permite crear cadenas formateadas usando {} como marcadores. Se parece mucho al estilo de Python o de otras librerías modernas de formato.

#include <format>
#include <iostream>
#include <string>

int main() {
    std::string nombre = "Luis";
    int edad = 35;

    std::string texto = std::format("Hola {}, tienes {} años.", nombre, edad);
    std::cout << texto << "\n";
}
Copied!

std::format no imprime directamente. Devuelve un std::string, que luego puedes guardar, enviar a un log, escribir en un archivo o mostrar por consola.

std::print y std::println

C++23 añade std::print y std::println, que son la versión directa para imprimir usando el mismo sistema de formato.

#include <print>
#include <string>

int main() {
    std::string nombre = "Luis";
    int edad = 35;

    std::println("Hola {}, tienes {} años.", nombre, edad);
}
Copied!

La diferencia es sencilla:

  • std::print no añade salto de línea.
  • std::println añade un salto de línea al final.

std::print pertenece a C++23, así que su disponibilidad depende del compilador y de la librería estándar que uses. Si tu entorno todavía no lo soporta, std::format + std::cout es una alternativa razonable.

Formato avanzado

Dentro de las llaves podemos añadir especificadores de formato. Por ejemplo, para decimales o hexadecimal:

double pi = 3.14159265;
int color = 255;

std::println("Pi vale {:.2f} y el color es {:X}", pi, color);
Copied!

En este ejemplo, {:.2f} muestra dos decimales y {:X} muestra el entero en hexadecimal con letras mayúsculas.