2011-01-22 13 views

Respuesta

5

Puede utilizar un locale a ch ange qué cosas se leen del archivo a medida que se lee. Es decir, va a filtrar todos los valores no numéricos:

struct numeric_only: std::ctype<char> 
{ 
    numeric_only(): std::ctype<char>(get_table()) {} 

    static std::ctype_base::mask const* get_table() 
    { 
     static std::vector<std::ctype_base::mask> 
      rc(std::ctype<char>::table_size,std::ctype_base::space); 

     std::fill(&rc['0'], &rc[':'], std::ctype_base::digit); 
     return &rc[0]; 
    } 
}; 

std::fstream myFile("foo.txt"); 
myfile.imbue(std::locale(std::locale(), new numeric_only())); 

A continuación, cuando se lee el archivo, se va a convertir todos los dígitos para los no dejando espacios que sólo los números. Después de eso, puedes simplemente usar tus conversiones normales para transformar lo que se está leyendo en ints.

std::vector<int> intFromFile; 
std::istream_iterator<int> myFileIter(myFile); 
std::istream_iterator<int> eos; 
std::copy(myFileIter, eos, std::back_inserter(intFromFile)); 

respuesta a los siguientes comentarios:

Aquí es lo que hice para conseguir que funcione

int main(int args, char** argv){ 
    std::fstream blah; 
    blah.open("foo.txt", std::fstream::in); 
    if(!blah.is_open()){ 
     std::cout << "no file"; 
     return 0; 
    } 
    blah.imbue(std::locale(std::locale(), new numeric_only())); 

    std::vector<int> intFromFile; 
    std::istream_iterator<int> myFileIter(blah); 
    std::istream_iterator<int> eos; 
    std::copy(myFileIter, eos, std::back_inserter(intFromFile)); 

    return 0; 
} 

Y esto pongo sólo los enteros en el vector, nada más y nada Menos. La razón por la que no funcionaba antes era doble:

  1. Estaba llenando hasta '9' pero no '9' en sí. Cambié el relleno a ':'
  2. Los números más grandes que lo que puede contener un int son un problema. Sugeriría usar largos.
+0

Lo intenté; pero parece no funcionar – Nawaz

+0

@Nawaz ok, dame un segundo para encender mi compilador y ver dónde cometí un error. – wheaties

+0

@wheaties: Por cierto, la idea es realmente buena si la haces funcionar. Me encantaría verlo funcionar. :-) – Nawaz

1
int a,b,c; 

    cin >> a; 
    cin.ignore(100,'-'); 
    cin >> b; 
    cin.ignore(100,':'); 
    cin >> c; 

    cout << "a = "<< a <<endl; 
    cout << "b = "<< b <<endl; 
    cout << "c = "<< c <<endl; 

de entrada:

1 - 2: 3

de salida:

a = 1
b = 2
c = 3

Véase a sí mismo aquí: http://www.ideone.com/DT9KJ

Nota: este puede manejar espacios adicionales también. Así se puede leer incluso esto:

 1  -  2  :  3

tema:

Using ifstream as fscanf

+3

ser * muy * cuidado con los números mágicos en el código. Ellos * volverán a morderte. –

+0

@Konrad: ¿estás hablando de '100' en' ignorar() '? ¡Puede aumentar eso a cualquier número grande que crea que puede haber un número adicional de espacios! – Nawaz

+3

podrías pero no deberías. Realmente no cambia nada. Debe usar 'numeric_limits :: max()', si corresponde. –

0

Simplemente,

ifstream file("file.txt"); 
int n1, n2, n3; 
char tmp; 
while (file.good()) { 
    file >> n1 >> tmp >> n2 >> tmp >> n3; 
} 
+0

Eso no podrá extraer n3 si no hubiera componentes numéricos para n1 o n2, por ejemplo. –

2

yo recomendaría al menos superficiales comprobaciones de validez al leer esto:

int a, b, c; 
char dash, colon; 

if (not (cin >> a >> dash >> b >> colon >> c) or dash != '-' or colon != ':') 
    Failure. Do something. 
0

Lo sentimos Konrad, pero recomiendo: Nunca so pena de muerte, nunca se Nuncanunca (¿es lo suficientemente claro? :-) leer datos formateados de un archivo. Simplemente no lo hagas

Solo hay una forma correcta de hacer la entrada de datos formateados: leer fragmentos de caracteres (normalmente líneas, pero también puede leer bloques de longitud fija).

Luego, analice el texto de entrada. No hará un control superficial, usará un analizador sintáctico que garantice detectar cualquier error de formato e informará ese error de manera comprensible, tomará las medidas adecuadas (terminación, omita la línea y continúe, lo que sea).

Separar la entrada (la operación de E/S) del análisis.

Este consejo de décadas de experiencia como programador comercial: la lectura de la entrada formateada es para los programas micky mouse proof-of-main. Incluso si tiene el control exclusivo de la creación del archivo, siempre analice y verifique e informe los errores: después de todo, las cosas cambian, puede funcionar hoy pero no mañana.

He estado escribiendo C++ durante décadas y nunca he leído un número entero.

7

creo que ésta sería la forma más elegante--yet más rápido:

int a, b, c; 
scanf("%d-%d:%d", &a, &b, &c); 
Cuestiones relacionadas