paulo1205
(usa Ubuntu)
Enviado em 26/07/2016 - 03:41h
Já que você pediu comentários gerais, vou generalizar mesmo, mas sem repetir o que os demais já disseram.
“Almentar” não existe. Existem “aumentar” e “alimentar”. Em todo caso, no lugar em que você usou a palavra, você quer mais é passar a ideia de deslocamento, não de aumento nem de alimentação.
Eu aprendi com a experiência que comentários que apenas duplicam em Português o que está escrito em C podem vir a ser piores do que a falta comentários. Qualquer mudança pontual no código obriga a dar manutenção também em cada comentário, e isso acaba virando um transtorno. Ademais, alguém que pegue seu código para ler ou dar manutenção tem de entender é do C, mas a presença dos comentários em Português pode vir a tirar o foco do que realmente interessa, ou induzir a pessoa a olhar para o C e interpretá-lo pelo que você disse em Português, em vez de entender realmente aquilo que está expresso em C.
Essa biblioteca CC50 é para proteger o usuário da complexidade de fazer entrada e saída de dados. Parece legal para quem está começando, porque I/O em C é mesmo complicada para novatos. Mas ela me deu a impressão de ser um tanto arbitrária e inflexível no tratamento de erros.
Eu não sei por que motivo você indicou seu programa como em C++, já que ele só usa recursos do C. Eu acho que você se confundiu e, por causa de tal confusão, recebeu os comentários que desaprovam o uso do nome “
string”, herdado dessa CC50, em descompasso com o uso costumeiro que tem em C++.
Se, de fato, seu código estiver em C puro, eu não me oponho ao uso do nome
string, pois C e C++ são mesmo linguagens diferentes (e, até por isso, o nome usado pela biblioteca padrão C++ para o seu tipo destinado a representar strings não é apenas
string, mas sim
std::string, e o uso do
namespace “
std” é justamente para protegê-la de possíveis conflitos com código em C). Contudo, eu sempre recomendo muita cautela com o uso de nomes alternativos de tipos que escondem a existência de um ponteiro, o que, por sinal, é justamente o que a CC50 faz, supostamente pra “ajudar”.
Se, no entanto, você realmente quis usar C++, então você deveria evitar coisas que podem confundir o leitor. (Aliás, deveria parar de usar essa CC50, pois C++ tem coisa muito melhor, incluindo o próprio tipo
std::string, que não está sujeito aos problemas de alocação e liberação de recursos mencionados abaixo.)
Ligado aos temas de esconder ponteiros e facilitar operações de entrada de dados, você cometeu um erro ligado ao emprego de
GetString(). Mais do que apenas ler uma string, essa função aloca dinamicamente uma área de memória para acomodar a string lida, e isso o obriga a liberar a “string” retornada (que na verdade é somente um ponteiro) antes de sair do bloco (no caso, do corpo da função
main()) ou de reutilizar a mesma variável numa próxima chamada a
GetString(). Você, contudo, esqueceu de providenciar a liberação de memória.
No seu caso, o erro apontado acima não traz consequências graves, já que o programa só chama
GetString() uma vez e também termina de executar logo, liberando implicitamente toda memória que tiver sido alocada. Mesmo assim, você deve se acostumar a sempre devolver explicitamente os recursos que você obtiver explicitamente. Esse hábito salutar vai ser muito valioso quando seus programas saltarem de 67 linhas para 6700 linhas ou -- o que é mais provável -- quando eles ultrapassarem as 67000 linhas. Também será valioso quando você começar a trabalhar com recursos que não são devolvidos automaticamente quando o programa termina (como, por exemplo, mecanismos de comunicação entre processos, tais como memória compartilhada, semáforos,
named pipes etc.).
Não é culpa sua, mas examinando o código da CC50, vi que ela, que é geralmente cautelosa com alocação de memória, falha em tratar um possível caso de erro dentro de
GetString(), e justamente na hora de minimizar o uso de memória alocada.
Na boa: pare logo de usar essa CC50 xexelenta.
Por que usar “
chave==0 || chave<0” em lugar de, simplesmente, “
chave<=0”?
E qual o problema com uma chave nula ou negativa? Se você considerar o alfabeto como cíclico, andar uma posição para a esquerda ou vinte e cinco para a direita dá na mesma, e andar vinte e seis para qualquer lado é a mesma coisa que não andar nenhuma. (Um problema que você realmente tem com sua chave é que o usuário pode chamar o programa colocando algo não-numérico como argumento, e a função
atoi() vai devolver zero como retorno, sem apontar erro de utilização. O Uilianries muito adequadamente apontou que você deveria usar
strtol() para poder identificar tal situação, e sinalizar o erro adequadamente.)
Eu não gostei do nome de algumas variáveis. Por exemplo, “
caracteres” não me transmite a ideia de representar o comprimento da mensagem.
A implementação do código de César também me pareceu excessivamente complicada e, ao mesmo tempo, incompleta e com um erro. Você usou um laço com três variáveis para algo que poderia ser resolvido com expressões simples. Além disso, você pode se complicar se sua mensagem tiver caracteres de pontuação, tabulações, letras acentuadas e outros caracteres fora do subconjunto alfanumérico do ASCII. E o erro é que você corre o risco de usar a variável
crip antes de lhe atribuir qualquer valor (suponha que, na primeira iteração do laço de repetição,
carac não valha nem 32 nem 57: você vai usar o valor indeterminado de
crip como parte do teste do segundo
if dentro do bloco
do-
while, e ainda corre semelhante risco nos dois
ifs seguintes se
carac também não valer 90 ou 122).
Para ajudar sua lógica, acho que você pode ter ganhos se usar as funções de <ctype.h> (ou <cctype>, se sua intenção for usar C++).
Por falar em
do-
while, eu acho prudente colocar o
while na mesma linha em que você fecha o bloco que o antecede, para que fique claro para o leitor que se trata do finalizador de um
do-
while, e não de um comando
while simples.
O código de César que eu conheço contempla apenas letras não-acentuadas. Você decidiu incluir algarismos como um alfabeto à parte, com tamanho diferente (10, em vez de 26). Nada contra, mas então tem de levar em consideração que o seu período de repetição das mensagens agora será de 130 (MMC entre 10 e 26), e não mais de 26. Isso pode ser relevante na decisão de filtrar os possíveis valores das chaves, mencionado acima.