【问题标题】:Reading and writing to .dat file读取和写入 .dat 文件
【发布时间】:2012-12-06 19:50:52
【问题描述】:

为什么这个文件总是包含一个额外的Fraction 结构?如果用户在程序刚启动时输入选项 3 来查看所有分数(文件应该为空),则打印出0/0。如果用户选择选项一并输入一个分数1/1,然后选择选项3,则会打印出两个分数1/1 1/1

注意:要运行它,您需要创建一个名为 "fractions.dat" 的空 .dat 文件

非常感谢您的帮助!

#include <iostream>
#include <fstream>

using namespace std;

struct Fraction
{
    int num, den;
};

int search(fstream& file, Fraction* f);
int menu();
void proccessChoice(int i);
Fraction* readFrac();

Fraction* fracs[100];
int index;
string fileName = "fractions.dat";
fstream file(fileName,  ios::in | ios::out | ios::binary | ios::trunc);

//structure called Fraction with num and den as its only integer members
int main()
{
    if (!file)
    {
        cout << "Error opening file. Program aborting.\n";
        system("pause");
        exit(1);
    }
    int choice;
    do
    {
        choice = menu();
        proccessChoice(choice);
    } while(choice != 4);


    system("pause");
    return 0;
}



int menu()
{
    int c;
    cout << "1.Enter new fraction" << endl;
    cout << "2.Display/update a fraction" << endl;
    cout << "3.Display all fractions" << endl;
    cout << "4.Quit" << endl;
    cin >> c;
    return c;
}

void proccessChoice(int i)
{
    switch(i)
    {
    case 1:
        {
            cout << "Enter a fraction to add: ";
            fracs[index] = readFrac();
            file.seekp(0, ios::end);
            file.write(reinterpret_cast<char*>(fracs[index]), sizeof(Fraction));
            /*cout << fracs[index]->num << "/" << fracs[index]->den ;*/
            index++;
        }
            break;
    case 2:
        {
            cout << "Enter fraction to view/update: ";
            Fraction* fToFind = readFrac();
            int i = search(file, fToFind);
            if (i == -1)
            {
                cout << "Fraction not found." << endl;
            }
            else
            {
                char r;
                cout << fToFind->num << "/" << fToFind->den << " found at index " << i << ". Update? [y/n]";
                cin >> r;
                if(r == 'y' || r == 'Y')
                {
                    cout << "Enter a new fraction: ";
                    Fraction* fToWrite = readFrac();
                    file.seekp(sizeof(Fraction) * (i));
                    file.write(reinterpret_cast<char*>(fToWrite), sizeof(Fraction));
                }
            }
            cout << i << endl;
            cout << "Case 2" << endl;
        }
            break;
    case 3:
        {
            Fraction* cur = new Fraction();
            //int pos = -1;
            if (!file)
            {
                cout << "Error opening file. Program aborting.\n";
                system("pause");
                exit(1);
            }
            file.seekg(0, ios::beg);
            while(!file.eof())
            {
                file.read(reinterpret_cast<char *>(cur), sizeof(Fraction));
                cout << cur->num << "/" << cur->den << endl;
            }
                    cout << "Case 3" << endl;
        }
            break;
    }
}

int search(fstream& file, Fraction* f)
{
    Fraction* cur = new Fraction();
    int pos = -1;
    if (!file)
    {
        cout << "Error opening file. Program aborting.\n";
        system("pause");
        exit(1);
    }
    file.seekg(0, ios::beg);
    while(!file.eof())
    {
        file.read(reinterpret_cast<char *>(cur), sizeof(Fraction));
        if((cur->num == f->num) && (cur->den == f->den))
        {
            cout << "\nFrac found!" << cur->num << "/" << cur->den<<endl;
            pos = file.tellg()/sizeof(Fraction) - 1;
            return pos;
        }
    }
    return pos;
}

Fraction* readFrac()
{
    Fraction* f = new Fraction();
    char slash;
    cin >> f->num >> slash >> f->den;
    return f;
}

尝试的解决方案 1:适用于用户第一次尝试查看所有分数,但在第二次尝试时找不到文件。

case 3:
        {
            Fraction* cur = new Fraction();
            //int pos = -1;
            if (!file)
            {
                cout << "Error opening file. Program aborting.\n";
                system("pause");
                exit(1);
            }
            file.seekg(0, ios::beg);
            while(!file.eof())
            {
                if(file.read(reinterpret_cast<char *>(cur), sizeof(Fraction)).gcount()== sizeof(Fraction))
                {
                    cout << cur->num << "/" << cur->den << endl;
                }
            }
                    cout << "Case 3" << endl;
        }
            break;
    }

【问题讨论】:

    标签: c++ io fstream


    【解决方案1】:

    因为你还没有到达文件的末尾!

    while(!file.eof())
    

    您打开了空文件,但是请注意,读取光标当前位于位置0。只要您没有尝试读取数据file.eof() 就会为假,因为光标尚未到达文件末尾。

    您需要检查您是否真的能够提取分数:

    if(
       file.read(reinterpret_cast<char *>(cur), sizeof(Fraction)).gcount() 
       == sizeof(Fraction)
    ){
         // Fraction has been extracted
    }
    else
         // either eof() or some other error.
    

    请注意,如果您为此提供自定义运算符,这将变得更加简单:

    std::istream& operator>>(std:istream& in, Fraction& f){
        return in.read(reinterpret_cast<char *>(&f), sizeof(Fraction));
    }
    
    // ....
    while(file >> *cur){
       // ... your code.
    }
    

    【讨论】:

    • 我尝试了您的第一个建议。它非常适合第一次执行选项 3,但如果用户再次选择选项 3,则找不到文件(请参阅问题更新)。
    • 第二种解决方案给出以下错误: 错误 1 ​​错误 C2678: binary '>>' : no operator found which take a left-hand operand of type 'std::fstream' (或者没有可接受的转换)
    • @Azzi:嗯,文件已经找到了。但是,它处于错误状态,这会将!file 评估为真。如果您想知道文件是否被打开,您应该使用.is_open()。请记住,您需要使用 .clear() 来清除旧的错误状态。
    • @Azzi:在第二个解决方案中出现了复制粘贴错误。应该是 std::istream 而不是……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-06
    相关资源
    最近更新 更多