istream_iterator вопрос, использующий в цикле - PullRequest
2 голосов
/ 31 июля 2011

Почему этот цикл не завершится?Программа останавливается после того, как она распечатывает все элементы в istream_iterator.

 /*30*/ int main( int arc, char **arv ) {
 /*31*/     vector<float> numbers( 0 );
 /*32*/     cout << "Please, input even number of floats: ";
 /*33*/     istream_iterator<float> iit (cin);
 /*34*/     istream_iterator<float> eos;
 /*35*/     while( iit != eos ) {
 /*36*/         cout << (*iit) << endl; 
 /*37*/         iit++;
 /*38*/     }   
 /*39*/     if( numbers.size( ) & 1 == 1 ) {
 /*40*/         cerr << "Sorry: you must input"
 /*41*/              << " an even number of inputs" << endl;
 /*42*/     }                                               
 /*43*/     return ( 0 );                                   
 /*44*/ }  

Обновление:

Так что теперь это делает больше.Спасибо всем.С предоставленной информацией я упростил вещи до меньшего количества строк.Нужно вернуть модульную часть, но теперь мне это намного яснее.

 34 int main( int arc, char **arv ) {
 35     vector<float> num;
 36     cout << "Please, input even number of floats: ";
 37     for( istream_iterator<float> iit (cin);
 38          iit!=istream_iterator<float>( );iit++ ) {
 39         num.push_back( (*iit) );
 40     }   
 41 }

Обновление 2: если кто-то еще читает эту ветку, могу ли я получить обратную связь по контенту / стилюот сообщества на «конечный» продукт?

/********************************************************************
 * Author: Mattew Hoggan
 * Description: Write a client program that uses the data type point.
 * Read a sequence of points (pairs of floating-point numbers) from
 * standard input, and find the one that is closest to the first.
 * *****************************************************************/

#include <math.h>                                                  
#include <iostream>                                                
#include <vector>                                                  
#include <istream>                                                 
#include <iterator>
#include <algorithm>
#include <limits.h>

using namespace std;                                               

typedef struct point {                                             
    float x;                                                       
    float y;                                                       
} point;                                                           

float calc_distance( const point *a, const point *b ) {            
    return sqrt( pow( a->x-b->x, 2.0 ) + pow( a->y-b->y, 2.0 ) );      
}                                                                  

void print_point( point *a ) {                                 
    cout << "(" << a->x << ", " << a->y << ") ";
}

void delet_point( point *a ) {
    delete a;
}

vector<point*>* form_pairs( vector<float> &num ) {
    vector<point*> *points=NULL;
    if( ( num.size( ) & 1 ) == 1 ) { 
        cerr << "ERROR: You input: " << num.size( ) 
             << " which is odd, failed to build vector "
             << endl;
        return points;
    } else {
        cout << "Going to build points" << endl;
        points = new vector<point*>;
        for( vector<float>::iterator vit=num.begin( );
            vit!=num.end( ); vit+=2 ) {
            point *in = new point( );
            in->x = *(vit);
            in->y = *(vit+1);
            points->push_back( in );     
        }   
        return points;
    }
}

void pop_front( vector<point*> *pairs ) {
    reverse( pairs->begin( ), pairs->end( ) );
    pairs->pop_back( );
    reverse( pairs->begin( ), pairs->end( ) );
}

void min_euclidean_distance( vector<point*> *pairs ) {
    if( pairs->size( ) == 1 ) {
        cerr << "You already know the answer to this" << endl;
        return;
    }
    point *first = pairs->front( );
    pop_front( pairs );
    point *second = pairs->front( );
    pop_front( pairs );

    for_each( pairs->begin( ),pairs->end( ),print_point );
    cout << endl;

    point *p_min = second;
    float f_min = calc_distance( first,second );
    for( vector<point*>::iterator pit = pairs->begin( );
        pit != pairs->end( ); pit++ ) {
        float tmp = calc_distance( first,(*pit) );
        if( tmp < f_min ) {
            f_min = tmp;
            p_min = (*pit);
        }
    }

    cout << "The closest node to "; print_point( first );
    cout << " is "; print_point( p_min );
    cout << " at " << f_min << " units away " << endl;
    delete first;
    delete second;
}

int main( int arc, char **arv ) {                                
    vector<float> num;
    cout << "Please, input even number of floats: ";
    for( istream_iterator<float> iit (cin);
         iit!=istream_iterator<float>( );iit++ ) {
         num.push_back( (*iit) );
    }

    vector<point*>* pairs = form_pairs( num );
    if( pairs ) {
        min_euclidean_distance( pairs );
        for_each( pairs->begin( ),pairs->end( ),delet_point );
        delete pairs;
    }
}  

Ответы [ 3 ]

10 голосов
/ 31 июля 2011

Если вы подключите istream_iterator к потоку, то istream_iterator будет действительным до тех пор, пока для потока, из которого он читает, не будет установлен failbit или badbit. Это происходит только в том случае, если вы читаете искаженные данные из потока или в потоке данных заканчиваются.

Поскольку cin считывает данные из стандартного потока ввода (который по умолчанию в большинстве систем подключен к клавиатуре), istream_iterator всегда может считывать больше данных. То есть, после того, как вы ввели список чисел, cin не будет в состоянии ошибки, потому что вы всегда можете ввести больше чисел в программу. Тот факт, что программа «зависает», вызван тем, что она ожидает ввода большего количества данных. Вы можете проверить это, введя дополнительные данные после того, как программа обработает все введенные вами данные.

Чтобы cin прекратил чтение данных, у вас есть несколько вариантов. Во-первых, вы можете сделать так, чтобы ОС перенаправляла cin, передавая данные в программу или считывая данные из файла. Например, в системе Linux вы можете запустить свою программу следующим образом:

./my-program < my-input-file

Как только программа прочитает весь текст из my-input-file, cin встретит конец файла и вызовет failbit. Затем цикл завершается.

Кроме того, вы можете явно указать, что cin достигнет конца файла. В системах Linux, если вы запускаете программирование из командной строки, вы можете нажать CTRL + D, чтобы заставить стандартный ввод отправить сигнал конца файла, что также приведет к выходу из цикла. В качестве альтернативы вы можете ввести недопустимое значение с плавающей точкой в ​​cin, например строку STOP!. Это приведет к тому, что failbit сработает на cin, поскольку он не может обрабатывать значение как число с плавающей запятой, а затем приведет к выходу из цикла.

Надеюсь, это поможет!

5 голосов
/ 31 июля 2011

Программа работает нормально, просто вы должны указать конец файла при вводе:

echo 1.1 5.3 | ./myprogram

Если вы буквально печатаете на консоли, отправьте Ctrl-D, чтобы сообщить об окончании ввода.

(Несомненно, ваше условное выражение, вероятно, должно читаться if( numbers.size( ) % 2 != 0 ) для ясности и семантики; также компилируйте и учитывайте предупреждения компилятора.)

3 голосов
/ 31 июля 2011

Стандартный ввод не имеет конца (, если вы не передаете ему что-то ); это продолжается навсегда . Следовательно, итератор istream никогда не достигнет EOF, поскольку EOF.

не существует.
...