12. Acceso aleatorio

12.1. Ejemplo solución acceso aleatorio

Un archivo de texto contiene información de nombre y valor.
El programa permite agregar registros y modificar los valores de registros existentes.

/*
 * manejo aleatorio de archivos
 * 
 * Germán Andrés Xander 2021
 */

#include <iostream>
#include <fstream>
#include <string>

#define ancho1 40
#define ancho2 8

using namespace std;

void agregar(fstream &base_datos);
long int buscar(fstream &base_datos, string nombre);
void modificar(fstream &base_datos, long int posicion);

int main(int argc, char **argv){
    long int posicion=-1;
    char opcion;
    string nombre;
    fstream base_datos("bd.txt", fstream::in | fstream::out);
    do{
        cout<<endl<<endl<<"Ingrese opcion:"<<endl
        		<<"1 agregar"<<endl
        		<<"2 buscar"<<endl
        		<<"3 modificar"<<endl
        		<<"s salir"<<endl;
        cin>>opcion;
        cin.ignore(100, '\n');
        switch (opcion){
            case '1': {
                agregar(base_datos);
                break;
            }
            case '2':{
                cout<<endl<<"Ingrese nombre a buscar: ";
                getline(cin,nombre);
                posicion=buscar(base_datos, nombre);
                if(posicion <0){
                    cout<<endl<<"no se encontró el nombre";
                }else{
                    cout<<endl<<"nombre encontrado en la posición: "<<posicion;
                }
                break;
            }
            case '3':{
                if(posicion>=0){
                    modificar(base_datos,posicion);
                    posicion=-1;
                }else{
                    cout<<endl<<"primero busque un nombre";
                }
                break;
            }
            case 's':{
                base_datos.close();
            }
        }
    }while(opcion!='s');
    return 0;
}

void agregar(fstream &base_datos){
    string nombre;
    string valor;
    cout<<endl<<"Ingrese nombre a agregar: ";
    getline(cin,nombre);
    nombre.resize(ancho1,' ');
    if (buscar(base_datos, nombre)<0){
        cout<<endl<<"Ingrese valor a agregar: ";
        getline(cin,valor);
        valor.resize(ancho2,' ');
        cout<<endl<<"estado error: "<<base_datos.fail();
        base_datos.clear();
        base_datos.seekp(0,ios_base::end);
        base_datos<<endl<<nombre<<valor<<"|";
        base_datos.flush();
    }else{
        cout<<endl<<"ya existe el nombre";
    }
}
    
long int buscar(fstream &base_datos, string nombre){
    string linea;
    base_datos.seekg(0);
    while (getline(base_datos,linea)) {
        if (linea.find(nombre)!= string::npos){
            long int posicion=base_datos.tellp();
            return posicion-ancho1-ancho2-2;
        }
    }
    return -1;
}

void modificar(fstream &base_datos, long int posicion){
    string linea;
    string nombre;
    string valor;
    base_datos.clear();
    base_datos.seekp(posicion);
    cout<<endl<<base_datos.tellp();
    getline(base_datos,linea);
    nombre=linea.substr(0,ancho1);
    cout<<endl<<"Ingrese nuevo valor para  "<<nombre<<": ";
    getline(cin,valor);
    valor.resize(ancho2,' ');
    linea.replace(ancho1,ancho2,valor);
    linea.append("\n");
    cout<<endl<<linea;
    base_datos.seekp(posicion);
    base_datos.write(linea.c_str(), linea.length());
    base_datos.flush();
}