Objeto cin

Se trata de un objeto global definido en "iostream.h".

En ejemplos anteriores ya hemos usado el operador >>.

El operador >>

Ya conocemos el operador >>, lo hemos usado para capturar variables.

istream &operator>>(int&)

Este operador está sobrecargado en cin para los tipos estándar: int&, short&, long&, double&, float&, charamp;& y char*.

Además, el operador << devuelve una referencia objeto ostream, de modo que puede asociarse. Estas asociaciones se evalúan de izquierda a derecha, y permiten expresiones como:

cin >> var1 >> var2;
cin >> variable;

Cuando se usa el operador >> para leer cadenas, la lectura se interrumpe al encontrar un carácter '\0', ' ' o '\n'.

Hay que tener cuidado, ya que existe un problema cuando se usa el operador >> para leer cadenas: cin no comprueba el desbordamiento del espacio disponible para el almacenamiento de la cadena, del mismo modo que la función gets tampoco lo hace. De modo que resulta poco seguro usar el operador >> para leer cadenas.

Por ejemplo, declaramos:

char cadena[10]; 
cin >> cadena;

Si el usuario introduce más de diez caracteres, los caracteres después de décimo se almacenarán en una zona de memoria reservada para otras variables o funciones.

Existe un mecanismo para evitar este problema, consiste en formatear la entrada para limitar el número de caracteres a leer:

char cadena[10];
cin.width(sizeof(cadena));
cin >> cadena;

De este modo, aunque el usuario introduzca una cadena de más de diez caracteres sólo se leerán diez.

Funciones interesantes de cin

Hay que tener en cuenta que cin es un objeto de la clase "istream", que a su vez está derivada de la clase "ios", así que heredará todas las funciones y operadores de ambas clases. Se mostrarán todas esas funciones con más detalle en la documentación de las bibliotecas, pero veremos ahora las que se usan más frecuentemente.

Formatear la entrada

El formato de las entradas de cin, al igual que sucede con cout, se puede modificar mediante flags. Estos flags pueden leerse o modificarse mediante las funciones flags, setf y unsetf.

Otro medio es usar manipuladores, que son funciones especiales que sirven para cambiar la apariencia de una operación de salida o entrada de un stream. Su efecto sólo es válido para una operación de entrada o salida. Además devuelven una referencia al stream, con lo que pueden ser insertados en una cadena entradas o salidas.

Por el contrario, modificar los flags tiene un efecto permanente, el formato de salida se modifica hasta que se restaure o se modifique el estado del flag.

Funciones manipuladoras con parámetros

Para usar estos manipuladores es necesario incluir el fichero de cabecera iomanip.

Existen cuatro de estas funciones manipuladoras aplicables a cin: setw, setbase, setiosflags y resetiosflags.

Todas trabajan del mismo modo, y afectan sólo a la siguiente entrada o salida.

En el caso de cin, no todas las funciones manipuladoras tienen sentido, y algunas trabajan de un modo algo diferentes que con streams de salida.

Manipulador setw

Permite establecer el número de caracteres que se leerán en la siguiente entrada desde cin. Por ejemplo:

#include <iostream>
#include <iomanip>
using namespace std;
 
int main() {
   char cad[10];
 
   cout << "Cadena:"
   cin >> setw(10) >> cad;

   cout << cad << endl
   return 0;
}

La salida tendrá este aspecto, por ejemplo:

Cadena: 1234567890123456
123456789

Hay que tener en cuenta que el resto de los caracteres no leídos por sobrepasar los diez caracteres, se quedan en el buffer de entrada de cin, y serán leídos en la siguiente operación de entrada que se haga. Ya veremos algo más abajo cómo evitar eso, cuando veamos la función "ignore".

El manipulador setw no tiene efecto cuando se leen números, por ejemplo:

#include <iostream>
#include <iomanip>
using namespace std;
 
int main() {
   int x;
 
   cout << "Entero:"
   cin >> setw(3) >> x

   cout << x << endl
   return 0;
}

La salida tendrá este aspecto, por ejemplo:

Entero: 1234567
1234567
Manipulador setbase

Permite cambiar la base de numeración que se usará para la entrada de números enteros. Sólo se admiten tres valores: 8, 10 y 16, es decir, octal, decimal y hexadecimal. Por ejemplo:

#include <iostream>
#include <iomanip>
using namespace std;
 
int main() {
   int x;
 
   cout << "Entero: ";
   cin >> setbase(16) >> x;

   cout << "Decimal: " << x << endl;
   return 0;
}

La salida tendrá este aspecto:

Entero: fed4

Decimal: 65236
Manipuladores setiosflags y resetiosflags

Permiten activar o desactivar, respectivamente, los flags de formato de entrada. Existen quince flags de formato a los que se puede acceder mediante un enum definido en la clase ios:

flag Acción
skipws ignora espacios en operaciones de lectura
left ajusta la salida a la izquierda
right ajusta la salida a la derecha
internal deja hueco después del signo o el indicador de base
dec conversión a decimal
oct conversión a octal
hex conversión a hexadecimal
showbase muestra el indicador de base en la salida
showpoint muestra el punto decimal en salidas en punto flotante
uppercase muestra las salidas hexadecimales en mayúsculas
showpos muestra el signo '+' en enteros positivos
scientific muestra los números en punto flotante en notación exponencial
fixed usa el punto decimal fijo para números en punto flotante
unitbuf vacía todos los buffers después de una inserción
stdio vacía los buffers stdout y stderr después de una inserción

De los flags de formato listados, sólo tienen sentido en cin los siguientes: skipws, dec, oct y hex.

Veamos un ejemplo:

#include <iostream>
#include <iomanip>
using namespace std;
 
int main() {
   char cad[10];

   cout << "Cadena: ";
   cin >> setiosflags(ios::skipws) >> cad;
   cout << "Cadena: " << cad << endl;

   return 0;
}

La salida tendrá este aspecto:

Cadena:         prueba
Cadena: prueba

Manipuladores sin parámetros

Existen otro tipo de manipuladores que no requieren parámetros, y que ofrecen prácticamente la misma funcionalidad que los anteriores. La diferencia es que los cambios son permanentes, es decir, no sólo afectan a la siguiente entrada, sino a todas las entradas hasta que se vuelva a modificar el formato afectado.

Manipuladores dec, hex y oct
inline ios& dec(ios& i)
inline ios& hex(ios& i)
inline ios& oct(ios& i)

Permite cambiar la base de numeración de las entradas de enteros:

Función Acción
dec Cambia la base de numeración a decimal
hex Cambia la base de numeración a hexadecimal
oct Cambia la base de numeración a octal

El cambio persiste hasta un nuevo cambio de base. Ejemplo:

#include <iostream>
using namespace std;

int main() {
   int x, y, z;

   cout << "Entero decimal (x y z): ";
   cin >> dec >> x >> y >> z;
   cout << "Enteros: " << x << ", " 
        << y << ", " << z << endl;
   cout << "Entero octal (x y z): ";
   cin >> oct >> x >> y >> z;
   cout << "Enteros: " << x << ", " 
        << y << ", " << z << endl;
   cout << "Entero hexadecimal (x y z): ";
   cin >> hex >> x >> y >> z;
   cout << "Enteros: " << x << ", " 
        << y << ", " << z << endl;

   return 0;
}

La salida tendrá éste aspecto:

Entero decimal (x y z): 10 45 25
Enteros: 10, 45, 25
Entero octal (x y z): 74 12 35
Enteros: 60, 10, 29
Entero hexadecimal (x y z): de f5 ff
Enteros: 222, 245, 255
Función ws
extern istream& ws(istream& ins);

Ignora los espacios iniciales en una entrada de cadena. Ejemplo:

#include <iostream>
using namespace std;
 
int main() {
   char cad[10];

   cout << "Cadena: ";
   cin >> ws >> cad;
   cout << "Cadena: " << cad << endl;

   return 0;
}

La salida tendrá éste aspecto:

Cadena:      hola
Cadena: hola
Función width()

Cambia la anchura en caracteres de la siguiente entrada de stream:

int width();
int width(int);

La primera forma devuelve el valor de la anchura actual, la segunda permite cambiar la anchura para la siguiente entrada, y también devuelve el valor actual de la anchura. Esta función no tiene efecto con variables que no sean de tipo cadena.

   char cadena[10];
 
   cin.width(sizeof(cadena));
   cin >> cadena;
Función setf()

Permite modificar los flags de manipulación de formato:

long setf(long);
long setf(long valor, long mascara);

La primera forma activa los flags que estén activos tanto en el parámetro y deja sin cambios el resto.

La segunda forma activa los flags que estén activos tanto en valor como en máscara y desactiva los que estén activos en mask, pero no en valor. Podemos considerar que mask contiene activos los flags que queremos modificar y valor los flags que queremos activar.

Ambos devuelven el valor previo de los flags.

   int x;
   
   cin.setf(ios::oct, ios::dec | ios::oct | ios::hex);
   cin >> x;
Función unsetf()

Permite eliminar flags de manipulación de formato:

void unsetf(long mascara);

Desactiva los flags que estén activos en el parámetro.

Nota: en algunos compiladores he comprobado que esta función tiene como valor de retorno el valor previo de los flags.

   int x;
   
   cin.unsetf(ios::dec | ios::oct | ios::hex);
   cin.setf(ios::hex);
   cin >> x;
