【问题标题】:My code isn't overwriting the text file, even though it should be?我的代码没有覆盖文本文件,即使它应该是?
【发布时间】:2015-05-20 17:02:30
【问题描述】:

我们在 C++ 类中编写了非常相似类型的代码,但我的版本无法正常工作,即使它逐行(几乎)相同。

我的代码旨在保存用户的口袋妖怪,他们可以随意添加和删除。我的显示功能正在工作,但我的添加和删除功能却没有。所有文件都在打开,但它并没有像预期的那样覆盖文件。真的不知道该怎么做,我是一个初学者,我知道的不多。

这是我目前得到的:

string name[100];
string type[100];
int level[100];
string newPokemon;
string newType;
int newLevel;
ifstream fin;
ofstream fout;
int numberOfPokemon = 0;
//Input Pokemon Info
cout << "Name of Pokemon: ";
getline(cin, newPokemon);
cin.ignore(100, '\n');
cout << "Pokemon type: ";
getline(cin, newType);
cin.ignore(100, '\n');
cout << "Pokemon level: "; //weird gap between "Pokemon type" and "pokemon level". I have to press enter twice from "pokemon type" to get to "pokemon level"
cin >> newLevel;
cin.ignore(5, '\n');
fin.open("pokemon.txt");
//Put file in array
if (fin.is_open())
{
    while (isalnum(fin.peek()) && numberOfPokemon < 100)
    {
        getline(fin, name[numberOfPokemon]);
        getline(fin, type[numberOfPokemon]);
        fin >> level[numberOfPokemon];
        fin.ignore(100, '\n');
        if (name[numberOfPokemon] != newPokemon)
            numberOfPokemon++;
    }
    fin.close();
}
//Output file
fout.open("pokemon.txt");
if (fout.is_open())
{
    for (int i = 0; i < numberOfPokemon; i++)
    {
        fout << name[i] << "\n";
        fout << type[i] << "\n";
        fout << level[i] << "\n";

    }
    //Tack on new piece
    fout << newPokemon << "\n";
    fout << newType << "\n";
    fout << newLevel << "\n";
    fout.close();
    cout << "Add Successful\n";
}
else
{
    cout << "Add Failure\n";
}

现在是我的删除功能:

string name[100];
string type[100];
int level[100];
int pokemonCount = 0;
string deletedPokemon = "";
bool found = false;

ifstream fin;

cout << "Which Pokemon would you like to delete?" << endl;
getline(cin, deletedPokemon);
cin.ignore(5, '\n');

fin.open("pokemon.txt");
if (fin.is_open())
{
    while (isalnum(fin.peek()))
    {
        getline(fin, name[pokemonCount]);
        getline(fin, type[pokemonCount]);
        fin >> level[pokemonCount];
        fin.clear();
        fin.ignore(100, '\n');
        if (deletedPokemon == name[pokemonCount])
        {
            pokemonCount--;
            found = true;
        }
        pokemonCount++;
    }
    fin.close();
    cout << "ya the file opened" << endl; //always appears
}

ofstream fout;
fout.open("pokemon.txt");
if (fout.is_open())
{
    for (int i = 0; i < pokemonCount; i++)
    {
        fout << name[i] << "\n";
        fout << type[i] << "\n";
        fout << level[i] << endl;
    }
    fout.close();
    cout << "pokemon removed\n";
    cout << "the file opened."; //it is returning that the file opened in both occasions in this function but nothing is happening!
}
else
{
   cout << "removal failure";
   cout << "The file didn't open";
}
return found;

在这个功能的最后(如果我选择删除一个),它会提供“你想添加一个口袋妖怪吗?”但它不会让我输入答案,它只会结束程序。

