Quatro Padrões Comprovados para Funções Definidas pelo Usuário em C
Quatro Padrões Comprovados para Funções Definidas pelo Usuário em C
Explore quatro maneiras distintas de implementar uma função definida pelo usuário que verifica se um número é primo, e aprenda qual abordagem oferece maior clareza e reutilizabilidade.
Abaixo, quatro programas completos demonstram como a mesma tarefa lógica pode ser expressa com diferentes assinaturas de função. Todas as quatro saídas são idênticas, mas as escolhas de design variam, ilustrando trade-offs chave no design de funções.
Exemplo 1: Sem Argumentos, Sem Valor de Retorno
#include <stdio.h> void checkPrimeNumber(); int main() { checkPrimeNumber(); // argumento não é passado return 0; } // tipo de retorno é void significando que não retorna valor void checkPrimeNumber() { int n, i, flag = 0; printf("Digite um inteiro positivo: "); scanf("%d",&n); for(i=2; i <= n/2; ++i) { if(n%i == 0) { flag = 1; } } if (flag == 1) printf("%d não é um número primo.", n); else printf("%d é um número primo.", n); }
A função checkPrimeNumber() é responsável por ler entrada do usuário, realizar o teste de primalidade e imprimir o resultado. Como seu tipo de retorno é void, ela comunica o resultado apenas através de efeitos colaterais.
Exemplo 2: Sem Argumentos, Mas Com Valor de Retorno
#include <stdio.h> int getInteger(); int main() { int n, i, flag = 0; // nenhum argumento é passado n = getInteger(); for(i=2; i<=n/2; ++i) { if(n%i==0){ flag = 1; break; } } if (flag == 1) printf("%d não é um número primo.", n); else printf("%d é um número primo.", n); return 0; } // retorna inteiro digitado pelo usuário int getInteger() { int n; printf("Digite um inteiro positivo: "); scanf("%d",&n); return n; }
Aqui, getInteger() encapsula a rotina de entrada e retorna o valor para main, que então lida com a lógica de verificação de primalidade. Essa separação torna a etapa de entrada reutilizável em diferentes contextos.
Exemplo 3: Argumento Passado, Sem Valor de Retorno
#include <stdio.h> void checkPrimeAndDisplay(int n); int main() { int n; printf("Digite um inteiro positivo: "); scanf("%d",&n); // n é passado para a função checkPrimeAndDisplay(n); return 0; } // tipo de retorno é void significando que não retorna valor void checkPrimeAndDisplay(int n) { int i, flag = 0; for(i=2; i <= n/2; ++i) { if(n%i == 0){ flag = 1; break; } } if(flag == 1) printf("%d não é um número primo.",n); else printf("%d é um número primo.", n); }
Neste padrão, a responsabilidade de exibir o resultado é transferida para a função auxiliar. Embora isso mantenha main enxuto, a função agora acopla o algoritmo com I/O, reduzindo sua reutilizabilidade.
Exemplo 4: Argumento Passado e Valor de Retorno
#include <stdio.h> int checkPrimeNumber(int n); int main() { int n, flag; printf("Digite um inteiro positivo: "); scanf("%d",&n); // n é passado para a função checkPrimeNumber() // o valor retornado é atribuído à variável flag flag = checkPrimeNumber(n); if(flag == 1) printf("%d não é um número primo",n); else printf("%d é um número primo",n); return 0; } // int é retornado da função int checkPrimeNumber(int n) { int i; for(i=2; i <= n/2; ++i) { if(n%i == 0) return 1; } return 0; }
Este design mantém o algoritmo isolado e retorna uma flag simples estilo Booleano. O chamador decide como apresentar o resultado, o que torna a função altamente reutilizável em bibliotecas ou aplicações maiores.
Escolhendo o Padrão Ótimo
Embora todas as quatro implementações produzam a mesma saída, a abordagem mais sustentável e testável é o Exemplo 4: passar o número como argumento e retornar uma flag estilo Booleano. Este padrão adere ao princípio de responsabilidade única, permite teste unitário de checkPrimeNumber sem dependências de I/O, e pode ser facilmente integrado em sistemas mais complexos.
Em última análise, a escolha depende da arquitetura do seu projeto. Se a função deve interagir diretamente com o usuário, o Exemplo 3 pode bastar. Para código de biblioteca ou serviços onde I/O é tratado em outro lugar, o Exemplo 4 oferece a maior flexibilidade.
Linguagem C
- Dominando Namespaces em C#: Organização, Escopo e Boas Práticas
- Tipos de Dados em C Explicados: int, float, char e Mais – Guia Completo
- Dominando Operadores em Programação C: Um Guia Abrangente
- Dominando Funções da Biblioteca Padrão C: Guia Prático
- Variáveis e Tipos de Dados em C++: Guia Completo sobre int, double, char, string, bool
- Ponteiros em C: Guia Completo sobre Tipos, Uso e Melhores Práticas
- Domine a Programação em C: Tutorial Completo para Iniciantes
- Entendendo Tipos de Dados em C: Guia Abrangente
- Dominando Funções em C: Estrutura, Declaração e Boas Práticas
- Dominando Argumentos Variáveis em C: Guia Prático