0

我对二进制文件有一个相当困难的问题。我被要求制作一个程序,将信息存储在文件中,但以顺序模式。由于不允许我直接在顺序模式下修改内容,我创建了一个函数,首先读取文件直到找到正确的注册表,同时将其他注册表复制到辅助文件中。当我完成我需要的修改后,我将它复制到辅助文件并继续复制。完成后,我将辅助文件中的所有内容复制到原始文件中。我在各种二进制文件示例之后做了这个,但是我的程序做了一些奇怪的事情。它开始吃掉我写的所有信息,只留下最后一个条目(有点像无限截断),更糟糕的是,还有一部分(标记为“讨厌的部分”

这是我正在使用的课程

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
}

不要介意西班牙语文本,它只是用于用户交流。任何帮助将不胜感激

4

1 回答 1

2

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

其次,您正在使用and读写复杂的数据结构 ( Cuenta, Cliente) 。这不起作用,除非在极少数情况下。无论是二进制还是文本,所有文件都有一种格式,并且在代码中必须尊重这种格式。您的类要么是 POD,要么非常接近于一个,在您对开发环境进行一些更改之前,您可能不会发现问题,但它仍然存在。(你需要这样做的事实在 这里应该是一个危险信号。)如果你在文本模式下阅读或写作,它肯定不起作用(在 Unix 下除外)。在 Windows 下,以文本模式读取以这种方式编写的文件将返回额外的字符,或在文件结尾之前停止。istream::readostream::writereinterpret_cast

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

while ( file >> something ) ...

或者

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

像你一样阅读,

while ( rep_clentes.read(...) ) ...

应该可以工作,只要您解决其余的问题。这可能是您无限循环的原因;由于istream文件结尾以外的某种原因处于错误状态,因此eof()永远不会成为真的。

于 2011-06-02T17:27:36.440 回答