c ++从文本文件中删除行(需要解释)

时间:2014-01-04 17:09:11

标签: c++

我正在尝试从文本文件中删除包含用户名和密码的行。 所以我试着跟着,

1)阅读文本文件。

2)将userName和密码存储在文本文件中。

3)提示用户要删除哪个用户。

4)如果输入与向量中的用户名匹配,则整个行将在向量中删除。

5)复制回文本文件(尚未完成)

我设法通过运气得到它     的文本文件(userInfo.txt)

amber abc
janet def
chris DEF
gerald AZC

我的代码输出

Before Deletion
amber abc
janet def
chris DEF
gerald AZC

Enter User Name to delete: amber

After Deletion
janet def
chris DEF
gerald AZC

但我真正理解的是,我的代码在与我的输入匹配之后实际上删除了整行,特别是从

开始
    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";
    } 

我希望有人可以向我解释。

我的代码

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";
    }
}

3 个答案:

答案 0 :(得分:1)

我不确定我理解你不明白但我会尽力帮助......

您删除了正确位置的行 您为erase方法提供了一个指向要删除的元素的迭代器 执行此操作时,下一行获取已删除行的索引并打印它(前一个下一行,现在是索引i中的行)。

答案 1 :(得分:1)

这是因为

userDetails.erase(userDetails.begin() + i);

删除包含用户名和密码的用户。

答案 2 :(得分:1)

我不遵循你不理解的内容。但是,我将讨论这段代码,因为它包含一个对初学者来说很常见的严重错误。

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";
}

这个“有效”的原因是当你的程序遇到一个对象,该对象的用户名与输入的用户名相匹配时,你会从向量中删除它。当发生这种情况时,矢量中“擦拭对象的更右侧”的每个对象的索引向下移动一个。因此,假设匹配的名称是“琥珀色”(索引0)。在第一次循环迭代中,将删除琥珀色; janet转移到指数0;克里斯转向指数1;并且gerald转移到索引2.仍然在第一次循环迭代,它将输出索引0,现在是克里斯所以一切都很好。在所有剩余的循环迭代中,userDetails.size()将评估为新的删除后大小3,因此对于索引0,1,2,您将只获得3次迭代。

现在为BUG:尝试输入“gerald”作为要删除的名称。

如果你这样做,请记住,当i为3时,它将在循环的第四次迭代中得到处理。杰拉德将被删除,将大小减小到3,最后一个有效索引减少到2.但是此时i仍为3!所以

cout << userDetails[i].getUserName() << " " << userDetails[i].getPassword() << "\n";
第四次迭代的

相当于:

cout << userDetails[3].getUserName() << " " << userDetails[3].getPassword() << "\n";

但没有userDetails[3],您的程序应该是段错误。

以下是如何正确实施它:

for (int i =0; i<userDetails.size(); i++) {
   if(userDetails[i].getUserName() == name){
        userDetails.erase(userDetails.begin() + i);
        continue; // skip to next iteration because we can't guarantee 'i' is a valid
                  // index or that username on this iteration doesn't match
   }
    cout << userDetails[i].getUserName() << " " << userDetails[i].getPassword() << "\n";
}

但是,我更喜欢以下习语:

auto i = userDetails.begin(), e = userDetails.end();
while (i != e)
{
    if (name == i->getUserName())
    {
        i = userDetails.erase(i); // i is now equal to next element after deleted one
        e = userDetails.end();    // update e to be equal to the new end
        // don't output because we deleted
    }
    else
    {
        std::cout << i->getUserName() << ' ' << i->getPassword() << std::endl;
        ++i;
    }
}