Ir ao conteúdo
  • Cadastre-se
Vinicius schmitz

C++ RESOLVIDO Substituir dados em arquivo binário (c++)

Posts recomendados

Olá pessoal, estou com uma dúvida em um código em c++ que consiste em substituir o 2° conjunto de dados de um arquivo binário, a estrutura dele deve ser assim, exemplo:

vinicius

20

1.80

 

Luan

17

1.65

 

Sendo uma string para o nome, um tipo inteiro para a idade, e um tipo float pra. Eu quero substituir o segundo conjunto ali (luan    17     1.65) por esse pré estabelecido (Maria    15    1.55) mas não consigo fazer isso, quando uso o fwrite para escrever por cima no arquivo n dá em nada. Isso deve ser feito na função substituir. Segue o Código:

 

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


using namespace std;

void criar_arq2(char nome_arq[])
{
    FILE *parq = fopen(nome_arq,"wb");
    char nome[20];
    int idade;
    float altura;
    if (parq == NULL)
        printf("Erro ao abrir arquivo!!!\n\n");
    else
    {
        int r = 1;
        do
        {
            printf("\nDigite nome, idade e altura: ");
            scanf("%s %i %f",nome, &idade, &altura);
            fwrite(&nome,sizeof(nome),1,parq);
            fwrite(&idade,sizeof(idade),1,parq);
            fwrite(&altura,sizeof(altura),1,parq);
            printf("\nDigite zero para parar: ");
            scanf("%i", &r);
        }
        while(r);
        fclose(parq);
    }
}

void ler_arq_2(char nome_arq[])
{
    FILE *parq = fopen(nome_arq,"rb");
    rewind(parq);
    char nome[20];
    int idade;
    float altura;
    if (parq == NULL)
        printf("Erro ao abrir arquivo!!!\n\n");
    else
    {
        while (fread(&nome,sizeof(nome),1,parq))
        {
            fread(&idade,sizeof(idade),1,parq);
            fread(&altura,sizeof(altura),1,parq);
            printf("nome : %s\n",nome);
            printf("idade : %d\n",idade);
            printf("altura: %.2f\n",altura);
        }
        fclose(parq);
    }
}

//27


void substituir_arq2(char nome_arq[])
{
    FILE *parq = fopen(nome_arq,"a+b");
    char nome2[10] = "Maria";
    int  idade2 = 15;
    float alt2 = 1.55;
    fseek(parq,18,SEEK_SET);
    int aux=ftell(parq);
    fwrite(&nome2,sizeof(nome2),1,parq);
    fwrite(&idade2,sizeof(idade2),1,parq);
    fwrite(&alt2,sizeof(alt2),1,parq);
    ler_arq_2(nome_arq);
    fclose(parq);

}


int main()
{
    cout << "Exercício criar o arquivo:\n\n\n" << endl;
    cout<<"Digite o nome do arquivo:\n\n";
    char arq[20];
    cin>>arq;
    criar_arq2(arq);
    ler_arq_2(arq);
    substituir_arq2(arq);
    return 0;
}

 

main.cpp.txt

  • Amei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Vinicius schmitz    arquivo binário vai bem com struct ,   então é melhor , no início do programa ,  pegar os dados que estão no arquivo , e coloca-los na struct , e assim durante o decorrer do programa você insere , lista , edita e remove algum dado na própria struct , e no final na hora que for sair salva tudo que está na struct naquele momento .

  • Obrigado 1
  • Amei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Seu programa não está bom.

 

Do modo como escreveu é muito difícil de testar. Lerdo e chato.

E é praticamente um programa em C. Use C++. É mais fácil.

 

