why am I getting the C version of getline()?

Discussion in 'C++' started by theronnightstar@gmail.com, Mar 10, 2007.

  1. Guest

    I seem to be having a problem with getline(). I have tried to find it
    on
    google, but I'm not seeing the answer. The goal of this section of
    code
    is simply to read in a line from a file to a string according to the
    conditions of the do...while statement.

    /////code

    void populate( vector<string>& unplayed_anagrams, string& word, const
    ifstream& dict_word_list )
    {
    const int max_size = word.size() + 1;
    int letters_left;
    char word_array[max_size];
    char test_word_array[max_size];
    string measure_word = " ";
    vector<int> used_letters;
    vector<int>::iterator iter;

    used_letters.clear();
    memset( test_word_array, '\0', max_size);
    memset( word_array, '\0', max_size);
    strcpy( word_array, word.c_str() );

    cout << "Please wait... Populating the arrays." << endl;

    while( !dict_word_list.eof() )
    {
    letters_left = (max_size - 1 ) ;
    do
    {
    getline( dict_word_list, measure_word ); //<-This is the
    offending code
    }
    while((measure_word.size() > word.size() && measure_word.size() <
    3) || measure_word == word);

    \\\\\code

    I have another section of code that does almost the same thing, with
    the
    exception that it works.

    /////code

    void load_words( string& word, ifstream& dict_file )
    {
    vector<string> temp_vector;
    int random_num = 0;
    int temp_size = 0;
    string line = " ";

    temp_vector.clear();

    while( word.size() < 6 )
    {
    while( !dict_file.eof() )
    {
    getline( dict_file, line );
    temp_vector.push_back( line );
    ++temp_size;
    }
    random_num = ( rand() % temp_size );
    word = temp_vector[random_num];
    }
    }

    \\\\\code

    When I compile the code, I get a compile time error pointing to the
    getline() in the first chunk of code.

    /////error

    jaag.cc: In function 'void
    populate(std::vector<std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >,
    std::allocator<std::basic_string<char, std::char_traits<char>,
    std::allocator<char> > > >&, std::string&, const std::ifstream&)':
    jaag.cc:126: error: invalid conversion from 'void*' to 'char**'
    jaag.cc:126: error: cannot convert 'std::string' to 'size_t*' for
    argument '2' to '__ssize_t getline(char**, size_t*, FILE*)'

    \\\\\error

    I was using these includes:

    /////code

    #include <iostream>
    #include <vector>
    #include <cstdlib>
    #include <cctype>
    #include <ctime>
    #include <fstream>
    #include <string>

    \\\\\code

    as best as I can figure it I am getting the C version of getline() in
    the first one and the C++ version in the second one. I can't figure
    it
    out. That's not what I need. I want them both to be C++. Any help on
    this
    would be greatly appreciated.

    Thanks

    PS I am using gcc-4.1.2 on amd64-gentoo-linux. If you need, I can
    post
    the code that is calling these functions. Thanks again.
    , Mar 10, 2007
    #1
    1. Advertising

  2. wrote:
    > I seem to be having a problem with getline(). I have tried to find it
    > on
    > google, but I'm not seeing the answer. The goal of this section of
    > code
    > is simply to read in a line from a file to a string according to the
    > conditions of the do...while statement.
    >
    > /////code
    >
    > void populate( vector<string>& unplayed_anagrams, string& word, const
    > ifstream& dict_word_list )


    Here is the error, drop the const

    void populate( vector<string>& unplayed_anagrams, string& word,
    ifstream& dict_word_list )

    And of course in *both* your functions, you should have istream not
    ifstream. Using istream in the function means the function can be used
    with any input stream, i.e. ifstream, fstream, istringstream,
    stringstream, cin, plus any others you care to define. Why limit your
    function to reading files only?

    john
    John Harrison, Mar 10, 2007
    #2
    1. Advertising

  3. Guest

    Thank you - it worked. I could have swore I tried that. *smacks self
    in head*. Anyway, thanks. As for the function - I have no use for
    anymore functionality. "Do one thing and do it well" from what I
    understand. If I ever need it again, I should know more about it and
    it shouldn't be too hard to modify.
    , Mar 10, 2007
    #3
  4. wrote:
    > Thank you - it worked. I could have swore I tried that. *smacks self
    > in head*. Anyway, thanks. As for the function - I have no use for
    > anymore functionality. "Do one thing and do it well" from what I
    > understand. If I ever need it again, I should know more about it and
    > it shouldn't be too hard to modify.
    >


    LOL, all you have to do is delete the 'f' from ifstream, not too hard?
    And it's a good habit to get into, shows you understand one of the key
    points of OO programming.

    john
    John Harrison, Mar 10, 2007
    #4
  5. Guest

    On Mar 10, 2:32 pm, John Harrison <> wrote:
    > wrote:
    > > Thank you - it worked. I could have swore I tried that. *smacks self
    > > in head*. Anyway, thanks. As for the function - I have no use for
    > > anymore functionality. "Do one thing and do it well" from what I
    > > understand. If I ever need it again, I should know more about it and
    > > it shouldn't be too hard to modify.

    >
    > LOL, all you have to do is delete the 'f' from ifstream, not too hard?
    > And it's a good habit to get into, shows you understand one of the key
    > points of OO programming.
    >
    > john


    I'll mark that one to you. I am still real new to anything past the
    most basic aspects of C++. You say istream can be bound to any input
    stream? I assume I don't have to set ios:: Correct?
    , Mar 10, 2007
    #5
  6. wrote:
    > On Mar 10, 2:32 pm, John Harrison <> wrote:
    >
    >> wrote:
    >>
    >>>Thank you - it worked. I could have swore I tried that. *smacks self
    >>>in head*. Anyway, thanks. As for the function - I have no use for
    >>>anymore functionality. "Do one thing and do it well" from what I
    >>>understand. If I ever need it again, I should know more about it and
    >>>it shouldn't be too hard to modify.

    >>
    >>LOL, all you have to do is delete the 'f' from ifstream, not too hard?
    >>And it's a good habit to get into, shows you understand one of the key
    >>points of OO programming.
    >>
    >>john

    >
    >
    > I'll mark that one to you. I am still real new to anything past the
    > most basic aspects of C++. You say istream can be bound to any input
    > stream? I assume I don't have to set ios:: Correct?
    >


    Correct, when you declare a stream variable, you have to say ifstream,
    stringstream or whatever kind of stream it is.

    But when you write a function that reads some input you should always
    declare the stream parameter as istream&, as in

    void some_function_that_reads(istream& the_stream_to_read)
    {
    ...
    }

    That way the function will work with any kind of input stream. Once you
    understand, it's a no-brainer.

    Technically the reason is that ifstream, fstream, istringstream, cin
    etc. all inherit from istream, so any of them will bind to to istream&.

    john
    John Harrison, Mar 10, 2007
    #6
  7. John Harrison wrote:
    > wrote:
    >
    >> On Mar 10, 2:32 pm, John Harrison <> wrote:
    >>
    >>> wrote:
    >>>
    >>>> Thank you - it worked. I could have swore I tried that. *smacks self
    >>>> in head*. Anyway, thanks. As for the function - I have no use for
    >>>> anymore functionality. "Do one thing and do it well" from what I
    >>>> understand. If I ever need it again, I should know more about it and
    >>>> it shouldn't be too hard to modify.
    >>>
    >>>
    >>> LOL, all you have to do is delete the 'f' from ifstream, not too hard?
    >>> And it's a good habit to get into, shows you understand one of the key
    >>> points of OO programming.
    >>>
    >>> john

    >>
    >>
    >>
    >> I'll mark that one to you. I am still real new to anything past the
    >> most basic aspects of C++. You say istream can be bound to any input
    >> stream? I assume I don't have to set ios:: Correct?
    >>

    >
    > Correct, when you declare a stream variable, you have to say ifstream,
    > stringstream or whatever kind of stream it is.
    >
    > But when you write a function that reads some input you should always
    > declare the stream parameter as istream&, as in
    >
    > void some_function_that_reads(istream& the_stream_to_read)
    > {
    > ...
    > }
    >
    > That way the function will work with any kind of input stream. Once you
    > understand, it's a no-brainer.
    >
    > Technically the reason is that ifstream, fstream, istringstream, cin
    > etc. all inherit from istream, so any of them will bind to to istream&.
    >
    > john


    Same goes for ostream& as well of course.

    john
    John Harrison, Mar 10, 2007
    #7
  8. Guest

    On Mar 10, 2:42 pm, John Harrison <> wrote:
    > John Harrison wrote:
    > > wrote:

    >
    > >> On Mar 10, 2:32 pm, John Harrison <> wrote:

    >
    > >>> wrote:

    >
    > >>>> Thank you - it worked. I could have swore I tried that. *smacks self
    > >>>> in head*. Anyway, thanks. As for the function - I have no use for
    > >>>> anymore functionality. "Do one thing and do it well" from what I
    > >>>> understand. If I ever need it again, I should know more about it and
    > >>>> it shouldn't be too hard to modify.

    >
    > >>> LOL, all you have to do is delete the 'f' from ifstream, not too hard?
    > >>> And it's a good habit to get into, shows you understand one of the key
    > >>> points of OO programming.

    >
    > >>> john

    >
    > >> I'll mark that one to you. I am still real new to anything past the
    > >> most basic aspects of C++. You say istream can be bound to any input
    > >> stream? I assume I don't have to set ios:: Correct?

    >
    > > Correct, when you declare a stream variable, you have to say ifstream,
    > > stringstream or whatever kind of stream it is.

    >
    > > But when you write a function that reads some input you should always
    > > declare the stream parameter as istream&, as in

    >
    > > void some_function_that_reads(istream& the_stream_to_read)
    > > {
    > > ...
    > > }

    >
    > > That way the function will work with any kind of input stream. Once you
    > > understand, it's a no-brainer.

    >
    > > Technically the reason is that ifstream, fstream, istringstream, cin
    > > etc. all inherit from istream, so any of them will bind to to istream&.

    >
    > > john

    >
    > Same goes for ostream& as well of course.
    >
    > john


    Nice - thanks for that very valuable lesson. I will have to make sure
    I use that.

    I still have a problem though. I put a few cout statements in as
    visual checks, but it is still failing on the getline statement. No
    compiler error, but the cout that should show what is in the string I
    am reading into says nothing. . One line above the getline() is
    another cout that does display what it is supposed to.

    /////code

    void populate( vector<string>& unplayed_anagrams, string& word,
    ifstream& word_file )
    {
    const int max_size = word.size() + 1;
    int letters_left;
    char word_array[max_size];
    char test_word_array[max_size];
    string measure_word;
    vector<int> used_letters;
    vector<int>::iterator iter;

    used_letters.clear();
    memset( test_word_array, '\0', max_size);
    memset( word_array, '\0', max_size);
    strcpy( word_array, word.c_str() );
    cout << "word_array in populate() is: "; //<-Debug statement
    for(int z = 0; z < max_size; ++z) //<-Debug statement
    {
    cout << word_array[z]; //<-Debug statement
    }
    cout << endl; //<-Debug statement
    cout << "Please wait... Populating the arrays." << endl;

    do
    {
    letters_left = (max_size - 1 ) ;
    cout << "\nletters_left is: " << letters_left << endl; //<-Debug
    statement
    do
    {
    if( word_file.is_open() ) //<-Debug statement
    cout << "The word_file is open." << endl; //<-Debug statement -
    works
    getline( word_file, measure_word ); //<-Problem
    cout << "\nmeasure_word in populate() is: " << measure_word <<
    endl; //<-Debug statement - doesn't work
    }
    while( ( measure_word.size() > word.size() && measure_word.size() <
    3 ) || measure_word == word );

    strcpy( test_word_array, measure_word.c_str() );

    I went back with the ifstream in the declaration though - is_open()
    doesn't work otherwise.
    , Mar 10, 2007
    #8
  9. Guest

    Sorry bout quoted text above.
    , Mar 10, 2007
    #9
  10. >
    > Nice - thanks for that very valuable lesson. I will have to make sure
    > I use that.
    >
    > I still have a problem though. I put a few cout statements in as
    > visual checks, but it is still failing on the getline statement. No
    > compiler error, but the cout that should show what is in the string I
    > am reading into says nothing. . One line above the getline() is
    > another cout that does display what it is supposed to.
    >


    The only explanation is that word_file isn't in the state you think it
    is. Possibly it's already at the end of file. Possibly you were reading
    something before and got an error. Possibly the file simply isn;t
    positioned where you think it is. In any case it must be something about
    how you used word_file before you call the populate function. Perhaps
    you could post that code.

    > /////code
    >
    > void populate( vector<string>& unplayed_anagrams, string& word,
    > ifstream& word_file )
    > {
    > const int max_size = word.size() + 1;
    > int letters_left;
    > char word_array[max_size];
    > char test_word_array[max_size];


    Neither of the above two line are legal C++ because max_size is not a
    compile time constant. I know it's a constant, but it's not a compile
    time constant as the value must be worked out at runtime.

    There is one compiler I know which allows this kind of code, but if you
    try this code on a different compiler you will likely get an error.

    john
    John Harrison, Mar 10, 2007
    #10
  11. Guest

    As you can tell I am trying to do a simple anagram game for my fiance.
    She loves them and I thought it would be an excellent learning
    exercise. I was very right, but this I can't figure out. I know there
    are a million better ways to this, but like I said, I am on a quest to
    learn by this. This is the full code as it runs (sorry about the
    length):

    /////code

    #include <iostream>
    #include <vector>
    #include <cstdlib>
    #include <cctype>
    #include <ctime>
    #include <fstream>
    #include <string>

    using namespace std;

    void test_functions();
    void test2(vector<string>& unplayed, vector<string>& played);
    void load_words( string& word, istream& dict_file ); //Loads the words
    from the dict_file to memory and chooses a game word
    void populate( vector<string>& unplayed_anagrams, string& word,
    ifstream& word_file );

    void test_functions()
    {
    srand(time(0));
    vector<string> unplayed_anagrams;
    vector<string> played_anagrams;
    string word;
    ifstream file;
    char again = 'y';

    file.open("test_list");
    unplayed_anagrams.clear();
    played_anagrams.clear();

    load_words(word, file);
    cout << "\nChosen word is: " << word << endl;

    populate(unplayed_anagrams, word, file); //<- Everthing is fine to
    here

    test2(unplayed_anagrams, played_anagrams);

    string test_word;
    here:
    int y = 1;
    while( y == 1 )
    {
    cout << "\nChoose an anagram: ";
    getline(cin, test_word);
    y = anagram_test(unplayed_anagrams, played_anagrams, test_word);
    if( y == 1)
    {
    cout << "Anagram is not valid." << endl;
    }
    else
    {
    cout << "Anagram should be valid." << endl;
    }
    }
    test2(unplayed_anagrams, played_anagrams);
    cout << "\nTest more? ";
    cin.get(again);
    cin.ignore(1, '\n');
    if( again == 'y' )
    {
    goto here;
    }

    }

    void test2(vector<string>& unplayed, vector<string>& played)
    {
    vector<string>::iterator iter;

    cout << "unplayed_anagrams are:" << endl;
    int x = 1;
    for( iter = unplayed.begin(); iter != unplayed.end(); ++iter)
    {
    cout << x << ". " << *iter << endl;
    }
    x = 1;
    cout << "\nplayed_anagrams are:" << endl;
    for( iter = played.begin(); iter != played.end(); ++iter)
    {
    cout << x << ". " << *iter << endl;
    }
    }
    void populate( vector<string>& unplayed_anagrams, string& word,
    ifstream& word_file )
    {
    const int max_size = word.size() + 1;
    int letters_left;
    char word_array[max_size];
    char test_word_array[max_size];
    string measure_word;
    vector<int> used_letters;
    vector<int>::iterator iter;

    used_letters.clear();
    memset( test_word_array, '\0', max_size);
    memset( word_array, '\0', max_size);
    strcpy( word_array, word.c_str() );
    cout << "word_array in populate() is: ";
    for(int z = 0; z < max_size; ++z)
    {
    cout << word_array[z];
    }
    cout << endl;
    cout << "\nPlease wait... Populating the arrays." << endl;

    do
    {
    letters_left = (max_size - 1 );
    cout << "\nletters_left is: " << letters_left << endl; //<- Works
    here
    do
    {
    if( word_file.is_open() )
    cout << "The word_file is open." << endl; //<-this displays
    getline( word_file, measure_word );
    cout << "\nmeasure_word in populate() is: " << measure_word <<
    endl; //<-This does not
    }
    while( ( measure_word.size() > word.size() && measure_word.size() <
    3 ) || measure_word == word );

    strcpy( test_word_array, measure_word.c_str() );

    for( int x1 = 0; x1 < max_size; ++x1)
    {
    for( int x2 = 0; x2 < max_size; ++x2 )
    {
    if( test_word_array[x2] == word_array[x1] )
    {
    for( iter = used_letters.begin(); iter != used_letters.end();
    ++iter )
    {
    if( x2 != *iter )
    {
    continue;
    }
    else
    {
    break;
    }
    }
    if( iter == used_letters.end() )
    {
    used_letters.push_back(x1);
    --letters_left;
    }
    else
    {
    continue;
    }

    }
    else
    {
    continue;
    }
    }
    }
    if( letters_left == 0 )
    {
    string blah = test_word_array;
    unplayed_anagrams.push_back(blah);
    }
    else
    {
    continue;
    }
    }
    while( !word_file.eof() );
    cout << "\nDone." << endl;
    }
    void load_words( string& word, istream& dict_file )
    {
    vector<string> temp_vector;
    int random_num = 0;
    int temp_size = 0;
    string line = " ";

    temp_vector.clear();

    while( word.size() < 6 )
    {
    while( !dict_file.eof() )
    {
    getline( dict_file, line );
    cout << line << endl;
    temp_vector.push_back( line );
    ++temp_size;
    }
    random_num = ( rand() % temp_size );
    word = temp_vector[random_num];
    }
    }

    //irrelevant code removed

    int main()
    {
    test_functions();
    return 0;
    }
    , Mar 10, 2007
    #11
  12. wrote:
    > As you can tell I am trying to do a simple anagram game for my fiance.
    > She loves them and I thought it would be an excellent learning
    > exercise. I was very right, but this I can't figure out. I know there
    > are a million better ways to this, but like I said, I am on a quest to
    > learn by this. This is the full code as it runs (sorry about the
    > length):


    No problem. The issue is that you read the "test_list" all the way to
    the end of file in load_words. It's still at the end of file when you
    call populate. Even worse when you read past the end of file that puts
    the stream into an error state. When a stream is in an error state
    nothing works until you clear the error state.

    Now I'm not sure exactly what you are trying to do, but I would guess
    that you want to go back to the beginning of the file before you call
    the populate function, so that populate starts reading from the
    beginning of "test_list". If so then see the additional code below

    >
    > /////code
    >
    > #include <iostream>
    > #include <vector>
    > #include <cstdlib>
    > #include <cctype>
    > #include <ctime>
    > #include <fstream>
    > #include <string>
    >
    > using namespace std;
    >
    > void test_functions();
    > void test2(vector<string>& unplayed, vector<string>& played);
    > void load_words( string& word, istream& dict_file ); //Loads the words
    > from the dict_file to memory and chooses a game word
    > void populate( vector<string>& unplayed_anagrams, string& word,
    > ifstream& word_file );
    >
    > void test_functions()
    > {
    > srand(time(0));
    > vector<string> unplayed_anagrams;
    > vector<string> played_anagrams;
    > string word;
    > ifstream file;
    > char again = 'y';
    >
    > file.open("test_list");
    > unplayed_anagrams.clear();
    > played_anagrams.clear();
    >
    > load_words(word, file);
    > cout << "\nChosen word is: " << word << endl;
    >


    // load_words has placed file in an error state
    // since it read to end of file, so first thing
    // to do is clear the error state
    file.clear();

    // now we want to start reading from the beginning
    // of the file again, so seek to start of file
    file.seekg(0, ios_base::beg);

    // now (hopefully) everything should be OK

    > populate(unplayed_anagrams, word, file); //<- Everthing is fine to
    > here
    >


    john
    John Harrison, Mar 10, 2007
    #12
  13. Guest

    You are so absolutely the man. That solved it all. Thanks for the
    lesson. I'll take it to heart. lol such a simple solution. Thanks
    again.
    Raymond
    , Mar 10, 2007
    #13
  14. Jerry Coffin Guest

    In article <>,
    says...

    [ ... ]

    > while( !word_file.eof() );


    [ ... ]

    > while( !dict_file.eof() )


    I haven't looked through all your code, but these jumped out at first
    glance. For all practical purposes, a loop like this can never work
    correctly. whatever.eof() only returns true when you attempt to read
    from the file but you've _already_ read all the input. Usually, you need
    to read the input, and check the return from that attempt to read, to
    see whether it encountered the end of the file or not. A typical
    (correct) loop would looks something like:

    while (getline(dict_file, line)) {
    cout << line << endl;
    temp_vector.push_back(line);
    ++ temp_size;
    }

    Since it looks like you have quite a few places that you read strings a
    line at a time, I'd consider writing a small proxy class that works that
    way:

    class line {
    std::string data;
    public:
    operator std::string() const { return data; }

    friend std::istream &operator>>(std::istream &is, line &l) {
    return std::getline(is, l.data);
    }
    };

    This allows you to read a line at a time using the normal stream
    extraction operator (>>). stream_iterators use insertion and extraction
    operators, so once you support them, you can use standard algorithms for
    quite a bit of what you're doing. For example, I'd rewrite your
    load_words something like this:

    string load_words(string &word, istream &dict_file) {
    vector<string> temp_vector;

    // read data from file to vector:
    copy(istream_iterator<line>(dict_file),
    istream_iterator<line>(),
    back_inserter(temp_vector));

    // write data from vector to cout
    std::copy(temp_vector.begin(), temp_vector.end(),
    ostream_iterator<string>(std::cout, "\n"));

    // return randomly chosen word
    return temp_vector[rand() % temp_vector.size()];
    }

    I didn't look at it in detail, but I did notice that part of your code
    uses strcpy -- chances are that you'd be better off using std::string
    instead, in which case you can just use the assignment operator.

    I should also add that if you're going to call load_words very often
    (like anything more than once), it would generally be quite a bit better
    to read the file only once during initialization, and from then on use
    the data from memory.

    As a general rule, I'd also advise that when you post code like this,
    you provide at least some minimal explanation of 1) what you want it to
    do, and 2) what it's not doing that you want it to (or what it's doing
    that you don't want). It might be reasonable to assume people remember
    your post from a few days ago in a newsgroup that gets only a half dozen
    posts a week (or something on that order), but in a newsgroup this busy,
    most people have to rely almost entirely on _this_ post to figure out
    what it's about.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
    Jerry Coffin, Mar 10, 2007
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    863
    Mark Rae
    Dec 21, 2006
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,768
    Smokey Grindel
    Dec 2, 2006
  3. V Green
    Replies:
    0
    Views:
    830
    V Green
    Feb 5, 2008
  4. PA Bear [MS MVP]
    Replies:
    0
    Views:
    935
    PA Bear [MS MVP]
    Feb 5, 2008
  5. MowGreen [MVP]
    Replies:
    5
    Views:
    2,002
    PA Bear [MS MVP]
    Feb 9, 2008
Loading...

Share This Page