开发者

istream_iterator question, using in loop

Why will this loop not terminate? The program freezes after it prints out all the elements in the 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*/ }  

Update:

So this now make more since. Thanks all. With the information provided I simplified things to less lines. Need to get the modulus part back in, but that is a lot more clear to me now.

 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 }

Update 2: If anyone is still reading this thread, can I get content/style feedback from the community on the "final" product?

/********************************************************************
 * 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;
    }
}  


If you connect an istream_iterator to a stream, that istream_iterator will be valid until the stream it reads from has failbit or badbit set. This only happens if you read malformed data out of the stream, or the stream runs out of data.

Because cin reads data from the standard input stream (which, by default on most systems, is connected to the keyboard), the istream_iterator can always read more data. That is, after you've entered a list of numbers, cin won't be in an error state because you can always enter more numbers into the program. The fact that the program is "freezing" is caused by the fact that it's waiting for more input to be entered. You can verify this by entering more data after the program processes all the data that you've entered.

To cause cin to stop reading data, you have several options. First, you can have the OS redirect cin by piping data into the program or reading the data out of a file. For example, on a Linux system, you could run your program like this:

./my-program < my-input-file

Once the program has read all of the text from my-input-file, cin will encounter the end of file and will trigger failbit. The loop then terminates.

Alternatively, you could explicitly cause cin to hit the end-of-file. On Linux systems, if you're running the programming from the command-line, you can press CTRL+D to cause standard input to send an end-of-file signal, which would also cause the loop to exit. Alternatively, you could enter an invalid floating-point value into cin, such as the string STOP!. This would cause failbit to trigger on cin, since it can't treat the value as a float, and would then cause the loop to exit.

Hope this helps!


The program works fine, it's just that you have to provide an end-of-file in your input:

echo 1.1 5.3 | ./myprogram

If you're literally typing on the console, send Ctrl-D to signal the end of the input.

(Unrelatedly, your conditional should probably read if( numbers.size( ) % 2 != 0 ) for clarity and semanticity; also, do compile with and heed compiler warnings.)


Standard input has no end (unless you pipe something to it); it continues forever. Therefore, the istream iterator will never actually reach the EOF because there is no EOF.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