Objetivamente em relação ao seu programa:

  • Ao ler o arquivo qual o propósito de chamar rewind() para um arquivo de acabou de abrir? Não vai fazer nada.
  • Ao regravar o arquivo, em main(), não acha que devia chamar ler() de novo? Assim, digamos, mostraria de uma vez se gravou ou não?
  • Não seria melhor espaçar a impressão dos registros e colocar um prompt avisando o que o programa está fazendo?
  • Está usando um tamanho diferente na definição de nome na regravação. 10 e não 20.
  • Não devia abrir o arquivo em append mode. Use "r+"e ele já fica posicionado no início....

Use C++. Defina uma struct ou class fora do programa. Se tivesse feito isso não teria errado o tamanho no substituir_Arq() por exemplo...

adicionado 2 minutos depois

A nota sobre o append mode se refere ao método substituir_arq2() onde usou "a+b". Pode usar apenas "r+"

  • Curtir 1
  • Amei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@arfneto

10 horas atrás, arfneto disse:

Seu programa não está bom.

 

Do modo como escreveu é muito difícil de testar. Lerdo e chato.

E é praticamente um programa em C. Use C++. É mais fácil.

 

Objetivamente em relação ao seu programa:

  • Ao ler o arquivo qual o propósito de chamar rewind() para um arquivo de acabou de abrir? Não vai fazer nada.
  • Ao regravar o arquivo, em main(), não acha que devia chamar ler() de novo? Assim, digamos, mostraria de uma vez se gravou ou não?
  • Não seria melhor espaçar a impressão dos registros e colocar um prompt avisando o que o programa está fazendo?
  • Está usando um tamanho diferente na definição de nome na regravação. 10 e não 20.
  • Não devia abrir o arquivo em append mode. Use "r+"e ele já fica posicionado no início....

Use C++. Defina uma struct ou class fora do programa. Se tivesse feito isso não teria errado o tamanho no substituir_Arq() por exemplo...

adicionado 2 minutos depois

A nota sobre o append mode se refere ao método substituir_arq2() onde usou "a+b". Pode usar apenas "r+"

@arfneto Oi, então o rewind foi inútil mesmo, eu coloquei só pra fzr uns testes, e esqueci de deletar. Arrumei o código, coloquei o ler_arquivo() no main(), porque se eu só deixasse na função substituir ele lia o arquivo original certo? porque o resultado na tela saia o mesmo de antes. No caso de espaçar a impressão dos registros acabei não o fazendo mas sim, seria melhor, e realmente não sei como colocar um prompt de comando como disse. Era esse o problema provavelmente, mudei isso e agora deu certo como eu queria. E do append mode foi a mesmo coisa do rewind(), eu tava tentando solucionar na louca, e mudei pra "a+b" no modo de abertura hehe. Muito Obrigado pela ajuda!!

adicionado 2 minutos depois
10 horas atrás, devair1010 disse:

@Vinicius schmitz    arquivo binário vai bem com struct ,   então é melhor , no início do programa ,  pegar os dados que estão no arquivo , e coloca-los na struct , e assim durante o decorrer do programa você insere , lista , edita e remove algum dado na própria struct , e no final na hora que for sair salva tudo que está na struct naquele momento .

@devair1010 Sim, vendo uns vídeos pra tentar solucionar o problema percebi isso, mas esse exercício era só pra substituir o segundo conjunto de dados por outro, então nem fiz usando struct. Obrigado pela dica!!

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
1 hora atrás, Vinicius schmitz disse:

Está usando um tamanho diferente na definição de nome na regravação. 10 e não 20.

 

imagino que corrigiu isso certo @Vinicius schmitz ? Poste o programa. 

 

Entendeu que escreveu um programa em C, certo?

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@herbertbahia @herbertbahia

@arfneto

2 horas atrás, arfneto disse:

 

imagino que corrigiu isso certo @Vinicius schmitz ? Poste o programa. 

 

Entendeu que escreveu um programa em C, certo?

Sim, sei poucas diferenças entre c e c++, daí vou fznd meio q misturado kk. Mudei bem pouca coisa no código, só para corrigir aquilo, que não estava substituindo corretamente o 2° conjunto de dados, segue o código:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