Función flags()

Permite cambiar o leer los flags de manipulación de formato:

long flags () const;
long flags (long valor);

La primera forma devuelve el valor actual de los flags.

La segunda cambia el valor actual por valor, el valor de retorno es el valor previo de los flags.

   int x;
   long f;
   
   f = flags();
   f &= !(ios::hex | ios::oct | ios::dec);
   f |= ios::dec;
   cin.flags(f);
   cin >> x;

Función get

La función get() tiene tres formatos:

int get();
istream& get(char& c);
istream& get(char* ptr, int len, char delim = '\n');

Sin parámetros, lee un carácter, y lo devuelve como valor de retorno:

Nota: Esta forma de la función get() se considera obsoleta.

Con un parámetro, lee un carácter:

En este formato, la función puede asociarse, ya que el valor de retorno es una referencia a un stream. Por ejemplo:

char a, b, c;
 
cin.get(a).get(b).get(c);

Con tres parámetros: lee una cadena de caracteres:

En este formato la función get lee caracteres hasta un máximo de 'len' caracteres o hasta que se encuentre el carácter delimitador.

char cadena[20];
 
cin.get(cadena, 20, '#');
Función getline

Funciona exactamente igual que la versión con tres parámetros de la función get(), salvo que el carácter delimitador también se lee, en la función get() no.

istream& getline(char* ptr, int len, char delim = '\n');
Función read

Lee n caracteres desde el cin y los almacena a partir de la dirección ptr.

istream& read(char* ptr, int n);
Función ignore

Ignora los caracteres que aún están pendientes de ser leídos:

istream& ignore(int n=1, int delim = EOF);

Esta función es útil para eliminar los caracteres sobrantes después de hacer una lectura con el operador >>, get o getline; cuando leemos con una achura determinada y no nos interesa el resto de los caracteres introducidos. Por ejemplo:

#include <iostream>
#include <iomanip>
using namespace std;
 
int main() {
   char cad[10];
   int i;
 
   cout << "Cadena: ";
   cin >> setw(10) >> cad;
   cout << "Entero: ";
   cin.ignore(100, '\n') >> i;
   cout << "Cadena: " << cad << endl;
   cout << "Entero: " << i << endl;

   cin.get();
   return 0;
}

La salida podría tener este aspecto:

Cadena: cadenademasiadolarga
Entero: 123
Cadena: cadenadem
Entero: 123
Función peek

Esta función obtiene el siguiente carácter del buffer de entrada, pero no lo retira, lo deja donde está.

int peek();
Función putback

Coloca un carácter en el buffer de entrada:

istream& putback(char);
Función scan

Lee variables con formato, es análogo al scanf de "stdio":

istream& scan(char* format, ...);

Nota: algunos compiladores no disponen de esta función.

Ejemplo:

   char l;
   int i;
   float f;
   char cad[15];
 
   cin.scan("%c%d%f%s", &l, &i, &f, cad);

Comentarios de los usuarios (2)

Lizardo Reyes Jara
2010-07-23 03:22:18

Hola, yo estudio programacion en c++, y me quedaban dudas pero leyendo todos los capitulos de su curso estoy ahora perfeccionando esos detalles que no me ensañaron y que recien estoy aprendiendo, ademas cuando termine c++, pienso estudiar html, css y mysql .. que son los temas que mas me gustan ..

Saludos

Juan Tijerina
2014-12-04 21:40:51

Me podrias ayudar con un programa que me encargaron..?

Esto es lo que me piden:

Desarrolle un programa con estructuras que almacene datos, de acuerdo a la siguiente tabla. El programa deberá INICIALIZAR la estructura antes de hacer cualquier cosa. Los datos iniciales serán de acuerdo a la tabla

1.-Matricula:

2.-Nombre:

3.-Grupo:

4.-Semestre:

1.-1670868

2.-Aurora

3.-322

4.-3

1.-1660002

2.-Eduardo

3.-353

4.-3

1.-1658288

2.-Barbará

3.-321

4.-3

1.-1681561

2.-Alejandra

3.-354

4.-3

1.-1627430

2.-Fernando

3.-334

4.-3

1.-1658368

2.-Félix

3.-522

4.-5

1.-1662162

2.-Missael

3.-521

4.-5

1.-1410752

2.-Said

3.-132

4.-1

1.-1734233

2.-Daniel

3.-132

4.-1

1.-1232432

2.-Abraham

3.-612

4.-6

Una vez hecho esto, el programa deberá imprimir un menú con las siguientes opciones:

1.- Buscar por Matricula

2.- Buscar por Grupo

3.- Buscar por Semestre

4.- Salir

El programa solo deberá cerrarse hasta que el usuario seleccione la opción de SALIR.