paulo1205
(usa Ubuntu)
Enviado em 28/02/2023 - 07:53h
Quando você tem tipos agregados de dados, em geral é melhor usar funções específicas para entrada e saída de cada tipo de dado (continue lendo e veja o exemplo na parte final desta postagem).
Como você pretende salvar os arquivos no disco? Em formato binário? Transformando todos os campos em texto?
Se for transformando para texto, você não tem escapatória de fazer código sob medida para cada tipo de dado, esteja esse código em duas funções separadas ou numa função só.
Se for em formato binário, a mais óbvia implementação é gravar diretamente o conteúdo de cada estrutura, o que é mais simples de fazer com uma função só do que seria se tivesse de haver uma conversão para texto. De fato, é tão simples de fazer com uma função só, que essa função inclusive já existe como
building block para qualquer outra função específica: trata-se exatamente da função
fwrite (), da biblioteca padrão do C. Provavelmente suas implementações de
salvar_colaborador () e
salvar_produto () (se você viesse a escrevê-las) usariam
fwrite () internamente, e teriam o seguinte aspecto geral.
// Função para salvar colaborador: retorna true se for bem sucedida ou false se não o for.
bool salvar_colaborador(const Colaborador *colab, FILE *fp){
return fwrite(colab, sizeof *colab, 1, fp)==1;
}
// Função para salvar produto: retorna true se for bem sucedida ou false se não o for.
bool salvar_produto(const Produto *prod, FILE *fp){
return fwrite(prod. sizeof *prod, 1, fp)==1;
}
/* BONUS: salvar vários colaboradores ou produtos de uma vez só (os quais tipicamente estarão armazenados em arrays). */
// Função para gravar um array com n colaboradores. Retorna a quantidade de colaboradores salva com sucesso.
size_t salvar_multi_colaboradores(const Colaborador *colabs, size_t n, FILE *fp){
return fwrite(colabs, sizeof colabs[0], n, fp);
}
// Função para gravar um array com n produtos. Retorna a quantidade de produtos salva com sucesso.
size_t salvar_multi_produtos(const Produto *prods, size_t n, FILE *fp){
return fwrite(prods, sizeof prods[0], n, fp);
}
Usando funções específicas, você reduz a chance de cometer enganos, e permite que o compilador diagnostique possíveis erros (que geralmente aparecem quando a gente faz
copy-and-paste ou quando estamos muito cansados). Compare estes dois códigos (ambos problemáticos).
typedef enum save_type {REG_COLAB, REG_PROD} tipo_salvamento;
// Note o uso de “void *” (ponteiro para tipo indeterminado em tempo de compilação).
bool salvar_registro(tipo_salvamento tipo_reg, void *reg, FILE *fp){
switch(type){
case REG_COLAB:
return fwrite(reg, sizeof (Colaborador), 1, fp)==1;
case REG_PROD:
return fwrite(reg, sizeof (Produto), 1, fp)==1;
}
return false;
}
int main(void){
Colaborador colab;
FILE *fp;
// ...
// Faz ajustes em colab e fp.
// ...
salvar_registro(REG_PROD, &colab, fp); // Note a mistura entre o tipo informado e o real tipo do dado.
// ...
} bool salvar_produto(const Produto *prod, FILE *fp){
return fwrite(prod. sizeof *prod, 1, fp)==1;
}
int main(void){
Colaborador colab;
FILE *fp;
// ...
// Faz ajustes em colab e fp.
// ...
salvar_produto(&colab, fp); // Note a discrepância entre o dado informado e o que a função espera.
// ...
}
A maior diferença entre os dois casos acima é que o primeiro não permite que o compilador ajude o programador a identificar o erro: o uso de
void * para permitir que a função aceite qualquer tipo de argumento (desde que seja um ponteiro) e o desacoplamento entre ponteiro e a informação do tipo que ele carrega vão permitir que o programa não apenas compile sem problemas, mas também que possivelmente execute sem qualquer tipo de alarme, até o dia em que alguém precisar ler os dados, e ver que eles provavelmente estarão corrompidos; já o segundo programa nem sequer vai compilar, porque o compilador não vai deixar você passar como argumento um ponteiro para colaborador para um parâmetro que espera um ponteiro para produto, obrigando-o a corrigir o sentido.
... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)