using namespace std;

void criar_arq2(char nome_arq[])
{
    FILE *parq = fopen(nome_arq,"wb");
    char nome[20];
    int idade;
    float altura;
    if (parq == NULL)
        printf("Erro ao abrir arquivo!!!\n\n");
    else
    {
        int r = 1;
        do
        {
            printf("\nDigite nome, idade e altura: ");
            scanf("%s %i %f",nome, &idade, &altura);
            fwrite(&nome,sizeof(nome),1,parq);
            fwrite(&idade,sizeof(idade),1,parq);
            fwrite(&altura,sizeof(altura),1,parq);
            printf("\nDigite zero para parar: ");
            scanf("%i", &r);
        }
        while(r);
        fclose(parq);
    }
}

void ler_arq_2(char nome_arq[])
{
    FILE *parq = fopen(nome_arq,"rb");
    char nome[20];
    int idade;
    float altura;
    if (parq == NULL)
        printf("Erro ao abrir arquivo!!!\n\n");
    else
    {
        while (fread(&nome,sizeof(nome),1,parq))
        {
            fread(&idade,sizeof(idade),1,parq);
            fread(&altura,sizeof(altura),1,parq);
            printf("nome : %s\n",nome);
            printf("idade : %d\n",idade);
            printf("altura: %.2f\n",altura);
        }
        fclose(parq);
    }
}




void substituir_arq2(char nome_arq[])
{
    FILE *parq = fopen(nome_arq,"r+b");
    char nome2[20] = "Maria";
    int  idade2 = 15;
    float alt2 = 1.55;
    fseek(parq,28,SEEK_SET);      //Aqui o fseek pula para onde seria na teoria a 4° linha do arquivo, onde começa o 2° conjunto de dados, assim para substitui-lo por Maria    15     1.55
    fwrite(&nome2,sizeof(nome2),1,parq);
    fwrite(&idade2,sizeof(idade2),1,parq);
    fwrite(&alt2,sizeof(alt2),1,parq);
    fclose(parq);

}


int main()
{
    cout << "Exercício criar o arquivo:\n\n\n" << endl;
    cout<<"Digite o nome do arquivo:\n\n";
    char arq[20];
    cin>>arq;
    criar_arq2(arq);
    ler_arq_2(arq);
    substituir_arq2(arq);
    cout<<"\n\n\n";
    ler_arq_2(arq);
    return 0;
}

 

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então alterou o  [10] para [20]. Muito bem. Era essencial porque iria corromper o nome, como deve ter visto.

 

Sobre as diferenças, digitando em cima de seu programa vou postar um programa em C++ que faz isso. No fundo é o seu programa com as correções que incluiu, e usando a outra linguagem. Pode ser útil a outros já que tem o programa em C acima.

 

As diferenças em um EXEMPLO
 

Em C++ é muito mais fácil criar modelos de coisas. O cara que escreveu tinha isso como objetivo maior o que ele chamava de "abstrações de custo zero". Nos '80. E acho que conseguiu.
 

Uma classe Registros
 

image.png.8e75fd1e47e7c492f3e2edd271787dde.png

 

Tem maneiras mais C++ de escrever isso :D e o trocadilho foi de propósito. Mas não quero gastar muito tempo e quero manter a familiaridade com o seu programa para ficar clara a vantagem de escrever assim

 

Veja o tal polimorfismo por exemplo: eu posso criar registros especificando o nome do arquivo ou não. Nesse caso o programa usa "arquivos.txt" como padrão. E dentro dos registros tem uma estrutura registro que contem os campos de dados e assim eu posso tratar como unidade sem ter que especificar um a um.

 

Veja que as funções cria() e le() e troca_o_segundo() fazem parte de registros e não ficam soltas pelo programa, e faz sentido porque elas só tem a ver com os registros. São chamadas métodos. E os métodos ficam encapsulados nas classes

 

