删除元素后列表的最终元素已损坏

时间:2014-12-26 05:51:03

标签: c++ list fstream ofstream

我有一个奇怪的问题。我正在编写一个函数来从其他地方创建的名称列表中删除一行,经过一些研究,它似乎应该相当简单。我将当前的名称列表写入列表,显示列表,让用户输入要删除的名称,从列表中删除用户输入的名称,然后将更新的列表显示给用户。

到目前为止,一切都运行良好,但是当我将列表写回文件时,姓氏会随机删除一些字符,从几个字符到整行。现在,这就是它变得奇怪的地方。如果我打开文件并在不退出程序的情况下查看它,文件的最后一行就会搞砸,并且只要我稍后在程序中显示它就会继续。但是,如果我退出程序然后打开文件,最后一行将回到原来的编写方式!在写入列表后,程序不会再写入该文件,因此我无法想象为什么会发生这种情况。

我几乎已经决定,由于文件最终来自程序正确,我可以忽略该问题,但我希望用户能够在删除后查看名称列表,原因有多种,这是不可能的而最后一个列表项打印不正确。

我仍然是C ++的初学者,所以我有点希望这只是我没有完全理解列表或其他东西的问题。无论如何,愚蠢的解释将是王牌。

我在下面添加了这个功能,非常感谢任何帮助。

char act, charname[50];
string namestr;
list <string> c1;
list <string>::iterator c1_Iter;

//write the names from the file into a list
ifstream names("List of Names.txt");
while (std::getline(names, namestr))
{
    c1.push_back(namestr);
}

//print the current names
cout << "Registered names:";
for (c1_Iter = c1.begin(); c1_Iter != c1.end(); c1_Iter++)
    cout << "\n" << setw(5) << " " << *c1_Iter;

//choose which names to delete and confirm
cout << "\n\nEnter the name you would like to delete: ";
cin.getline(charname, 50);
cin.getline(charname, 50);
cout << "\nAre you sure? Enter 'y' to permanently delete " << charname << ", and any other key to return to the start screen.";
cin >> act;

if (act == 'y' || act == 'Y')
{
    //delete a file associated with each name
    string strname(charname);
    strname.append(".txt");
    if (remove(strname.c_str()) < 0)
        perror("Error deleting file");

    else
    {
        //delete name from the file only if that person's individual file is successfully deleted
        c1.remove(charname);
        cout << "\n" << charname << " successfully deleted!\n";

        //print the updated list of names
        cout << "\nUpdated list of registered names:\n";
        for (c1_Iter = c1.begin(); c1_Iter != c1.end(); c1_Iter++)
            cout << *c1_Iter << endl;

        //write updated list of names over "List of Names" to update the file
        ofstream newNames("List of Names.txt");
        for (c1_Iter = c1.begin(); c1_Iter != c1.end(); c1_Iter++)
            newNames << *c1_Iter << endl;
        newNames.close();
    }
}

1 个答案:

答案 0 :(得分:3)

正如Mohit Jain在评论中提到的那样,您需要在names.close()上致电ifstream,然后再打开文件作为单独的ofstream进行书写。此外,您可以使用std::string charname而不是char charname[50]

您还可以使用fstream进行适当的搜索。如果我没有弄错,那么处理同一文件的活动ifstreamofstream对象会导致未定义的行为。

这是一个更加C ++友好的解决方案:

#include <iostream>
#include <string>
#include <fstream>
#include <list>
#include <iomanip>

int main()
{
    char act;
    std::string charname;
    std::string namestr;
    std::list<std::string> c1;
    std::list<std::string>::iterator c1_Iter;

    //write the names from the file into a list
    std::ifstream names("names.txt");
    while (std::getline(names, namestr))
    {
        c1.push_back(namestr);
    }

    //print the current names
    std::cout << "Registered names:";
    for (c1_Iter = c1.begin(); c1_Iter != c1.end(); c1_Iter++)
        std::cout << "\n" << std::setw(5) << " " << *c1_Iter;

    //choose which names to delete and confirm
    std::cout << "\n\nEnter the name you would like to delete: ";
    std::cin >> charname;
    std::cout << "\nAre you sure? Enter 'y' to permanently delete " << charname << ", and any other key to return to the start screen.";
    std::cin >> act;

    if (act == 'y' || act == 'Y')
    {
        //delete a file associated with each name
        std::string strname(charname);
        strname.append(".txt");
        if (remove(strname.c_str()) < 0)
        {
            std::cerr << "Error deleting file " << strname << std::endl;
            return 1;
        }
        else
        {
            //delete name from the file only if that person's individual file is successfully deleted
            c1.remove(charname);
            std::cout << "\n" << charname << " successfully deleted!\n";

            //print the updated list of names
            std::cout << "\nUpdated list of registered names:\n";
            for (c1_Iter = c1.begin(); c1_Iter != c1.end(); c1_Iter++)
                std::cout << *c1_Iter << std::endl;

            //write updated list of names over "List of Names" to update the file
            names.close(); //Close the ifstream before opening the file for editing
            std::ofstream newNames("names.txt");
            for (c1_Iter = c1.begin(); c1_Iter != c1.end(); c1_Iter++)
                newNames << *c1_Iter << std::endl;
            newNames.close();
        }
    }

    return 0;
}