Ir ao conteúdo
  • Cadastre-se

Vinicius schmitz

Membro Júnior
  • Posts

    4
  • Cadastrado em

  • Última visita

posts postados por Vinicius schmitz

  1. 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
  2. @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
  3. @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
  4. 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

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

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!