【问题讨论】:

    标签: c++ text-files overwrite


    【解决方案1】:

    ofstream::open 的默认行为是简单地打开文件进行读写。如果您想覆盖该文件,您需要在调用open 时指定它。

    fout.open("pokemon.txt", ios_base::in|ios_base::out|ios_base::trunc);
    

    【讨论】:

    • 啊当然。我忘记了。好吧,我用该行替换了两个函数中的两个 fout.open,但它仍然返回我试图删除的那个。不过谢谢!
    • @Hannah 你是什么意思删除?我假设您想删除“pokemon.txt”的现有内容并将其替换为open 之后您在循环中所做的任何事情。这段代码应该这样做。
    • 好吧,我正在尝试消除文本文件中的特定记录。例如,在此文件中,它显示名称、类型和级别。当它提示我删除记录时,我输入名称。该程序应该删除该特定条目的名称、类型和级别。即使更改了 fout.open (在添加和删除功能中 - 都应该被覆盖),它仍然不会更改文本文件。你是对的,它应该被覆盖,但由于某种原因,这没有发生。
    【解决方案2】:

    确保您的文件未在属性下标记为只读。

    另外,你的删除功能有一个错误:

    bfound 应该替换为 nDelete pokemon 并且当你写出文件时:

        if (deletedPokemon == name[pokemonCount])
        {
            pokemonCount--;
            found = true;
            nDeleteIndex = i;
        }
    ....
        for (int i = 0; i < pokemonCount; i++)
        {
    
        if(i == nDeleteIndex)
            continue;
        fout << name[i] << "\n";
        fout << type[i] << "\n";
        fout << level[i] << endl;
        }
    

    现在它会重写你所有的口袋妖怪,而不会跳过你要删除的那个!

    另外,如果用户有 155 个口袋妖怪作为完整索引,会发生什么情况。你想使用:

     std::vector<string> names;
     ....
     string szPokemon;
     getline(fin, name[numberOfPokemon]);
     names.push_back(szPokemon);
    

    因此您不再有限制!

    【讨论】:

    • 这是个好主意,但我检查了它,它可以读写。不过还是谢谢。
    • 你能详细说明将 i == nDeletePokemon 放在哪里吗?并在 155 宠物小精灵指数上取得好成绩!我将如何使用 std::vector 名称; ?感谢您的帮助!
    • int nDeleteIndex = -1;跟踪要删除的口袋妖怪。如果在找到 pokemon 后它仍然是 -1,那么我们未能找到 pokemon 并返回。否则,当我们写出文件时,只需在您点击 nDeleteIndex 时跳过口袋妖怪。
    • 好的,所以我在顶部声明了 int nDeleteIndex = -1,并包括了其余部分。它告诉我,我没有在 for 语句之上声明。我应该在哪里申报? @加里凯泽
    • 用名称声明它,使其在完整的功能范围内。同时删除 pokemonCount--;陈述。如果一切都失败,让它为名称写“测试”,从而让你知道它是一个写入错误或一个逻辑错误。
    【解决方案3】:

    这里的代码更简洁,更易于维护,并且无论何时您从口袋妖怪中添加/删除一个字段(闪亮?男性/女性?独特?)您都可以轻松地在 CPokemonObject 内完成,而不必复制粘贴代码 100 次。

    #include "stdafx.h"
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #include <vector>
    
    using namespace std;
    #define POKEMON_FILE "Pokemon.txt"
    
    class CPokemon
    {
    public:
        string szName;
        string szType;
        int nLevel;
        CPokemon() : szName("Pika"), nLevel(10), szType("Lightning")
        {};
    
        void Read(ifstream &file)
        {
            file >> szName;
            file >> szType;
            file >> nLevel;
        };
    
        void Write(ofstream &file)
        {
            file << szName << endl;
            file << szType << endl;
            file << nLevel << endl;
        };
    
        void CreatePokemon()
        {
            //Input Pokemon Info
            cout << "Name of Pokemon: ";
            getline(cin, szName);
            cout << "Pokemon type: ";
            getline(cin, szType);
            cout << "Pokemon level: "; //weird gap between "Pokemon type" and "pokemon level". I have to press enter twice from "pokemon type" to get to "pokemon level"
            cin >> nLevel;
        }
    };
    
    void WritePokemons(vector<CPokemon>& Pokemons)
    {
        ofstream fout;
        fout.open(POKEMON_FILE);
    
        //check the file open
        if (!fout.is_open())
        {
            cout << "removal failure";
            cout << "The file didn't open";
            return;
        }
    
        //Write out all the pokemons
        for (unsigned int i = 0; i < Pokemons.size(); i++)  
            Pokemons[i].Write(fout);
    
        fout.close();
    }
    
    void ReadPokemons(vector<CPokemon>& Pokemons)
    {
        ifstream fin;
        fin.open(POKEMON_FILE);
        if (fin.is_open())
        {
            while (isalnum(fin.peek()))
            {
                CPokemon Pokemon;
                Pokemon.Read(fin);
                Pokemons.push_back(Pokemon);
            }
            fin.close();
            cout << "ya the file opened" << endl; //always appears
        }
    }
    
    bool DeletePokemon()
    {
        vector<CPokemon> Pokemons;
    
        string szPokemonToDelete = "";
        cout << "Which Pokemon would you like to delete?" << endl;
        cin >> szPokemonToDelete;
    
        //Read all pokemons
        ReadPokemons(Pokemons);
    
        ofstream fout;
        fout.open("pokemon.txt");
    
        //check the file open
        if (!fout.is_open())
        {
            cout << "removal failure";
            cout << "The file didn't open";
            return false;
        }
    
        bool bFound = false;
        for (unsigned int i = 0; i < Pokemons.size(); i++)      
        {
            //Skip the pokemon to delete
            if(Pokemons[i].szName == szPokemonToDelete)
            {
                bFound = true; //we found the pokemon to delete
                continue;
            }
    
            Pokemons[i].Write(fout);
        }
    
        fout.close();
    
        return bFound;
    }
    
    void AddPokemon()
    {
        vector<CPokemon> Pokemons;
    
        //Read all pokemons from the file
        ReadPokemons(Pokemons);
    
        //Create the new porkemon
        CPokemon Pokemon;
        Pokemon.CreatePokemon();
    
        //Add the pokemon to the list
        Pokemons.push_back(Pokemon);
    
        //Output file
        WritePokemons(Pokemons);
    }
    

    【讨论】:

    • 天哪,这太棒了!虽然我为我的班级修复了代码,但当我玩 Pokemon X 时,我肯定会使用它!太感谢了!这比我目前所知道的要先进得多,但它会非常有用!谢谢!
    • 没问题,我制作这个小程序的原因是,正如你所看到的,每次你向口袋妖怪添加一个字段并且如果你必须通过口袋妖怪时,单独的读/写很快就会变得难以管理对于任何对象,您都必须传递所有变量。因此,您可以轻松地替换 DrawPokemon(CPokemon &Pokemon),而不是执行 DrawPokemon(string name,string type, string shiny, string age...),也不是pokemon前面的'&',用来让编译器知道使用指针而不是每次都复制整个对象。
    猜你喜欢
    • 1970-01-01
    • 2014-05-06
    • 2010-10-29
    • 2021-12-16
    • 2018-04-25
    • 2017-03-04
    • 2012-06-23
    • 2013-09-30
    • 1970-01-01
    相关资源
    最近更新 更多