2012-03-05 24 views
6

Estoy intentando leer un unsigned int usando cin como sigue:lectura 'unsigned int' usando 'cin'

#include <limits.h> 
#include <iostream> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    unsigned int number; 

    // UINT_MAX = 4294967295 
    cout << "Please enter a number between 0 and " << UINT_MAX << ":" << endl; 

    cin >> number; 

    // Check if the number is a valid unsigned integer 
    if ((number < 0) || ((unsigned int)number > UINT_MAX)) 
    { 
     cout << "Invalid number." << endl; 
     return -1; 
    } 
    return 0; 
} 

Sin embargo, cada vez que introduzca un valor mayor que el límite superior del número entero sin signo (UINT_MAX), el programa muestra 3435973836. ¿Cómo verifico si la entrada dada por el usuario cae entre 0 a UINT_MAX?

+12

'if ((number <0) || ((unsigned int) number> UINT_MAX))' No puedo describir lo equivocado que es esto. – ildjarn

+0

Tal vez comience con algo más simple, y definitivamente un buen libro. –

+1

Pregunta bastante básica pero razonable de hacer. Pero muy largo para explicar. – Mysticial

Respuesta

5

dos cosas:

  • Comprobación de si un entero sin signo es 0 o <> UINT_MAX no tiene sentido, ya que nunca se puede llegar a ese valor! Su compilador probablemente ya se queja con una advertencia como "la comparación siempre es falsa debido al rango limitado de tipo".

  • La única solución en la que puedo pensar es capturar la entrada en una cadena, luego usar la antigua strtoul() que establece errno en caso de desbordamiento.

es decir .:

#include <stdlib.h> 

unsigned long number; 
std::string numbuf; 
cin >> numbuf; 
number = strtoul(numbuf.c_str(), 0, 10); 
if (ULONG_MAX == number && ERANGE == errno) 
{ 
    std::cerr << "Number too big!" << std::endl; 
} 

Nota: strtoul devuelve un largo sin signo; no hay función strtou(), devolviendo un int sin signo.

+0

Probablemente sea mejor configurar errno en 0 antes de la llamada y luego verificar si hay algún valor distinto de cero. Parece que al menos EINVAL también puede suceder. –

2

Puede leer en un unsigned long long y probarlo contra el límite int sin firmar.

+0

Eso es lo que el operador >> ya está haciendo. –

+0

@BoPersson, ¿estás diciendo que '>>' se promociona automáticamente a largo tiempo? Incluso si lo hace, tendría que truncarse cuando se almacena en un int sin firmar. – AShelly

+0

Estoy diciendo que 'operator >>' está usando 'num_get' que recopila caracteres, convierte al tipo entero sin signo más grande y luego verifica el rango objetivo antes de asignar el resultado. Como si hubieras hecho eso tú mismo. –

2

Cuando los usuarios entran en un número más alto que UINT_MAX, cintapas al UINT_MAX de todos modos. El valor tampoco puede ser negativo.

Si necesita ampliar el rango, use unsigned long long para la entrada, y envíe a unsigned int después del control. Sin embargo, esto no protegerá contra los números que están fuera del rango de unsigned long long.

Para una solución de propósito general, puede leer un string, y hacer una conversión usando unsigned long long como resultado.

3

Su comprobación no tiene sentido (lo que un compilador con avisos correctamente habilitados le diría) ya que su valor nunca está por debajo de 0 y nunca por UINT_MAX, ya que son el valor más pequeño y más grande una variable del tipo unsigned int (qué número es) puede contener.

Utilice el estado de flujo para determinar si la lectura en el entero funcionó correctamente.

1

Si intenta leerlo en un unsigned int, tendrá que limitarse a las restricciones de unsigned int.

La forma más general de hacer lo que está pidiendo es leer la entrada como string y analizarla para asegurarse de que esté en el rango apropiado. Una vez que lo haya validado, puede convertirlo a unsigned int.

Cuestiones relacionadas