firstly I admit I am asking this because of my homework
secondly, my c++ is still at a beginner level. so I need some help.

ok..going back to my question.

I am trying to remove a line containing username and password from text file.
so I tried to following,

1)Read the text file.

2)store the userName and password inside the textfile.

3)prompt the user which user he wants to delete.

4)the entire line will be deleted in the vector if the input matches with the username in the vector.

this is my contents of my textfile formatted by(username password)

textfile(userInfo.txt)

amber abc
janet def
chris DEF
gerald AZC

my output of my codes(say if I choose to delete janet.seems ok)

Before Deletion
amber abc
janet def
chris DEF
gerald AZC

Enter User Name to delete: amber

After Deletion
amber abc
chris DEF
gerald AZC

my output of my codes(now if I try to delete gerald)

Before Deletion
amber abc
janet def
chris DEF
gerald AZC

Enter User Name to delete: amber

After Deletion
amber abc
janet def
chris DEF
gerald AZC

As you can see. if I try to delete the last element in the vector, it will not get deleted.
I hope someone can explain it to me and tell me what I should do. Thanks.

NOTE
** I am not allowed to use c++11 for my solution for my homework **

my full codes

user.h

#ifndef user_user_h
#define user_user_h
#include <iostream>

class user  {

public:
   user() {
        userName = " ";
        password = " ";
   }

    user(std::string userName,std::string password);

    std::string getUserName();
    std::string getPassword();

    void setUserName(std::string userName);
    void setPassword(std::string password);

private:
    std::string userName,password; 
};
#endif

main.cpp

#include "user.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>

using namespace std;

user::user(string userName,string password)  {
    setUserName(userName);
    setPassword(password);
};

string user::getUserName()    {
    return userName;
}
string user::getPassword()  {
    return password;
}

void user::setUserName(std::string userName) {
    this->userName = userName;
}

void user::setPassword(std::string password) {
    this->password = password;
}


int main(){
    vector<user> userDetails;
    string line;
    string userName;
    string password;

    ifstream readFile("userInfo.txt");

    while(getline(readFile,line))   {
        stringstream iss(line);
        iss >> userName >> password;

        user userInfoDetails(userName,password);
        userDetails.push_back(userInfoDetails);

    }
    readFile.close();

    cout << "Before Deletion" << endl;
    for (int i =0; i<userDetails.size(); i++) {
       cout << userDetails[i].getUserName() << " " << userDetails[i].getPassword() << "\n";
    }
    cout << " " << endl;

    string name;
    cout << "Enter User Name to delete: ";
    cin >> name;
    cout << " " << endl;
    cout << "After Deletion" << endl;
    for (int i =0; i<userDetails.size(); i++) {
       if(userDetails[i].getUserName() == name){
            userDetails.erase(userDetails.begin() + i);
       }
        cout << userDetails[i].getUserName() << " " << userDetails[i].getPassword() << "\n";
    }
}

line 64 needs to be an else statement so the the program doesn't attempt to display an erased item in the vector

    for (int i = 0; i<userDetails.size(); i++) {
        if (userDetails[i].getUserName() == name){
            userDetails.erase(userDetails.begin() + i);
        }
        else
            cout << userDetails[i].getUserName() << " " << userDetails[i].getPassword() << "\n";
    }

Deleting data in vector comes with a lot of work. For your operation, you need to consider list.

Now based on your code , from line 49 to end. i dont personally like how you are dealing with the vector. vector comes with iterator to use to loop through your vector.

on line 60 your if statement must look like this
if(userDetails[i].getUserName()==name){
userDetails.erase(userdetails[i]) ;
userDetails.resize();
}

Vectors limitation is this form or operations so next time plan your tasks very well and think about which libs to use.

A std::list is better suited for that purpose because vector does a lot of memory reallocations during erase while std::list does not.

int main(){

    vector<user> userDetails;
    // string line;
    string userName;
    string password;

    {
        // local scope: we do not want to keep 
        // the stream for longer than necessary
        ifstream readFile("userInfo.txt");

        // while(getline(readFile,line))   {
        // a line consists of just two ws-seperated tokens
        // we can directly read them into userName and password
        while( readFile >> userName >> password )   {
            // stringstream iss(line);
            // iss >> userName >> password;
            // user userInfoDetails(userName,password);

            // using the object anonymously makes for clearer code
            userDetails.push_back( user(userName,password) );
        }
        // readFile.close();
        // the destructor of the stream will close it
    }

    cout << "Before Deletion" << endl;
    for ( /*int*/ std::size_t i =0; i<userDetails.size(); i++) {
       cout << userDetails[i].getUserName() << " " 
            << userDetails[i].getPassword() << "\n";
    }

    cout << " " << endl;
    string name;
    cout << "Enter User Name to delete: ";
    cin >> name;
    cout << " " << endl;

    for (/*int*/ std::size_t i = 0; i<userDetails.size(); /* i++ */ ) {

            if(userDetails[i].getUserName() == name){
                 // userDetails.erase(userDetails.begin() + i);

                 // if we do not need to maintain an ordered sequence
                 // this is the canonical way to remove an element
                 // cheaper than: userDetails.erase(userDetails.begin() + i);
                 std::swap( userDetails[i], userDetails.back() ) ;
                 userDetails.pop_back() ;
                 // break ; // uncomment if there are no duplicated names
            }

            else ++i ; // increment only if the element at i is not erased
                 // if we have erased the element at position i,
                 // a new element has come into that position;
                 // and we want to look at it next
    }

     /*
         // note: if the relative order in the sequence must be maintained,
         // the canonical way is to use the remove-erase idiom
     */

    cout << "After Deletion" << endl;
    for ( std::size_t i =0; i<userDetails.size(); i++) {
       cout << userDetails[i].getUserName() << " " 
            << userDetails[i].getPassword() << "\n";
    }
}
commented: nice solution :) +14

thank you all for your advices and help

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.