lundi 26 décembre 2016

std::getline not working properly on Mac OSX

I am developing a simple program for practicing languages: you can add words to a database and the program asks them to you in random order. As simple as that. In the database, the format is

word \t - \t translation \t |

Here is the full code:

//The purpose of this code is to practice linguistics. It creates a database of words and then asks them in random order.
#include <iostream>
#include <string>
#include <fstream>
#include <time.h>
#include <climits>
#include <vector>
#include <random>

int
main()
{
    std::cout<<"Choose the language."<<std::endl<<"a) english \nb) french \nc) spanish \nd) portuguese"<<std::endl;
    std::string response;
    std::cin>>response;
    std::string language = response;
    if(response != "english" && response != "french" && response != "spanish" && response != "portuguese")
    {   
        std::cerr<<"Error. Exiting"<<std::endl;
        return 2;
    }

    std::cout<<"What do you want to do?"<<std::endl<<"a) Practice (type 'practice')"<<std::endl<<"b) Add a new word to database (type 'add')"<<std::endl;
    response.clear();
    std::cin>>response;
    std::fstream f;
    language.append(".txt");
    f.open (language, std::fstream::app| std::fstream::in);

    if (response=="add")
    {
        while (response != "no")
        {
            std::string word;
            std::cout<<"Alright, what is the word?"<<std::endl;
            std::cin.ignore();
            std::getline(std::cin, word);
            f<<word<<'\t'<<'-'<<'\t';
            std::cout<<"What is its translation?"<<std::endl;
            word.clear();
            std::getline(std::cin, word);
            f<<word<<'\t'<<'|'<<std::endl;
            std::cout<<"Word added. Do you want to add another one? (yes, no) "<<std::endl;
            response.clear();
            std::cin>>response;
        }
        return 0;
    }

    if (response=="practice")
    {
        std::string word;
        int n=0;
        while (f.good())
        {               
            std::getline(f, word, '|');
            n++;
            word.clear();           
        }
        n--;
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<> dis(1, n);

        while (response != "no")
        {
            f.clear();
            f.seekg(0);
            int k= dis(gen);
            for (int i=1; i<=k; i++)
            {
                std::getline(f, word, '|');
                word.clear();
            }
            std::getline(f, word, '-');
            std::cout<<"Your word is:  "<<word<<std::endl<<"Press the return key when you want to know the translation"<<std::endl;
            std::cin.ignore();
            std::getline(std::cin, response, '\n');
            std::getline(f,word,'\t');
            word.clear();
            std::getline(f, word, '|');
            std::cout<<word<<std::endl;
            std::cout<<"Do you want to keep going? (yes, no) "<<std::endl;
            response.clear();
            std::cin>>response;
        }
        return 0;

    }
    else 
        return 1;
}

The problem is the following: the code compiles without any problem, BUT: on Linux everything works as it should, however on Mac OS (I checked on a couple of Macbooks with different Operating Systems on them) it doesn't work. I traced the error to the std::getline function in line 56: it turns on the eofbit making the cycle end after just one iteration, and I cannot fully understand why (on Linux it works just fine!).

 while (f.good())
    {               
        std::getline(f, word, '|');
        n++;
        word.clear();           
    }

The debugger confirms what I have just said. You can click here to see how the program behaves!

Can you please help?

If you want to try the code yourself, here you can find the english database of words.

Aucun commentaire:

Enregistrer un commentaire