Entrada de Datos. Lenguaje C++
SOLUCIONARIO
Entrada de Datos. Lenguaje C++
2026-04-05
Por
Occam's Razor

#include <vector>
#include <iostream>
#include <algorithm>

int 
main()
{
    int n, t;
    std::cout << "Introduce dos numeros separados por espacios ? ";
    std::cin >> n >> t;

    std::cout << "Has introducido " << n << " y " << t << std::endl;
    std::vector<int> a(10);
    
    std::cout << "Introduce 10 numeros separados por espacios ? ";
    for (auto& v : a) std::cin >> v;

    for (auto iter = a.begin(); iter != a.end(); iter++) 
      std::cout << *iter << " ";
    std::cout << std::endl;

    return 0;
}

En la versión C++ hemos utilizado el equivalente a scanf y pritnf, que para C++ es cout y cin. cin y cout son realmente dos objetos de las clase llamada istream y ostream respectivamente. Estas clases sobrecargan el operador << y >> para leer y escribir datos en la consola. Personalmente, la sobrecarga de este operador me resulta extraña… pero así ha sido desde los principios de C++. Estos operadores se encargan de convertir los datos automáticamente, a partir de los tipos de las variables que intercalamos entre ellos.

¿SABÍAS QUÉ?

Aunque no lo hayamos visto aún, C++, al igual que muchos lenguajes orientados a objetos, nos permite sobrecargar operadores, esto es, proporcionar nuestro propio código para que operadores estándar operen de forma distinta. Así es como (junto con el polimorfismo) estos lenguajes consiguen que cuando “sumamos” dos cadenas de caracteres las concatenemos o hagamos cualquier otra cosa que nos apetezca. Esto es bastante común en C++ y aunque hace que el código sea en generar más “legible”, en ocasiones puede resultar muy confuso o requerir un conocimiento profundo del código que estás utilizando.

 

Si bien, podríamos haber escrito el programa utilizando un array estándar como el de la versión C, hemos vuelto a utilizar un objeto, un vector en este caso, y de esta forma ilustrar el uso de los iteradores. De lo contrario el código C y C++ serían prácticamente idénticos.

SOY NOVATO

La línea std:vector<int> a(10) hace uso de un template o plantilla para generar un vector de enteros. El <int> es el parámetro del template. Estos templates se instancian en tiempo de compilación, momento en el cual, el compiladore generará una nueva clase de vectores de valores enteros (llamémosla iVector aunque os aseguro que el nombre real es bastante más raro) y la línea anterior pasaría a ser algo así como iVector a(10).

También observad que el número de elementos se pasa entre paréntesis y no corchetes. Aquí no estamos declarando un array, sino que estamos llamando a la función de la clase llamada constructor que inicializa el objeto. En este caso, reservando memoria para 10 enteros, entre otras cosas.

 

La librería estándar C++ ofrece una amplia y potente variedad de clases para definir y manejar estructuras de datos. Las estructuras complejas como vectores en este caso, suelen ofrece iteradores. Los iteradores son objetos que nos permiten recorrer los elementos de la estructura de datos sin necesidad de conocer los detalles de su estructura interna. Como podemos ver, el iterador nos ofrece funciones para obtener el primer y último elemento, además de sobrecargar el operador ++ para permitirnos movernos por la estructura de datos y el oeprador * para acceder a los datos.

De esta forma, nuestro programa principal no necesita saber si el vector está almacenado en un array, en un bloque de memoria consecutivo, o en una lista enlazada.

¿SABÍAS QUÉ?

Las clases iterador nos ofrecen muchos más métodos para navegar las estructuras de datos (prev, next, advance,…). Existen distintos tipos de iteradores que ofrecen distintas posibilidades, en general, sobrecargando distintos operadores.

 

Este programa utiliza la forma foreach de for y por tanto necesitamos compilar el programa para C++11 o superior, lo que podemos hacer de la siguiente forma:

g++ -std=c++11 -o input input.cpp

El objeto cin nos ofrece cierta funcionalidad para detectar errores en la entrada. Veamos este fragmento de código:

std::cout << "Introduce un Numero: "
std::cin >> n

if (std::cin.fail()) {
   std::cin.clear(); // Limpia el indicador de error
   std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
   std::cout << "Por favor introduzca un número";
}

La llamada std::cin.fail() devuelve el valor verdadero si la operación de entrada ha fallado, lo cual puede ocurrir porque hemos introducido una cadena de caracteres, o usado un formato no soportado. Esto activa el flag de error que indica que se ha producido un error durante la lectura.

En ese punto los caracteres leídos del usuario todavía se encuentra en el buffer de lectura, lo que significa que si volvemos a intentar leer un número, cin >> fallará de nuevo. std::cin.ignore nos permite eliminar los datos problemáticos del buffer de entrada.

std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');

Esta línea ignora hasta un máximo de std::numeric_limits<std::streamsize>::max() que viene a ser algo así como el tamaño máximo de datos leídos o hasta que se encuentre el fin de línea. O en otras palabras, descarta el resto de la línea. Si no hacemos esto, la próxima lectura de datos volverá a encontrarse con los datos que provocaron el error inicial y nuestro programa entraría en un bucle infinito intentando parsear una y otra vez la misma cadena.

Además es necesario borrar el indicador de error para que la próxima línea se pueda leer normalmente usando std::cin:clear().

SUMARIO

  • Podemos leer datos en nuestros programas usando el objeto cin y el operador >>
  • Al igual que en C, si quieres más control sobre la validez de los datos es mejor escribir tus propios parsers.
  • Elementos de la librería estándar como iteradores o plantillas simplifican mucho nuestros programas

SOBRE Occam's Razor
Somos una revista libre que intenta explicar de forma sencilla conceptos tecnológicos y científicos de los que no podemos escapar. Al final, todo es más fácil de lo que parece!

 
Tu publicidad aquí :)