E cada ocorrência de registros --- são chamadas instâncias ---  tem seu nome_de_arquivo e seu contador de registros total. Ao declarar uma variável como sendo do tipo registros o sistema chama uma função com esse nome, a tal registros(). E você pode criar várias com o mesmo nome apenas mudando o tipo ou o número de argumentos. E só com isso já dá pra fazer muita coisa.
 

A função main em C++

    registros um;
    if (um.total <= 0) return -1; // nao leu nada
    cout << "\nlendo os caras" << endl;
    um.le();
    cout << "\nregrava o segundo" << endl;
    um.troca_o_segundo();
    cout << "\nle de novo" << endl;
    um.le();

Veja que declarar a variável um como registro vai fazer com que o programa crie o arquivo. Veja a diferença:

    registros um;
    registros outro("outro.txt");
    registros dois("maisum.txt");

No caso do primeiro vai usar o padrão "arquivos.txt" e nos outros vai usar o nome especificado.

 

E como registros tem um campo total que é atualizado ao criar cada arquivo tudo fica mais simples. um.le() sabe qual arquivo vai abrir, assim como outro.le() e dois.le() e não é preciso mudar nada no programa para tratar múltiplos arquivos, já que são múltiplas classes. struct e classe é a mesma coisa nesse exemplo.
 

Cada ocorrência de registros --- se chama instância --- tem um campo nome_do_arquivo que indica qual o arquivo a ser usado. Está encapsulado.

 

O "método" cria()

    int cria(const char* nome_do_arquivo)
    {
        int N = 0;
        registro rec;
        ofstream arquivo(nome_do_arquivo, ios::out | ios::binary);
        if (!arquivo)
        {
            cout << "Erro ao abrir " <<
                string(nome_do_arquivo) <<
                "!!!\n\n" << endl;
            exit(-1);
        };
        string nome;
        cout << "\n[Tecle 0 para encerrar] Nome: " << flush;
        cin >> nome;
        while (nome != "0")
        {
            N += 1;
            strncpy(rec.nome, nome.c_str(), 20);
            cout << "Nome: " << string(rec.nome) << endl;
            cout << "Idade: " << flush;
            cin >> rec.idade;
            cout << "Altura: " << flush;
            cin >> rec.altura;
            arquivo.write((char*)&rec, sizeof(rec));
            cout << "\n[Tecle ENTER para encerrar] Nome: " << flush;
            cin >> nome;
        };  // while()
        arquivo.close();
        return N;   // retorna quantos leu
    };  // cria()

