C ++,序列模式下二进制文件的问题

时间:2011-06-02 16:18:34

标签: c++ ios binaryfiles sequential truncation

我对二进制文件有一个相当困难的问题。我被要求制作一个程序,将信息存储在文件中,但是在顺序模式下。由于我不允许直接在顺序模式下修改内容,因此我创建了一个函数,它首先读取文件,直到找到正确的注册表,同时将其他注册表复制到辅助文件中。当我完成修改我需要的东西时,我将其复制到辅助文件并继续复制。完成后,我将所有内容从辅助文件复制到原始文件。我已经做了以下各种二进制文件的例子,但我的程序做了一些奇怪的事情。它开始吃掉我写的所有信息,只留下最后一个条目(类似无限截断的东西),更糟糕的是,有一部分(标记为“讨厌的部分”)开始一个没有意义的无限循环(它是好像文件有无限大小)我已经把这个逻辑变成了一千次,我似乎没有发现任何错误,我不知道你是否可以帮助我,如果我错过了一些重要的东西。

以下是我正在使用的课程

class Cliente{
public:
    int numCuenta;
    char dni[10];
    char nombre[40];
};

class Cuenta{
private:        
    int numCuenta;
    double monto;
    int numDuenhos;

public:
    const static double MONTO_MIN = 100.0;
    Cuenta(){
        numCuenta = 0;
        monto = 0;
        numDuenhos = 0;
    }
    int getnumCuenta(){
        return numCuenta;
    }
    void setnumCuenta(int numCuenta){
        this->numCuenta= numCuenta;
    }
    int getnumDuenhos(){
        return numDuenhos;
    }
    void setnumDuenhos(int numDuenhos){
        this->numDuenhos= numDuenhos;
    }
    double getMonto(){
        return monto;
    }
    void setMonto(double monto){
        this->monto = monto;
    }
};

和有问题的功能

 void modificarCuenta() {
    Cuenta aux;
    Cliente c;
    ifstream rep_cuentas("cuentas.bin");
    ofstream buf_cuentas("cuentas_rep.bin",ios::out | ios::trunc | ios::binary);
    if(!rep_cuentas) {
        cout <<endl << "Error al leer fila principal";
    }
    else if(!buf_cuentas) {
        cout << endl << "Error al abrir el archivo buffer";
    }
    else {
        cout <<endl << "Ingrese el numero de cuenta a modificar: "; //id of entry
        int num_cuenta;
        cin >> num_cuenta;
        ifstream rep_clientes("clientes.bin");
        ofstream buf_clientes("cilentes_rep.bin",ios::out | ios::trunc | ios::binary);
        //este archivo es necesario, por eso termina si no lo lee
        if (!rep_clientes) {
            cerr << "Error al Abrir el Archivo de Clientes" << endl;
            return;
        }
        rep_cuentas.read(reinterpret_cast<char *>(&aux),sizeof(Cuenta));
        while(!rep_cuentas.eof()){
            if(aux.getnumCuenta() == num_cuenta){
                rep_clientes.read(reinterpret_cast<char *>(&c),sizeof(Cliente));
                while(!rep_clientes.eof()){
                    if(c.numCuenta == num_cuenta){
                        cout << "DNI del Cliente: " << c.dni << endl; //old dni
                        cout << "Nombre del Cliente: " << c.nombre << endl; // old name
                        cout << "Modificar estos datos? (1 para confirmar): ";
                        int opc;
                        cin >> opc;
                        if (opc == 1){
                            c.numCuenta = aux.getnumCuenta();
                            cout << endl << "Ingrese nuevo DNI: "; //new dni
                            cin >> c.dni;
                            cout << endl << "Ingrese nuevo Nombre: "; //new name
                            cin >> c.nombre;
                        }
                    }
                    buf_clientes.write(reinterpret_cast<char *>(&c),sizeof(Cliente));
                    rep_clientes.read(reinterpret_cast<char *>(&c),sizeof(Cliente));
                }
                int num = aux.getnumDuenhos();
                while(true){
                    cout << endl << "Desea ingresar mas duenhos? (1 para confirmar): "; //appending new user?
                    int op;
                    cin >> op;
                    if (op == 1){
                        c.numCuenta = aux.getnumCuenta();
                        cout << endl << "Ingrese nuevo DNI: "; //new dni
                        cin >> c.dni;
                        cout << endl << "Ingrese nuevo Nombre: "; //new name
                        cin >> c.nombre;
                        num++;
                        buf_clientes.write(reinterpret_cast<char *>(&c),sizeof(Cliente));                                            
                    }
                    else{ 
                        aux.setnumDuenhos(num);
                        break;
                    }
                }
            }
            buf_cuentas.write(reinterpret_cast<char *>(&aux),sizeof(Cuenta));
            rep_cuentas.read(reinterpret_cast<char *>(&aux),sizeof(Cuenta));
        }
        rep_clientes.close();
        buf_clientes.close();
    }

    rep_cuentas.close();
    buf_cuentas.close();
    ofstream rcuentas("cuentas.bin",ios::out | ios::trunc| ios::binary);
    ifstream bcuentas("cuentas_rep.bin");
    if(!rcuentas) {
        cout << endl << "Error al abrir la fila principal";
    }
    else if(!bcuentas) {
        cout << endl << "Error al abrir el archivo buffer";
    }
    else{
        bcuentas.read(reinterpret_cast<char *>(&aux),sizeof(Cuenta));
        while(!bcuentas.eof()){
            rcuentas.write(reinterpret_cast<char *>(&aux),sizeof(Cuenta));
            bcuentas.read(reinterpret_cast<char *>(&aux),sizeof(Cuenta));
        }
        rcuentas.close();
        bcuentas.close();
        ofstream rclientes("clientes.bin",ios::out | ios::trunc | ios::binary);
        ifstream bclientes("clientes_rep.bin");
        bclientes.read(reinterpret_cast<char *>(&c),sizeof(Cliente));
        //pesky part
        while(!bclientes.eof()){
            rclientes.write(reinterpret_cast<char *>(&c),sizeof(Cliente));
            bclientes.read(reinterpret_cast<char *>(&c),sizeof(Cliente));                                
        }                            
        //end of pesky part
        bclientes.close();
        rclientes.close();
        cout << endl << "Modificacion Realizada con Exito" << endl;  //confirmation text
    }
}

