0

For some reason, the code below doesn't append the user to the user.txt file. It always ends up in the if(file.fail()) structure. Any idea on how to fix it? I tried closing and opening the same file again before writing the user to it. But that doesn't seem to work either.

   void users::userAdd()
    {
    std::string username;
    std::string function;
    std::string user;
    std::size_t found;
    std::string line;
    std::fstream myfile ("C:\\Users\\kk\\Desktop\\users.txt",  std::ios_base::in | std::ios_base::out | std::ios_base::app);

    if (!myfile || !myfile.good())
    {
        std::cout << "could not open file!\n";
    }
    if (myfile.is_open())
    {
        std::cout<<"new username:";
        std::cin>>username;

        while (! myfile.eof())
        {
            getline (myfile,line);
            found = line.find(username);

            if (found != std::string::npos)
            {
                std::cout<<"User already exists"<<std::endl;
                return;
            }
        }
        std::cout<<"Function:";
        std::cin>>function;
        user = username+ " " + function;
        myfile << user;
        myfile.close();
    }
    if (myfile.fail())
    {
        std::cout << "Failed to append to file!\n";
    }
}

Edit

I removed the std::ios_base::appendand added a couple lines: (it works like I want it to)

    ...
    std::cout<<"functie:";
    std::cin>>functie;
    myfile.clear();
    myfile.seekg(0, myfile.end);
    user = "\n" + gebruikersnaam + " " + functie;
    myfile << user;
    myfile.close();
    ...
halfer
  • 18,701
  • 13
  • 79
  • 158
  • Call [`std::fstream::clear()`](http://en.cppreference.com/w/cpp/io/basic_ios/clear) after all input was read, before append writing to the file call [`std::fstream::seekg()`](http://en.cppreference.com/w/cpp/io/basic_istream/seekg) to set the write position. Also note [`while (! myfile.eof())`](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) raises some problems. – πάντα ῥεῖ Aug 19 '14 at 11:39
  • 1
    First, you open a file in append mode, which positions the file pointer past the end of the file. Then you try to read a line from it. What do you expect the `getline` to return? – Sergey Kalinichenko Aug 19 '14 at 11:40
  • Mmh, that's true dasblinkenlight. I didn't see that directly. Thank you πάντα ῥεῖ and jotik for the solution. It works now. I'll post the solution under "EDIT:" – user3752929 Aug 19 '14 at 12:12

2 Answers2

2

You're not rewinding the file, i.e. repositioning the read/write pointer to the beginning of the file. Using std::ios_base::app means that the read/write pointer is position at the end of the file.

You should probably omit std::ios_base::app. This way your while-loop will read the whole file and effectively position the pointer to the end of the file before you append to it.

See also: this question.

PS: This looks to be a bug:

if (found != std::string::npos) {
    std::cout<<"User already exists"<<std::endl;
    return;
}

what if username is a substring of line?

jotik
  • 14,982
  • 9
  • 48
  • 106
0

Put myfile.tellg (0) to start reading from the start of the file.

halfer
  • 18,701
  • 13
  • 79
  • 158