daniel_silva Posted January 22, 2016 at 04:59 PM Report #592341 Posted January 22, 2016 at 04:59 PM Boa tarde programadores 😉 Gostava de saber como é que elimino um registo no ficheiro... Fico à espera de dicas! 😄 Obrigado 👍 Abraço.
nunopicado Posted January 22, 2016 at 05:35 PM Report #592346 Posted January 22, 2016 at 05:35 PM E nem tens de esperar muito.. 😁 A resposta curta é: Não eliminas. A resposta longa é: Crias um ficheiro temporário do mesmo tipo, e para ele copias todos os registos menos o que queres eliminar. Depois eliminas o ficheiro original, e por fim, renomeias o ficheiro temporário com o nome do original. Ficheiros sequenciais têm essa pequena chatice. "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.
passarito Posted January 22, 2016 at 05:40 PM Report #592348 Posted January 22, 2016 at 05:40 PM (edited) Eliminar automaticamente penso que não dá. Podes é usar uma de das duas formas seguintes: 1. Eliminação fisica 1.1. Copias todos os registos excepto o que queres apagar para o novo ficheiro temporário 1.2. Apagas o ficheiro de dados 1.3. Renomeias o ficheiro temporário para o nome "oficial" 2. Eliminação virtual 2.1. No registo adicionas um campo boolean que será true quando o registo existe. Quando mandas apagar um registo passas esse campo a false. Nesta opção poderás programar um item para te reduzir o numero de registos reais e consequentemente o tamanho usando a primeira opção Edited January 22, 2016 at 05:41 PM by passarito
daniel_silva Posted January 25, 2016 at 04:06 PM Author Report #592477 Posted January 25, 2016 at 04:06 PM Boa tarde. Nunopicado, percebi a tua forma de eliminar 😄 Vou tentar fazer como tu disseste se tiver alguma opinião meto a duvida no fórum para alguém me esclarecer 👍 CRLF, não percebi a tua segunda sugestão... Abraço.
Solution passarito Posted January 25, 2016 at 06:49 PM Solution Report #592505 Posted January 25, 2016 at 06:49 PM Antes de mais, o meu nome não é CRLF assim como o teu não é null 😉 Voltando ao que interessa, a 2ª opção será desta forma, imagina que o teu registo tem os campos Nome, Sexo, Idade, Morada. É só acrescentar um campo boolean, por exemplo, ativo. Agenda=Record Nome: string[30]; Sexo: Char; Idade: integer; Morada: String[100]; activo: boolean; //Campo a adicionar para controlo das supressões (Verdadeiro-Mostra registo, Falso-Esconde registo) end;
thoga31 Posted January 25, 2016 at 08:48 PM Report #592511 Posted January 25, 2016 at 08:48 PM O método do @passarito tem uma vantagem e uma desvantagem, principalmente em ficheiros com muitos registos. Vantagem: é muito mais rápido a "eliminar" registos - apenas muda o campo. Desvantagem: ficam em disco os registos activos e os inactivos. Knowledge is free!
nunopicado Posted January 25, 2016 at 09:13 PM Report #592514 Posted January 25, 2016 at 09:13 PM O método do passarito é o que se usa em casos onde a informação é de importância elevada (por exemplo, um software de facturação, onde dados nenhuns podem ser apagados, apenas inactivados/escondidos). Além da vantagem da rapidez e simplicidade de eliminar um registo (basta mudar o valor do campo), tem a vantagem de ser possível recuperar a informação, como se fosse uma reciclagem. É só voltar a mudar o valor e está lá tudo na mesma. Usando este método, pode-se depois criar uma opção no programa que execute o primeiro método, em que efectivamente apaga todos os que estiverem marcados como inactivos. Isto usa "o melhor dos dois mundos", é rápido ao eliminar, e quando se achar necessário, é possível a eliminação efectiva. Agora, uma nota: Como diz o passarito, é preciso fazer um controlo de supressões. Isto quer dizer que não basta por lá o campo e atribuir-lhe um valor, é necessário em TODAS as operações fazer a validação do campo e agir em conformidade. Por exemplo, se estamos a fazer a listagem dos registos, é preciso mostrar apenas os que não estejam marcados como apagados. "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.
daniel_silva Posted January 27, 2016 at 03:39 PM Author Report #592614 Posted January 27, 2016 at 03:39 PM Boa tarde. Antes de mais peço desculpa ao @passarito por no último comentário que fiz lhe ter chamado CRLF. 😕 Agora que já percebi o segundo método do passarito, acho melhor o método do verdadeiro e falso! Ou seja, posso criar uma opção para o utilizador eliminar (esconder) o registo que deseja e posso criar outra opção para recuperar os registos que foram escondidos, como fosse uma reciclagem. Se tiver mais dúvidas sobre este assunto esclareço aqui com vocês. 👍 Muito obrigado. 😄 Abraço!
nunopicado Posted January 27, 2016 at 06:19 PM Report #592677 Posted January 27, 2016 at 06:19 PM Ou seja, posso criar uma opção para o utilizador eliminar (esconder) o registo que deseja e posso criar outra opção para recuperar os registos que foram escondidos, como fosse uma reciclagem. Nem mais. 🙂 Num programa de faturação, por exemplo, é o único método admissível. 1 Report "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.
passarito Posted January 29, 2016 at 03:44 PM Report #592776 Posted January 29, 2016 at 03:44 PM Antes de mais peço desculpa ao @passarito por no último comentário que fiz lhe ter chamado CRLF. 😕 Tás desculpado! Com este método "the sky is the limit". Ora bem, vejamos, como o ficheiro de registos pode crescer muito e comprometer a velocidade do programa o que podes fazer? Opção de acesso restrito, normalmente chamava-lhe "funções especiais" e tinha uma password. Dentro dessa opção então poderás ter várias coisas, tais como, apagar definitivamente os registos utilizando o 1º método. Mas ainda assim, não querendo perder essa informação apagada, queres reduzir o tamanho do ficheiro? Solução: Arranjas um ficheiro de segurança e os registos normais copia-los para para o ficheiro oficial e os marcados como apagados adiciona-los ao tal ficheiro de segurança. Assim tens um ficheiro de trabalho de tamanho relativamente reduzido e um de segurança com tudo o que foi apagado que poderás consultar, importar, etc. a qualquer altura. Claro que dentro das funções especiais. Ora aí tens "The best of both worlds" 2 Report
daniel_silva Posted January 31, 2016 at 06:41 PM Author Report #592845 Posted January 31, 2016 at 06:41 PM Boa tarde. Então imagina que tenho um ficheiro de clientes e um de fornecedores, o melhor era fazer 2 ficheiros de segurança. Por exemplo, tinha a opção eliminar registos dos clientes e outras para os fornecedores. Certo?
passarito Posted February 1, 2016 at 08:16 AM Report #592855 Posted February 1, 2016 at 08:16 AM Sim, é o melhor a fazer
daniel_silva Posted February 1, 2016 at 08:07 PM Author Report #592904 Posted February 1, 2016 at 08:07 PM Como diz o passarito, é preciso fazer um controlo de supressões. Isto quer dizer que não basta por lá o campo e atribuir-lhe um valor, é necessário em TODAS as operações fazer a validação do campo e agir em conformidade. @nunopicado, não percebo o que queres dizer com isso... Podes explicar melhor? Obrigado.
nunopicado Posted February 1, 2016 at 09:04 PM Report #592906 Posted February 1, 2016 at 09:04 PM @nunopicado, não percebo o que queres dizer com isso... Podes explicar melhor? Imagina que fazes uma função que te mostra todos os registos. Normalmente, percorres o ficheiro e vais mostrando cada registo. Com este sistema, tens de controlar o que está ou não marcado como apagado. Ou seja, percorres o ficheiro e mostras apenas os que não estiverem marcados como apagados. "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.
daniel_silva Posted February 4, 2016 at 07:39 PM Author Report #593185 Posted February 4, 2016 at 07:39 PM Boa noite. Com o método 1 como posso fazer?
passarito Posted February 5, 2016 at 08:49 AM Report #593191 Posted February 5, 2016 at 08:49 AM Tal e qual como expliquei anteriormente 1. Eliminação fisica 1.1. Copias todos os registos excepto o que queres apagar para o novo ficheiro temporário 1.2. Apagas o ficheiro de dados 1.3. Renomeias o ficheiro temporário para o nome "oficial"
daniel_silva Posted February 7, 2016 at 06:10 PM Author Report #593253 Posted February 7, 2016 at 06:10 PM (edited) Boa tarde. Ando de volta disto à algum tempo, nas calmas... Mas tenho de começar a apressar-me para mostrar o trabalho ao professor. Estou a fazer o método 2 que o @passarito referiu, fiz o que vocês me explicaram mas não está a a resultar... Não percebo o porque! Devo ter algo mal com o sinal true ou false... Program Pzim ; uses crt; type dados_cliente = Record nomeC:string; num_biC:string; data_nasC:string; ruaC:string; loteC:string; cod_postalC:string; localidadeC:string; telemovelC:string; enderecoC:string; esconder:boolean; end; total_dados = Record cliente:dados_cliente; end; ficheiro_cliente = file of total_dados; var d:total_dados; f_cliente:ficheiro_cliente; opcao,fecho_principal:char; Function exist_fich_cliente:boolean; begin assign(f_cliente,'C:\stand\cliente.dat'); {$I-} reset(f_cliente); close(f_cliente); {$I+} exist_fich_cliente:=(ioresult=0); end; Procedure menu_princial(var op:char); begin clrscr; writeln (' --------------------------'); writeln ('| MENU PRINCIPAL |'); writeln (' --------------------------'); writeln; writeln (' 1: Registrar um cliente'); writeln; writeln (' A: Pesquisar Clientes'); writeln; writeln (' E: Eliminar registros de clientes'); writeln; readln (op); end; Procedure ler_cliente(var lc:total_dados); var num_biC:string; fc:ficheiro_cliente; sinal:boolean; begin assign(fc,'C:\stand\cliente.dat'); reset(fc); seek(fc,0); sinal:=false; clrscr; writeln (' ----------------------------'); writeln ('| REGISTRAR UM CLIENTE |'); writeln (' ----------------------------'); writeln; write ('> Numero de contribuinte: '); {verificar se já existe} readln (num_biC); while not(eof(fc)) do begin read(fc,lc); if (lc.cliente.num_biC = num_biC) then sinal:=true; end; if sinal = true then {se existir} begin writeln; writeln ('-- [ERRO] O numero de contribuinte ',num_bic,' ja existe. --'); end; if sinal = false then {se não existir} begin with lc do begin cliente.num_biC := num_biC; cliente.esconder := false; write ('> Nome..................: '); readln (cliente.nomeC); write ('> Data de nascimento....: '); readln (cliente.data_nasC); write ('> Rua...................: '); readln (cliente.ruaC); write ('> Lote..................: '); readln (cliente.loteC); write ('> Codigo postal.........: '); readln (cliente.cod_postalC); write ('> Localidade............: '); readln (cliente.localidadeC); write ('> Telemovel.............: '); readln (cliente.telemovelC); write ('> E-mail................: '); readln (cliente.enderecoC); end; close(fc); end; end; Procedure escrever_cliente(ec:total_dados); begin with ec do begin writeln ('> Nome..................: ',cliente.nomeC); writeln ('> Numero de contribuinte: ',cliente.num_biC); writeln ('> Data de nascimento....: ',cliente.data_nasc); writeln ('> Rua...................: ',cliente.ruaC); writeln ('> Lote..................: ',cliente.loteC); writeln ('> Codigo postal.........: ',cliente.cod_postalC); writeln ('> Localidade............: ',cliente.localidadeC); writeln ('> Telemovel.............: ',cliente.telemovelC); writeln ('> E-mail................: ',cliente.enderecoC); end; end; Procedure esc_reg_fich_cliente(var fc:ficheiro_cliente); var efc:total_dados; fecho:char; begin assign(fc,'C:\stand\cliente.dat'); reset(fc); seek(fc,filesize(fc)); Repeat ler_cliente(efc); write(fc,efc); writeln; Repeat writeln ('Deseja continuar a registrar clientes? S/N '); readln (fecho); Until (fecho='n') or (fecho='s') or (fecho='N') or (fecho='S'); Until (fecho='N') or (fecho='n'); close(fc); end; {PESQUISAR CLIENTES REGISTRADOS} Procedure pesquisar_clientes(var fc:ficheiro_cliente); var pc:total_dados; sinal:boolean; pesqcliente,num_biC:string; oputi:char; begin clrscr; assign(fc,'C:\stand\cliente.dat'); reset(fc); seek(fc,0); sinal:=false; writeln (' ------------------------------ '); writeln ('| Pesquisar clientes |'); writeln (' ------------------------------ '); writeln; write ('> Introduza o nome do cliente: '); readln (pesqcliente); while not(eof(fc)) do begin read(fc,pc); if (pc.cliente.nomeC = pesqcliente) and (pc.cliente.esconder = false) then begin writeln; escrever_cliente(pc); sinal:=true; end; end; if (sinal=false) then begin writeln; writeln ('--- [ERRO] Nao existe nenhum cliente com esse nome na base de dados. ---'); end; close(fc); end; Procedure eliminar_cliente(var fc:ficheiro_cliente); var ee:total_dados; var eliminar:char; num_biC:string; begin clrscr; assign(fc,'C:\stand\cliente.dat'); reset(fc); seek(fc,0); writeln (' ----------------------------'); writeln ('| ELIMINAR UM CLIENTE |'); writeln (' ----------------------------'); writeln; writeln ('> Introduza o numero de contribuinte do cliente: '); readln (num_biC); while not(eof(fc)) do {PESQUISAR CLIENTES PARA OS ELIMINAR} begin read (fc,ee); if (ee.cliente.num_biC = num_biC) then begin writeln; escrever_cliente(ee); end; end; writeln; writeln ('- Carregue na tecla [E] para eliminar: '); readln (eliminar); if (eliminar = 's') or (eliminar = 'S') then begin ee.cliente.esconder := true; {esconder o registo} write(fc,ee); end; close(fc); end; Begin if (exist_fich_cliente) then reset(f_cliente) else rewrite(f_cliente); close(f_cliente); Repeat menu_princial(opcao); case opcao of '1':esc_reg_fich_cliente(f_cliente); 'a','A':pesquisar_clientes(f_cliente); 'e','E':eliminar_cliente(f_cliente); end; writeln; Repeat writeln ('- Deseja sair do programa? S/N '); readln (fecho_principal); Until (fecho_principal='n') or (fecho_principal='s') or (fecho_principal='N') or (fecho_principal='S'); Until (fecho_principal='S') or (fecho_principal='s'); End. Quando o esconder tomar o valor a true esconde o registo. Fico a aguardar uma ajuda vossa, obrigado. 👍 Abraço! Edited February 7, 2016 at 06:25 PM by thoga31 GeSHi
pwseo Posted February 7, 2016 at 08:02 PM Report #593255 Posted February 7, 2016 at 08:02 PM daniel_silva, Tens aí uma coisa interessante: um bug a esconder outro bug. Para começar, quando tentas eliminar um registo, não podes simplesmente definir esconder := true e escrever o registo novamente. Primeiro é necessário fazeres seek até à posição onde o registo começa e aí sim escrevê-lo, pois se não o fizeres estarás simplesmente a criar um duplicado do original, mas com esconder := true. Este é o primeiro bug. O primeiro bug nunca foi detectado porque tens um outro bug: quando perguntas ao utilizador se quer eliminar o cliente, pedes para ele carregar na tecla E, mas o teu código apenas actua caso seja pressionada a tecla S. Corrigindo o bug da tecla errada irás reparar que de cada vez que «eliminas» um registo ele na realidade está a ser duplicado, pois não estás a escrevê-lo em cima do seu original mas sim a criar uma cópia sua logo de seguida. Experimenta 🙂 1 Report
passarito Posted February 8, 2016 at 09:20 AM Report #593261 Posted February 8, 2016 at 09:20 AM (edited) Para trabalhares com ficheiros de em Pascal tens que ter isto em mente:Imagina um apontador, quando queres ler ou escrever um registo o apontador tem de estar imediatamente antes do registo isto para quê? Para que quando mandas ler ou escrever ele vai fazê-lo no que estiver imediatamente a seguir, assim quando lê, por exemlo, o registo 5 ele irá ficar a apontar para o registo 6. Se quizeres alterar o registo 5 tens de fazer recuar o ponteiro. Para esse efeito as funções seek e filepos funcionam muito bem. Vou-te dar o exemplo para este caso, mas se queres "brincar" com elas é melhor estudá-las assim como o filesize. Tenta isto: Procedure eliminar_cliente(var fc:ficheiro_cliente); var ee:total_dados; var eliminar:char; num_biC:string; begin .. writeln; writeln ('- Carregue na tecla [E] para eliminar: '); readln (eliminar); if (eliminar = 's') or (eliminar = 'S') then begin seek(fc,filepos(fp)-1); //coloca-te na posição correcta para escrever o registo ee.cliente.esconder := true; {esconder o registo} write(fc,ee); end; close(fc); end; Mais 2 pontos: - Estuda a função readkey, vais ver que vai ser uma grande ajuda em vez do readln para ler só uma tecla. - Se o utilizador colocar um nº de contribuinte que não existe como é que o programa se comporta? Edited February 8, 2016 at 09:23 AM by passarito
daniel_silva Posted February 9, 2016 at 12:59 PM Author Report #593291 Posted February 9, 2016 at 12:59 PM Boa tarde. @pwseo o segundo bug foi mesmo distracção minha. 😛 obrigado por me avisares! 👍 @passarito agradeço-te muito por me teres ajudado neste tópico! Cada vez gosto mais deste fórum por ter pessoas que estão sempre disponíveis para ajudar. 😉 Vou seguir o teu concelho de estudar a função readkey. Quando o nº de contribuinte não existir meto uma mensagem de erro, ou pergunto ao utilizador se ele pretende registrar. 😁 Obrigado! 🙂 Abraço.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now