Ir ao conteúdo

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


Ir à solução Resolvido por arfneto,

Posts recomendados

Postado

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
Postado

@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
Postado

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
Postado

@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
Postado
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
Postado

@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
  • Solução
Postado

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
Postado
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

Crie uma conta ou entre para comentar

Você precisa ser um usuário 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 comunidades 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...