如果你需要它,这是写一个新条目的功能,它完全正常:

void crearCuenta(){
    Cuenta aux;
    aux.setnumCuenta(0);
    ifstream rcuentas("cuentas.bin");
    if(!rcuentas){
        cout<< endl <<"Primer uso del Sistema detectado, generando numero de cuenta inicial" <<endl;
    }
    else {
        rcuentas.read(reinterpret_cast<char *>(&aux),sizeof(Cuenta));
        while(!rcuentas.eof()){
            rcuentas.read(reinterpret_cast<char *>(&aux),sizeof(Cuenta));
        }
        rcuentas.close();
    }
    Cuenta cu;         
    cu.setnumCuenta(aux.getnumCuenta() + 1);
    int num_duenhos = 0;
    ofstream a_clientes("clientes.bin",ios::app |ios::binary);
    while(true){
        char dni[10];
        cout << "Ingrese el DNI del Duenho: "; //new dni
        Cliente c;
        cin >> c.dni;
        cout << "Ingrese el Nombre del Duenho: "; //new name
        cin >> c.nombre;
        c.numCuenta = cu.getnumCuenta();
        num_duenhos++;
        a_clientes.write(reinterpret_cast<char *>(&c),sizeof(Cliente));
        cout << "Desea ingresar otro duenho? (escriba 1 para confirmar): "; //another entry?
        int val;
        cin >> val;
        if (val != 1)
            break;
    }
    cu.setnumDuenhos(num_duenhos);
    while(true){
        double monto;
        cout << endl;
        cout << "Ingrese el monto con el cual iniciara la cuenta:"; //numerical value (greater than 100)
        cin >> monto;
        if (monto < Cuenta:: MONTO_MIN){
            cout << "Debe ingresar un valor mayor a " << Cuenta::MONTO_MIN << endl;
        }
        else{
            cu.setMonto(monto - monto * 0.005);
            break;
        }
    }
    ofstream acuentas("cuentas.bin",ios::app| ios::binary);
    if(!acuentas){
        cout<< endl <<"ERROR en la fila secuencial" <<endl;
    }
    else{
        acuentas.write(reinterpret_cast<char *>(&cu),sizeof(Cuenta));
        acuentas.close();
    }
    cout << "Cuenta Guardada Satisfactoriamente con número: " << cu.getnumCuenta() << endl;  //confirmation text
}

不介意西班牙语文本,它只是用于用户交流。任何帮助将受到高度赞赏

1 个答案:

答案 0 :(得分:2)

对于初学者,你不是以二进制模式打开输入,所以除非 你在Unix下,你不会在磁盘上看到文件的字节图像。 如果我理解正确,您希望阅读您的文件 用同一个程序写的;如果是这样,阅读和写作不同 模式不起作用。

其次,您正在阅读和编写复杂的数据结构(CuentaCliente}使用istream::readostream::write。事实并非如此 工作,除了少数情况。无论是二进制还是文本,所有文件 有一种格式,这种格式必须在代码中得到尊重。您的 类是POD,或者足够接近一个,你可能不会 在您的开发中进行一些更改之前,请先查看问题 环境,但它仍然存在。 (事实上​​你需要一个 reinterpret_cast这样做应该是一个红旗。)它绝对不会起作用 (在Unix下除外)如果您以文本模式读取或写入。读一个文件 以这种方式在文本模式下写入将返回其他字符,或停止 在文件结束之前,在Windows下。

此外,while ( file.eof() ) 是读取文件的正确方法。该 file.eof()的结果在输入之后才是可靠的 失败。对于文本文件,通常使用:

while ( file >> something ) ...

while ( std::getline( file, line ) ) ...

像你一样阅读,

while ( rep_clentes.read(...) ) ...
如果您解决了其他问题,

应该可行。 这可能是你无限循环的原因; istream在。{ 由于某种原因而不是文件结尾的错误状态,因此eof()会 永远不会成真。