Programar em C/Dicas de programação em C

Convenções tipográficas editar

Uma das melhores maneiras de obter um código claro e usando identificadores coerentes.
Por exemplo é bom poder identificar rapidamente as variáveis em função de suas propriedades .
Veja abaixo algumas delas.

                                      prefixos identificadores
   - ponteiro                         p_
   - tabela estática(static array)    a_ ou sa_    
   - tabela dinâmica (dynamic array)  da_ 
   - cadeia de caracteres(string)     s_ 

Em um código com a variável "p_exemplo" podemos deduzir rapidamente que estamos usando um ponteiro .

A função printf é a melhor amiga de um programador editar

Um programador novato tende a ver apenas duas aplicações para o printf:

  1. Solicitar entrada para o usuário do programa.
  2. Imprimir o resultado do programa.

O fato é que um programador pode aplicar o printf a fim de saber o que ocorre durante a execução de programa. Isto permite, dentre outras coisas, detectar erros.

Por exemplo, suponha um programa no qual várias funções e rotinas são executadas. Algo como:

 int main(int argc, char *argv[])
 {
 ...
 funcao1(...);
 funcao2(...);
 funcao3(...);
 funcao4(...);
 ...
 return 0;
 }

Digamos que o programa tenha sido compilado com sucesso, mas ocorra algum erro durante sua execução. Podemos usar o printf para detectar o erro da seguinte maneira:

 int main(int argc, char *argv[])
 {
 ...
 printf("iniciando funcao1");
 funcao1(...);
 printf("completa função1, iniciando funcao2");
 funcao2(...);
 printf("completa função2, iniciando funcao3");
 funcao3(...);
 printf("completa função3, iniciando funcao4");
 funcao4(...);
 printf("completa função4");
 ...
 return 0;
 }

Isto permite o programador determinar até que ponto o programa roda antes de dar erro, facilitando muito a detecção deste.

Outro exemplo de como o printf é útil na detecção de problemas. Suponha um programa cheio de laços aninhados. Tal como:

  for(...)
  {
 	 while(...)
         {
         ...
            for(...)
             {
              ...
             }
         }
  }

Caso durante a execução o programa entre em um loop infinito, uma forma de detectar em qual dos laços está o problema é:

 for(...)
  { printf("Teste 1");
     while(...)
      { printf("Teste 2");
      ...
          for(...)
          { printf("Teste 3");
             ...
           }
        }
   }

A impressão que se repetir eternamente é aquela dentro do laço problemático.

Um último exemplo de detecção de problemas por meio do printf. Suponha que a resposta dada por um programa não é a esperada, que a resposta consiste na impressão de uma variável x, a qual recebe diversas atribuições ao longo do programa. Podemos identificar o erro dando um printf em x após cada uma de suas atribuições:

  x=...
 printf("primeira atribuicao de x eh %tipo", x);
 ...
  x=...
  printf("segunda atribuicao de x eh %tipo", x);
  ...
  x=...
  printf("terceira atribuicao de x eh %tipo", x);
  ...
 printf("A resposta eh %tipo", x);

Caso o valor de x dependa do valor de outras variáveis que não são impressas, imprimi-las pode ajudar na detecção do problema.

Para uso como debug, a linguagem C apresenta duas macros que quando utilizadas junto com o printf são ótimos recursos.

  • __FILE__ = nome do arquivo.
  • __LINE__ = numero da linha de execuçãão.

O Compilador gcc ainda dispõe de uma outra macro bastante util:

  • __PRETTY_FUNCTION__ = nome da função atual.
  ...
 printf("%d:%s:%s\n", __LINE__, __FILE__, __PRETTY_FUNCTION__);
  ...

O trecho acima vai te dar uma saida para debug muito util com o seguinte conteudo:

  Exemplo:
 3:hello.c:main

Tecle 1 para rodar editar

Existem duas formas de manter um programa rodando enquanto o usuário desejar:

  1. Conter a maior parte do programa dentro de um laço.
  2. Usar o comando goto(lembre-se que o comando goto não é de uso aconselhado para a programação estruturada).

Alguns exemplos:

Com while:

 int main(int argc, char *argv[]) 
 {
 
  int rodando=1;
  while(rodando==1)/*Este laco mantem o programa rodando enquanto o usuario desejar*/
  {
  ...
 
  printf("\nDigite 1 para continuar rodando o programa.");
  printf("\nDigite qualquer outro numero para encerrar o programa. ");
  scanf("%d", &rodando);
  }
  
  return 0;
 }

Com do...while

 int main(int argc, char *argv[])
 {
 short int rodando;
 do    /*Este laco mantem o programa rodando enquanto o usuario desejar*/
 {
 ...
 printf("\nDigite 1 para manter o programa rodando. ");
 scanf("%d", &rodando);
 }while(rodando==1);
   
 return 0;
 }

Com o goto

 int main(int argc, char *argv[])
 {  
 MARCA:
  
 ...
 FIM:
 int y;
 printf("Tecle 1 para continuar rodando o programa. Tecle 0 para encerrar o programa\n");
 scanf("%d",&y);
 if(y==1)
 {
 goto MARCA;
 }
 
 if(y!=1 && y!=0)
 {
 goto FIM;
 }
  return 0;
 }