Se trata de un objeto global definido en "iostream.h".
En ejemplos anteriores ya hemos usado 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.
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 librerías, pero veremos ahora las que se usan más frecuentemente.
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.
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.
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
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
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
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.
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; cin.get(); 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
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; cin.get(); return 0; }
La salida tendrá éste aspecto:
Cadena: hola Cadena: hola
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;
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;
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;
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;
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, '#');
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');
Lee n caracteres desde el cin y los almacena a partir de la dirección ptr.
istream& read(char* ptr, int n);
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
Esta función obtiene el siguiente carácter del buffer de entrada, pero no lo retira, lo deja donde está.
int peek();
Coloca un carácter en el buffer de entrada:
istream& putback(char);
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);
© Noviembre de 2001 Salvador Pozo, salvador@conclase.net