Em C++ você pode usar write() close(0 e read() para manipular o arquivo. 

 

troca_o_segundo() em C++

    int troca_o_segundo()
    {
        registro rec{ "Maria", 15, 1.55f };
        int N = sizeof(registro);
        int lidos = 0;
        ofstream arquivo(nome_do_arquivo, ios::in | ios::out);
        if (!arquivo)
        {
            cout << "Erro ao abrir " <<
                string(nome_do_arquivo) <<
                "!!!\n\n" << endl;
            return 0;
        };
        arquivo.seekp(N);
        arquivo.write((char*)&rec, sizeof(rec));
        arquivo.close();
        return 0;
    };  // troca_o_segundo()

É bem simples. Note que o seek é feito em unidades de N que é o tamanho do registro. Então se você mudar o registro para incluir campos não precisa mexer nessas coisas aqui.


Esse programa de teste mostra
 


[Tecle 0 para encerrar] Nome: Ana
Nome: Ana
Idade: 12
Altura: 1.5

[Tecle ENTER para encerrar] Nome: Bia
Nome: Bia
Idade: 13
Altura: 1.5

[Tecle ENTER para encerrar] Nome: Cris
Nome: Cris
Idade: 12
Altura: 1.5

[Tecle ENTER para encerrar] Nome: 0

lendo os caras
Registro: [ Nome: Ana, idade: 12,  Altura: 1.5 ]
Registro: [ Nome: Bia, idade: 13,  Altura: 1.5 ]
Registro: [ Nome: Cris, idade: 12,  Altura: 1.5 ]

regrava o segundo

le de novo
Registro: [ Nome: Ana, idade: 12,  Altura: 1.5 ]
Registro: [ Nome: Maria, idade: 15,  Altura: 1.55 ]
Registro: [ Nome: Cris, idade: 12,  Altura: 1.5 ]

[Tecle 0 para encerrar] Nome: Jhonny
Nome: Jhonny
Idade: 65
Altura: 1.85

[Tecle ENTER para encerrar] Nome: 0

lendo os caras
Registro: [ Nome: Jhonny, idade: 65,  Altura: 1.85 ]

regrava o segundo

le de novo
Registro: [ Nome: Jhonny, idade: 65,  Altura: 1.85 ]
Registro: [ Nome: Maria, idade: 15,  Altura: 1.55 ]

E aqui está o programa que cria dois arquivos só pra mostrar que nada muda

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

struct registros
{
    const char* nome_do_arquivo;
    int total;
    struct registro
    {
        char        nome[20];
        int         idade;
        float       altura;
    };

    registros() : nome_do_arquivo("arquivo.txt")
    {    total = cria(nome_do_arquivo); };

    registros(const char* nome) : nome_do_arquivo(nome)
    {    total = cria(nome_do_arquivo); };

    int cria(const char* nome_do_arquivo)
    {
        int N = 0;
        registro rec;
        ofstream arquivo(nome_do_arquivo, ios::out | ios::binary);
        if (!arquivo)
        {
            cout << "Erro ao abrir " <<
                string(nome_do_arquivo) <<
                "!!!\n\n" << endl;
            exit(-1);
        };
        string nome;
        cout << "\n[Tecle 0 para encerrar] Nome: " << flush;
        cin >> nome;
        while (nome != "0")
        {
            N += 1;
            strncpy(rec.nome, nome.c_str(), 20);
            cout << "Nome: " << string(rec.nome) << endl;
            cout << "Idade: " << flush;
            cin >> rec.idade;
            cout << "Altura: " << flush;
            cin >> rec.altura;
            arquivo.write((char*)&rec, sizeof(rec));
            cout << "\n[Tecle ENTER para encerrar] Nome: " << flush;
            cin >> nome;
        };  // while()
        arquivo.close();
        return N;   // retorna quantos leu
    };  // cria()

    int le()
    {
        registro rec;
        int N = sizeof(registro);
        int lidos = 0;
        ifstream arquivo(nome_do_arquivo, std::ifstream::binary);
        if (!arquivo)
        {
            cout << "Erro ao abrir " <<
                string(nome_do_arquivo) <<
                "!!!\n\n" << endl;
            return 0;
        };
        arquivo.read( (char*) &rec, N);
        while (arquivo)
        {
            lidos += 1;
            cout << "Registro: [ " <<
                "Nome: " << string(rec.nome) <<
                ", idade: " << rec.idade << 
                ",  Altura: " << rec.altura << 
                " ]" << endl;
            arquivo.read((char*)&rec, N);
        };
        arquivo.close();
        return lidos;
    }

    int troca_o_segundo()
    {
        registro rec{ "Maria", 15, 1.55f };
        int N = sizeof(registro);
        int lidos = 0;
        ofstream arquivo(nome_do_arquivo, ios::in | ios::out);
        if (!arquivo)
        {
            cout << "Erro ao abrir " <<
                string(nome_do_arquivo) <<
                "!!!\n\n" << endl;
            return 0;
        };
        arquivo.seekp(N);
        if (!arquivo.good()) return -1;
        arquivo.write((char*)&rec, sizeof(rec));
        arquivo.close();
        return 0;
    };  // troca_o_segundo()
};

int main()
{
    registros um;
    if (um.total <= 0) return -1; // nao leu nada
    cout << "\nlendo os caras" << endl;
    um.le();
    cout << "\nregrava o segundo" << endl;
    um.troca_o_segundo();
    cout << "\nle de novo" << endl;
    um.le();

    registros outro("outro.txt");
    if (outro.total <= 0) return -1; // nao leu nada
    cout << "\nlendo os caras" << endl;
    outro.le();
    cout << "\nregrava o segundo" << endl;
    outro.troca_o_segundo();
    cout << "\nle de novo" << endl;
    outro.le();

    return 0;
}

 

C++ é uma linguagem "enorme".  Há muitas e distintas maneiras de fazer quase tudo. Mas acho que dá pra comparar os dois programas fazendo a mesma coisa.

 

Herança, polimorfismo, templates, private/public, encapsulamento, lambdas, functors, a própria biblioteca padrão... É algo grande. Mas é muito produtiva.

 

 

 

 

  • Curtir 1
  • Obrigado 1
  • Amei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
2 horas atrás, arfneto disse:

Então alterou o  [10] para [20]. Muito bem. Era essencial porque iria corromper o nome, como deve ter visto.

 

Sobre as diferenças, digitando em cima de seu programa vou postar um programa em C++ que faz isso. No fundo é o seu programa com as correções que incluiu, e usando a outra linguagem. Pode ser útil a outros já que tem o programa em C acima.

 

As diferenças em um EXEMPLO
 

Em C++ é muito mais fácil criar modelos de coisas. O cara que escreveu tinha isso como objetivo maior o que ele chamava de "abstrações de custo zero". Nos '80. E acho que conseguiu.
 

Uma classe Registros
 

image.png.8e75fd1e47e7c492f3e2edd271787dde.png

 

Tem maneiras mais C++ de escrever isso :D e o trocadilho foi de propósito. Mas não quero gastar muito tempo e quero manter a familiaridade com o seu programa para ficar clara a vantagem de escrever assim

 

Veja o tal polimorfismo por exemplo: eu posso criar registros especificando o nome do arquivo ou não. Nesse caso o programa usa "arquivos.txt" como padrão. E dentro dos registros tem uma estrutura registro que contem os campos de dados e assim eu posso tratar como unidade sem ter que especificar um a um.

 

Veja que as funções cria() e le() e troca_o_segundo() fazem parte de registros e não ficam soltas pelo programa, e faz sentido porque elas só tem a ver com os registros. São chamadas métodos. E os métodos ficam encapsulados nas classes

 

E cada ocorrência de registros --- são chamadas instâncias ---  tem seu nome_de_arquivo e seu contador de registros total. Ao declarar uma variável como sendo do tipo registros o sistema chama uma função com esse nome, a tal registros(). E você pode criar várias com o mesmo nome apenas mudando o tipo ou o número de argumentos. E só com isso já dá pra fazer muita coisa.
 

A função main em C++


    registros um;
    if (um.total <= 0) return -1; // nao leu nada
    cout << "\nlendo os caras" << endl;
    um.le();
    cout << "\nregrava o segundo" << endl;
    um.troca_o_segundo();
    cout << "\nle de novo" << endl;
    um.le();

Veja que declarar a variável um como registro vai fazer com que o programa crie o arquivo. Veja a diferença:


    registros um;
    registros outro("outro.txt");
    registros dois("maisum.txt");

No caso do primeiro vai usar o padrão "arquivos.txt" e nos outros vai usar o nome especificado.

 

E como registros tem um campo total que é atualizado ao criar cada arquivo tudo fica mais simples. um.le() sabe qual arquivo vai abrir, assim como outro.le() e dois.le() e não é preciso mudar nada no programa para tratar múltiplos arquivos, já que são múltiplas classes. struct e classe é a mesma coisa nesse exemplo.
 

Cada ocorrência de registros --- se chama instância --- tem um campo nome_do_arquivo que indica qual o arquivo a ser usado. Está encapsulado.

 

O "método" cria()


    int cria(const char* nome_do_arquivo)
    {
        int N = 0;
        registro rec;
        ofstream arquivo(nome_do_arquivo, ios::out | ios::binary);
        if (!arquivo)
        {
            cout << "Erro ao abrir " <<
                string(nome_do_arquivo) <<
                "!!!\n\n" << endl;
            exit(-1);
        };
        string nome;
        cout << "\n[Tecle 0 para encerrar] Nome: " << flush;
        cin >> nome;
        while (nome != "0")
        {
            N += 1;
            strncpy(rec.nome, nome.c_str(), 20);
            cout << "Nome: " << string(rec.nome) << endl;
            cout << "Idade: " << flush;
            cin >> rec.idade;
            cout << "Altura: " << flush;
            cin >> rec.altura;
            arquivo.write((char*)&rec, sizeof(rec));
            cout << "\n[Tecle ENTER para encerrar] Nome: " << flush;
            cin >> nome;
        };  // while()
        arquivo.close();
        return N;   // retorna quantos leu
    };  // cria()

Em C++ você pode usar write() close(0 e read() para manipular o arquivo. 

 

troca_o_segundo() em C++


    int troca_o_segundo()
    {
        registro rec{ "Maria", 15, 1.55f };
        int N = sizeof(registro);
        int lidos = 0;
        ofstream arquivo(nome_do_arquivo, ios::in | ios::out);
        if (!arquivo)
        {
            cout << "Erro ao abrir " <<
                string(nome_do_arquivo) <<
                "!!!\n\n" << endl;
            return 0;
        };
        arquivo.seekp(N);
        arquivo.write((char*)&rec, sizeof(rec));
        arquivo.close();
        return 0;
    };  // troca_o_segundo()

É bem simples. Note que o seek é feito em unidades de N que é o tamanho do registro. Então se você mudar o registro para incluir campos não precisa mexer nessas coisas aqui.


Esse programa de teste mostra
 



[Tecle 0 para encerrar] Nome: Ana
Nome: Ana
Idade: 12
Altura: 1.5

[Tecle ENTER para encerrar] Nome: Bia
Nome: Bia
Idade: 13
Altura: 1.5

[Tecle ENTER para encerrar] Nome: Cris
Nome: Cris
Idade: 12
Altura: 1.5

[Tecle ENTER para encerrar] Nome: 0

lendo os caras
Registro: [ Nome: Ana, idade: 12,  Altura: 1.5 ]
Registro: [ Nome: Bia, idade: 13,  Altura: 1.5 ]
Registro: [ Nome: Cris, idade: 12,  Altura: 1.5 ]

regrava o segundo

le de novo
Registro: [ Nome: Ana, idade: 12,  Altura: 1.5 ]
Registro: [ Nome: Maria, idade: 15,  Altura: 1.55 ]
Registro: [ Nome: Cris, idade: 12,  Altura: 1.5 ]

[Tecle 0 para encerrar] Nome: Jhonny
Nome: Jhonny
Idade: 65
Altura: 1.85

[Tecle ENTER para encerrar] Nome: 0

lendo os caras
Registro: [ Nome: Jhonny, idade: 65,  Altura: 1.85 ]

regrava o segundo

le de novo
Registro: [ Nome: Jhonny, idade: 65,  Altura: 1.85 ]
Registro: [ Nome: Maria, idade: 15,  Altura: 1.55 ]

E aqui está o programa que cria dois arquivos só pra mostrar que nada muda


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

struct registros
{
    const char* nome_do_arquivo;
    int total;
    struct registro
    {
        char        nome[20];
        int         idade;
        float       altura;
    };

    registros() : nome_do_arquivo("arquivo.txt")
    {    total = cria(nome_do_arquivo); };

    registros(const char* nome) : nome_do_arquivo(nome)
    {    total = cria(nome_do_arquivo); };

    int cria(const char* nome_do_arquivo)
    {
        int N = 0;
        registro rec;
        ofstream arquivo(nome_do_arquivo, ios::out | ios::binary);
        if (!arquivo)
        {
            cout << "Erro ao abrir " <<
                string(nome_do_arquivo) <<
                "!!!\n\n" << endl;
            exit(-1);
        };
        string nome;
        cout << "\n[Tecle 0 para encerrar] Nome: " << flush;
        cin >> nome;
        while (nome != "0")
        {
            N += 1;
            strncpy(rec.nome, nome.c_str(), 20);
            cout << "Nome: " << string(rec.nome) << endl;
            cout << "Idade: " << flush;
            cin >> rec.idade;
            cout << "Altura: " << flush;
            cin >> rec.altura;
            arquivo.write((char*)&rec, sizeof(rec));
            cout << "\n[Tecle ENTER para encerrar] Nome: " << flush;
            cin >> nome;
        };  // while()
        arquivo.close();
        return N;   // retorna quantos leu
    };  // cria()

    int le()
    {
        registro rec;
        int N = sizeof(registro);
        int lidos = 0;
        ifstream arquivo(nome_do_arquivo, std::ifstream::binary);
        if (!arquivo)
        {
            cout << "Erro ao abrir " <<
                string(nome_do_arquivo) <<
                "!!!\n\n" << endl;
            return 0;
        };
        arquivo.read( (char*) &rec, N);
        while (arquivo)
        {
            lidos += 1;
            cout << "Registro: [ " <<
                "Nome: " << string(rec.nome) <<
                ", idade: " << rec.idade << 
                ",  Altura: " << rec.altura << 
                " ]" << endl;
            arquivo.read((char*)&rec, N);
        };
        arquivo.close();
        return lidos;
    }

    int troca_o_segundo()
    {
        registro rec{ "Maria", 15, 1.55f };
        int N = sizeof(registro);
        int lidos = 0;
        ofstream arquivo(nome_do_arquivo, ios::in | ios::out);
        if (!arquivo)
        {
            cout << "Erro ao abrir " <<
                string(nome_do_arquivo) <<
                "!!!\n\n" << endl;
            return 0;
        };
        arquivo.seekp(N);
        if (!arquivo.good()) return -1;
        arquivo.write((char*)&rec, sizeof(rec));
        arquivo.close();
        return 0;
    };  // troca_o_segundo()
};

int main()
{
    registros um;
    if (um.total <= 0) return -1; // nao leu nada
    cout << "\nlendo os caras" << endl;
    um.le();
    cout << "\nregrava o segundo" << endl;
    um.troca_o_segundo();
    cout << "\nle de novo" << endl;
    um.le();

    registros outro("outro.txt");
    if (outro.total <= 0) return -1; // nao leu nada
    cout << "\nlendo os caras" << endl;
    outro.le();
    cout << "\nregrava o segundo" << endl;
    outro.troca_o_segundo();
    cout << "\nle de novo" << endl;
    outro.le();

    return 0;
}

 

C++ é uma linguagem "enorme".  Há muitas e distintas maneiras de fazer quase tudo. Mas acho que dá pra comparar os dois programas fazendo a mesma coisa.

 

Herança, polimorfismo, templates, private/public, encapsulamento, lambdas, functors, a própria biblioteca padrão... É algo grande. Mas é muito produtiva.

 

 

 

 

@arfneto Muito obrigado mesmo, td explicado de forma didática, e você refez o código ainda. De verdade, me ajudou muito!!!! :) :) :) 

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

javaweb-popup.jpg

CURSO ONLINE DE PROGRAMAÇÃO
FULL STACK

Entre para o mercado que paga mais de R$ 12.000 por mês e não tem crise!

CLIQUE AQUI E INSCREVA-SE AGORA MESMO!