Linguagem Progr C

4,140 views

Published on

Excelente material didático sobre C da UTFPR. Deriva do material de um curso à distância da UFMG oferecido de 1997 à 2005.

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,140
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
259
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Linguagem Progr C

  1. 1.                   Linguagem de Programação C   
  2. 2.              Esta  apostila  foi  elaborada  a  partir  da  versão  .doc  da  apostila  que  foi  foi  elaborada  por  Henrique  José  dos  Santos  (Eng.  da  Computação,  UNISANTOS,  Santos‐SP) e posteriormente utilizada pela UFMG e atualmente mantida por pelo  professor Renato Cardoso Mesquita  Alguns  capítulos  foram  modificados  e/ou  inseridos  pelos  professores  Roberto  Teixeira  Alves  e  Rodrigo  Janasievicz  Gomes  Pinheiro  para  atender  o  conteúdo que desejamos abordar no curso de extensão da UTFPR.   
  3. 3. ÍNDICE 1.  INTRODUÇÃO ................................................................................................................................................... 5  1.1.  VISÃO GERAL DE UM PROGRAMA C ............................................................................................................... 6  2.  SINTAXE............................................................................................................................................................. 8  2.1.  O C É quot;CASE SENSITIVEquot; .............................................................................................................................. 8  2.2.  PALAVRAS RESERVADAS DO C ..................................................................................................................... 9  2.3.  IDENTIFICADORES ......................................................................................................................................... 9  2.4.  TIPOS ............................................................................................................................................................ 9  2.5.  DECLARAÇÃO E INICIALIZAÇÃO DE VARIÁVEIS .......................................................................................... 10  2.6.  CONSTANTES .............................................................................................................................................. 13  2.7.  CARACTERES DE CONTROLE DA LINGUAGEM C ........................................................................................... 14  2.8.  INSTRUÇÕES ................................................................................................................................................ 15  2.9.  OPERADORES ARITMÉTICOS ....................................................................................................................... 15  2.10.  OPERADORES RELACIONAIS E LÓGICOS ...................................................................................................... 17  2.11.  OPERADORES LÓGICOS BIT A BIT ............................................................................................................... 18  2.12.  EXPRESSÕES ............................................................................................................................................... 19  2.13.  TABELA DE PRECEDÊNCIAS DO C ................................................................................................................ 21  2.14.  ESPAÇAMENTO E PARÊNTESES .................................................................................................................... 21  2.15.  ESTRUTURA DE UM PROGRAMA EM C.......................................................................................................... 21  3.  FUNÇÕES BÁSICAS DE ENTRADA E SAÍDA ........................................................................................... 23  3.1.  FUNÇÃO PRINTF( ) (BIBLIOTECA STDIO.H)............................................................................................. 23  3.2.  DOIS PRIMEIROS PROGRAMAS .................................................................................................................... 26  4.  ESTRUTURAS DE CONTROLE ................................................................................................................... 29  4.1.  COMANDO SIMPLES ..................................................................................................................................... 29  4.2.  BLOCO DE COMANDOS ................................................................................................................................ 29  4.3.  ESTRUTURAS DE SELEÇÃO .......................................................................................................................... 29  4.4.  ESTRUTURAS DE REPETIÇÃO ....................................................................................................................... 34  5.  VETORES, MATRIZES E STRING .............................................................................................................. 41  5.1.  VETORES ..................................................................................................................................................... 41  5.2.  STRINGS ...................................................................................................................................................... 43  5.3.  MATRIZES ................................................................................................................................................... 46  6.  PONTEIROS ..................................................................................................................................................... 49  6.1.  INTRODUÇÃO .............................................................................................................................................. 49  6.2.  COMO FUNCIONAM OS PONTEIROS ............................................................................................................. 49  6.3.  DECLARAÇÃO DE PONTEIROS ..................................................................................................................... 50  6.4.  OPERADORES & E * ..................................................................................................................................... 50  6.5.  PROBLEMAS NO USO DE PONTEIROS ............................................................................................................ 51  6.6.  OPERAÇÕES ELEMENTARES COM PONTEIROS .............................................................................................. 52  6.7.  PONTEIROS E VETORES ............................................................................................................................... 53  6.8.  PONTEIROS E STRINGS ................................................................................................................................ 55  6.9.  VETORES DE PONTEIROS ............................................................................................................................. 55  6.10.  PONTEIROS PARA PONTEIROS ...................................................................................................................... 56  7.  FUNÇÕES ......................................................................................................................................................... 57   
  4. 4. 7.1.  VALORES DE RETORNO POR FUNÇÕES ........................................................................................................ 58  7.2.  LOCALIZAÇÃO DAS FUNÇÕES ...................................................................................................................... 59  7.3.  ESCOPO DE VARIÁVEIS ............................................................................................................................... 62  7.4.  PASSAGEM POR VALOR ............................................................................................................................... 64  7.5.  PASSAGEM POR REFERÊNCIA ...................................................................................................................... 65  7.6.  PASSANDO VETORES PARA FUNÇÕES .......................................................................................................... 66  7.7.  PASSAGEM DE MATRIZ PARA FUNÇÃO ......................................................................................................... 67  7.8.  RECURSIVIDADE ......................................................................................................................................... 68  7.9.  ARGUMENTOS ARGC E ARGV DO MAIN ........................................................................................................ 69  8.  DIRETIVAS DE COMPILAÇÃO ................................................................................................................... 71  8.1.  A DIRETIVA INCLUDE .................................................................................................................................. 71  8.2.  AS DIRETIVAS DEFINE E UNDEF ................................................................................................................... 71  8.3.  AS DIRETIVAS IFDEF E ENDIF ..................................................................................................................... 73  8.4.  A DIRETIVA IFNDEF .................................................................................................................................... 74  8.5.  A DIRETIVA IF ............................................................................................................................................ 74  8.6.  A DIRETIVA ELSE ........................................................................................................................................ 74  8.7.  A DIRETIVA ELIF ........................................................................................................................................ 75  9.  MANIPULAÇÃO DE ARQUIVOS ................................................................................................................. 77  9.1.  INTRODUÇÃO .............................................................................................................................................. 77  9.2.  LENDO E ESCREVENDO CARACTERES EM ARQUIVOS .................................................................................. 80  9.3.  OUTROS COMANDOS DE ACESSO A ARQUIVOS ........................................................................................... 83  9.4.  FLUXOS PADRÃO ........................................................................................................................................ 87  10.  TIPOS DE DADOS AVANÇADOS ............................................................................................................ 89  10.1.  MODIFICADORES DE ACESSO ...................................................................................................................... 89  10.2.  CONVERSÃO DE TIPOS ................................................................................................................................ 91  10.3.  MODIFICADORES DE FUNÇÕES .................................................................................................................... 92  10.4.  PONTEIROS PARA FUNÇÕES ......................................................................................................................... 93  10.5.  ALOCAÇÃO DINÂMICA ................................................................................................................................ 94  10.6.  ALOCAÇÃO DINÂMICA DE VETORES E MATRIZES ....................................................................................... 97  11.  TIPOS DE DADOS DEFINIDOS PELO USUÁRIO. ............................................................................. 101  11.1.  ESTRUTURAS - PRIMEIRA PARTE ............................................................................................................... 101  11.2.  ESTRUTURAS - SEGUNDA PARTE ............................................................................................................... 103  11.3.  DECLARAÇÃO UNION................................................................................................................................ 106  11.4.  ENUMERAÇÕES ......................................................................................................................................... 107  11.5.  O COMANDO SIZEOF ................................................................................................................................. 108  11.6.  O COMANDO TYPEDEF ............................................................................................................................... 109  11.7.  UMA APLICAÇÃO DE STRUCTS: AS LISTAS SIMPLESMENTE ENCADEADAS .................................................. 110  12.  CONCEITOS BÁSICOS DE C++ ............................................................................................................. 114  12.1.  O QUE É PROGRAMAÇÃO ORIENTADA À OBJETOS?..................................................................................... 114  12.2.  CARACTERÍSTICAS PRINCIPAIS DE UMA LINGUAGEM ORIENTADA AO OBJETO ................ 115  12.3.  ELEMENTOS DA LINGUAGEM C++ ................................................................................................... 115     
  5. 5. 1. INTRODUÇÃO  Um programa de computador é um conjunto instruções que representam um algoritmo para  a  resolução  de  algum  problema.  Estas  instruções  são  escritas  através  de  um  conjunto  de  códigos  (símbolos  e  palavras).  Este  conjunto  de  códigos  possui  regras  de  estruturação  lógica  e  sintática  própria. Dizemos que este conjunto de símbolos e regras formam uma linguagem de programação.  Podemos dividir, genericamente, as linguagens de programação em dois grandes grupos: as  linguagens de baixo nível e as de alto nível:  Linguagens  de  baixo  nível:  São  linguagens  voltadas  para  a  máquina,  isto  é,  são  escritas  usando  as  instruções  do  microprocessador  do  computador.  São  genericamente  chamadas  de  linguagens Assembly.  Vantagens:  Programas  são  executados  com  maior  velocidade  de  processamento.  Os  programas ocupam menos espaço na memória.   Desvantagens:  Em  geral,  programas  em  Assembly  têm  pouca  portabilidade,  isto  é,  um  código  gerado  para  um  tipo  de  processador  não  serve  para  outro.  Códigos  Assembly  não  são  estruturados, tornando a programação mais difícil.    Linguagens  de  alto  nível:  São  linguagens  voltadas  para  o  ser  humano.  Em  geral  utilizam  sintaxe  estruturada  tornando  seu  código  mais  legível.  Necessitam  de  compiladores  ou  interpretadores para gerar instruções do microprocessador. Interpretadores fazem  a interpretação  de cada instrução do programa fonte executando‐a dentro de um ambiente de programação, Basic e  AutoLISP  por  exemplo.  Compiladores  fazem  a  tradução  de  todas  as  instruções  do  programa  fonte  gerando um programa executável. Estes programas executáveis (*.exe) podem ser executados fora  dos  ambientes  de  programação,  C  e  Pascal  por  exemplo.  As  linguagens  de  alto  nível  podem  se  distinguir quanto a sua aplicação em genéricas como C, Pascal e Basic ou específicas como Fortran  (cálculo matemático), GPSS (simulação), LISP (inteligência artificial) ou CLIPPER (banco de dados).  Vantagens:  Por  serem  compiladas  ou  interpretadas,  tem  maior  portabilidade  podendo  ser  executados em varias plataformas com pouquíssimas modificações. Em geral, a programação torna‐ se mais fácil por causa do maior ou menor grau de estruturação de suas linguagens.   Desvantagens: Em geral, as rotinas geradas (em linguagem de maquina) são mais genéricas e  portanto mais complexas e por isso são mais lentas e ocupam mais memória.  Mas o que é C? C é o nome de uma linguagem atualmente utilizada em diferentes áreas e  propósitos. Faz parte hoje de uma linguagem considerada avançada, desenvolvida nos laboratórios  Bell nos anos 70.  A  definição  formal  da  linguagem  pode  ser  encontrada  no  livro  “The  C  Programming  Language” de Brian W. Kernighan e Dennis M. Ritchie (os pais da linguagem). Nos anos 80 iniciou‐se  5 
  6. 6.   um  trabalho  de  criação  de  um  padrão  chamado  C  ANSI  (American  National  Standardization  Institute).  É  uma  linguagem  de  nível  médio,  pois  pode‐se  trabalhar  em  um  nível  próximo  ao  da  máquina ou como uma linguagem de alto nível como outras existentes.  Com o C podemos escrever programas concisos, organizados e de fácil entendimento, mas  infelizmente  a  falta  de  disciplina  pode  gerar  programas  mal  escritos,  difíceis  de  serem  lidos  e  compreendidos.  Não  se  deve  esquecer  que  C  é  uma  linguagem  para  programadores,  pois  impõe  poucas restrições ao que pode ser feito. O C é amigável e estruturado para encorajar bons hábitos  de programação; cabe ao programador exercitar esses hábitos.  A necessidade de escrever programas, que façam uso de recursos da linguagem de máquina  de uma  forma mais  simples e  portátil, fez  com que  a principal utilização do C  fosse a reescrita do  sistemas  operacional  UNIX  e  deu  origem  a  outras  linguagens  de  programação,  entre  elas  a  linguagem C++ e Java. Sua indicação é principalmente no desenvolvimento de programas, tais como:  compiladores, interpretadores, editores de texto; banco de dados. Computação gráfica, manipulação  e processamento de imagens, controle de processos, …  Principais características da linguagem C a serem ponderadas:  • Portabilidade  • Geração de códigos executáveis compactos e rápidos  • Interação com o sistema operacional  • Facilidade de uso (através de ambientes como o Borland C++ 5.0)  • Linguagem estruturada  • Confiabilidade   • Simplicidade    1.1. Visão geral de um programa C  A geração do programa executável a partir do programa fonte obedece a uma seqüência de  operações antes de tornar‐se um executável. Depois de escrever o módulo fonte em um editor de  textos,  o  programador  aciona  o  compilador  que  no  UNIX  é  chamado  pelo  comando  cc.  Essa  ação  desencadeia  uma  seqüência  de  etapas,  cada  qual  traduzindo  a  codificação  do  usuário  para  uma  forma de linguagem de nível inferior, que termina com o executável criado pelo lincador.  6 
  7. 7.   Editor (módulo fonte em C)    Pré‐processador (novo fonte expandido)    Compilador (arquivo objeto)    Lincador (executável)    7 
  8. 8.   2. Sintaxe  A  sintaxe  são  regras  detalhadas  para  cada  construção  válida  na  linguagem  C.  Estas  regras  estão relacionadas com os tipos, as declarações, as funções e as expressões.  Os tipos definem as propriedades dos dados manipulados em um programa.  As  declarações  expressam  as  partes  do  programa,  podendo  dar  significado  a  um  identificador, alocar memória, definir conteúdo inicial, definir funções.  As funções especificam as ações que um programa executa quando roda.   A  determinação  e  alteração  de  valores,  e  a  chamada  de  funções  de  entrada  e  saída  (imput/output ‐  I/O) são definidas nas expressões.  As funções são as entidades operacionais básicas dos programas em C, que por sua vez são a  união de uma ou mais funções executando cada qual o seu trabalho. Há funções básicas que estão  definidas  na  biblioteca  C.  As  funções  printf()  e  scanf()  por  exemplo,  permitem  respectivamente escrever na tela e ler os dados a partir do teclado. O programador também pode  definir novas funções em seus programas, como rotinas para cálculos, impressão, etc.   Todo programa C inicia sua execução chamando a função main(), sendo obrigatória a sua  declaração no programa principal.  Comentários  no  programa  são  colocados  entre  /*  e  */  não  sendo  considerados  na  compilação.  Cada instrução encerra com ; (ponto e vírgula) que faz parte do comando.  Exemplo:  main() /* função obrigatória */ { printf(quot;oiquot;); } 2.1. O C é quot;Case Sensitivequot;  Vamos  começar  o  nosso  curso  ressaltando  um  ponto  de  suma  importância:  o  C  é  quot;Case  Sensitivequot;, isto  é,  maiúsculas  e  minúsculas  fazem  diferença.  Se declarar  uma  variável com  o  nome  soma ela será diferente de Soma, SOMA, SoMa ou sOmA. Da mesma maneira, os comandos do C  if  e  for,  por  exemplo,  só  podem  ser  escritos  em  minúsculas  pois  senão  o  compilador  não  irá  interpretá‐los como sendo comandos, mas sim como variáveis.      8 
  9. 9.   2.2. Palavras Reservadas do C  Todas  as  linguagens  de  programação  têm  palavras  reservadas.  As  palavras  reservadas  não  podem ser usadas a não ser nos seus propósitos originais, isto é, não podemos declarar funções ou  variáveis com os mesmos nomes. Como o C é quot;case sensitivequot; podemos declarar uma variável For,  apesar  de  haver  uma  palavra  reservada  for,  mas  isto  não  é  uma  coisa  recomendável  de  se  fazer  pois pode gerar confusão.      Apresentamos  a  seguir  as  palavras  reservadas  do  ANSI  C.  Veremos  o  significado  destas palavras chave à medida que o curso for progredindo:  auto    double    int    struct    break    else    long     switch    case    enum    register    typedef    char    extern    return    union    const    float    short    unsigned    continue    for    signed    void    default    goto    sizeof    volatile    do  if  static  while    2.3. Identificadores  São  utilizados  para  dar  nomes  a  constantes,  variáveis,  funções  e  vários  objetos  definidos  pelo usuário. As regras para formação desses nomes são:    • Todo identificador deve iniciar por uma letra (a..z ou A..Z) ou um sublinhado  • Não  pode  conter  símbolos  especiais.  Após  o  primeiro  caracter  pode  ser  utilizado:  letras, sublinhados e/ou dígitos.  • Utiliza‐se  identificadores  de,  no  máximo,  32  caracteres  por  estes  serem  significativos.  • Não pode ser palavra reservada e nem nome de funções de bibliotecas.    2.4. Tipos  Quando  você  declara  um  identificador  dá  a  ele  um  tipo.  O  C  tem  5  tipos  básicos:  char,  int, float, void, double. Objetos do tipo char representam caracteres, objetos do tipo int  representam  valores  inteiros  e  objetos  do  tipo  float  representam  números  reais  (ponto  flutuante).  O  double  é  o  ponto  flutuante  duplo  e  pode  ser  visto  como  um  ponto  flutuante  com  muito mais precisão.  O void é o tipo vazio, ou um quot;tipo  sem  tipoquot;.  A  aplicação deste quot;tipoquot;  será  vista posteriormente.  9 
  10. 10.   Para cada um dos tipos de variáveis existem os modificadores de tipo. Os modificadores de  tipo do C são quatro: signed, unsigned, long e short. Ao float não se pode aplicar nenhum  e  ao  double  pode‐se  aplicar  apenas  o  long.  Os  quatro  modificadores  podem  ser  aplicados  a  inteiros. A intenção é que short e long devam prover tamanhos diferentes de inteiros onde isto  for  prático.  Inteiros  menores  (short)  ou  maiores  (long).  int  normalmente  terá  o  tamanho  natural para uma determinada máquina. Assim, numa máquina de 16 bits, int provavelmente terá  16 bits. Numa máquina de 32 bits, int deverá ter 32 bits. Na verdade, cada compilador é livre para  escolher tamanhos adequados para o seu próprio hardware, com a única restrição de que shorts ints e ints devem ocupar pelo menos 16 bits, longs ints pelo menos 32 bits, e short int  não pode ser maior que int, que não pode ser maior que long int. O modificador unsigned serve  para  especificar  variáveis  sem  sinal.  Um  unsigned int  será  um  inteiro  que  assumirá  apenas valores positivos. A seguir estão listados os tipos de dados permitidos e seu valores máximos  e  mínimos  em  um  compilador  típico  para  um  hardware  de  16  bits.  Também  nesta  tabela  está  especificado o formato que deve ser utilizado para ler os tipos de dados com a função scanf():  Formato para  Intervalo  Tipo  Num de bits  leitura com  Inicio  Fim  scanf  char  8  %c  ‐128  127  unsigned char 8  %c 0 255  signed char  8  %c  ‐128  127  Int  16  %i  ‐32.768  32.767  unsigned int  16  %u  0  65.535   signed int  16  %i ‐32.768 32.767  short int  16  %hi  ‐32.768  32.767  unsigned short int  16  %hu  0  65.535  signed short int  16  %hi  ‐32.768  32.767   long int  32  %li ‐2.147.483.648 2.147.483.647 signed long int  32  %li  ‐2.147.483.648  2.147.483.647  unsigned long int  32  %lu  0  4.294.967.295  float  32  %f  3,4E‐38  3.4E+38   double  64  %lf 1,7E‐308 1,7E+308  long double  80  %Lf  3,4E‐4932   3,4E+4932    O  tipo  long double  é  o  tipo  de  ponto  flutuante  com  maior  precisão.  É  importante  observar  que  os  intervalos  de  ponto  flutuante,  na  tabela  acima,  estão  indicados  em  faixa  de  expoente, mas os números podem assumir valores tanto positivos quanto negativos.  2.5. Declaração e Inicialização de Variáveis  As variáveis no C devem ser declaradas antes de serem usadas. A forma geral da declaração  de variáveis é:   tipo_da_variável lista_de_variáveis; 10 
  11. 11.   As  variáveis  da  lista  de  variáveis  terão  todas  o  mesmo  tipo  e  deverão  ser  separadas  por  vírgula.  Como  o  tipo  default  do  C  é  o  int,  quando  vamos  declarar  variáveis  int  com  algum  dos  modificadores  de  tipo,  basta  colocar  o  nome  do  modificador  de  tipo.  Assim  um  long  basta  para  declarar um long int.   Por exemplo, as declarações   char ch, letra; long count; float pi; declaram duas variáveis do tipo char (ch e letra), uma variável long int (count) e  um float pi.   Onde as variáveis podem ser declaradas   Há três lugares nos quais podemos declarar variáveis.   O primeiro é fora de todas as funções do programa. Estas variáveis são chamadas variáveis  globais e podem ser usadas a partir de qualquer lugar no programa. Pode‐se dizer que, como elas  estão fora de todas as funções, todas as funções as vêem. Estas variáveis são alocadas estaticamente  na memória RAM.  O segundo lugar no qual se pode declarar variáveis é no início de um bloco de código. Estas  variáveis são chamadas locais e só têm validade dentro do bloco no qual são declaradas, isto é, só a  função  à  qual  ela  pertence  sabe  da  existência  desta  variável,  dentro  do  bloco  no  qual  foram  declaradas. Estas variáveis são alocadas dinamicamente na memória RAM. Depois que uma função é  executada, estas variáveis são desalocadas.   O terceiro  lugar onde  se  pode  declarar variáveis é  na  lista de  parâmetros  de uma  função.  Mais uma vez, apesar de estas variáveis receberem valores externos, estas variáveis são conhecidas  apenas pela função onde são declaradas e também são alocadas dinamicamente na memória RAM.   Veja o programa abaixo:   #include <stdio.h> int contador; int func1(int j) { /* aqui viria o código da funcao ... */ } int main(){ char condicao; int i; for (i=0; i<100; i=i+1){ /* Bloco do for */ float f2; /* etc ... ... */ 11 
  12. 12.   func1(i); } /* etc ... */ return(0); } A variável contador é uma variável global, e é acessível de qualquer parte do programa.  As variáveis condicao  e i, só existem dentro de main(), isto é são variáveis locais de main. A  variável float f2 é um exemplo de uma variável de bloco, isto é, ela somente é conhecida dentro  do bloco do for, pertencente à função main. A variável inteira j é um exemplo de declaração na  lista de parâmetros de uma função (a função func1).   As regras que regem onde uma variável é válida chamam‐se regras de escopo da variável. Há  mais dois detalhes que devem ser ressaltados. Duas variáveis globais não podem ter o mesmo nome.  O mesmo vale para duas variáveis locais de uma mesma função. Já duas variáveis locais, de funções  diferentes, podem ter o mesmo nome sem perigo algum de conflito.     Alocação de memória: Reserva de espaço de memória (RAM) para alocar uma variável.  • Alocação estática de memória: Tipo de alocação de memória em que uma variável é alocada  (tem um espaço  reservado)  na  memória  RAM durante toda a  execução  do  programa.  Este  espaço de memória é desalocado somente quando o programa acaba.  • Alocação  dinâmica  de  memória:  Tipo  de  alocação  de  memória  em  que  uma  variável  é  alocada  (tem  um  espaço  reservado)  na  memória  RAM  temporariamente.  Este  espaço  de  memória é desalocado quando o espaço não é mais necessário.  Podemos inicializar variáveis no momento de sua declaração. Para fazer isto podemos usar a  forma geral   tipo_da_variável nome_da_variável = constante; Isto é importante pois quando o C cria uma variável ele não a inicializa. Isto significa que até  que um primeiro valor seja atribuído à nova variável ela tem um valor indefinido e que não pode ser  utilizado para nada. Nunca presuma que uma variável declarada vale zero ou qualquer outro valor.  Exemplos de inicialização são dados abaixo :    char ch='D'; int count=0; float pi=3.141; Ressalte‐se novamente que, em C, uma variável tem que ser declarada no início de um bloco  de código. Assim, o programa a seguir não é válido em C (embora seja válido em C++).  int main(){ int i; int j; j = 10; 12 
  13. 13.   int k = 20; /* Esta declaracao de variável não é válida, pois não está sendo feita no início do bloco */ return(0); } 2.6. Constantes  Muitas  vezes  identificamos  uma  constante  numérica  por  um  símbolo:  Pi  =  3,14159  por  exemplo.  Podemos  definir  um  nome  simbólico  para  esta  constante,  isto  é,  podemos  definir  uma  constante  simbólica  que  represente  valor.  O  programador  pode  definir  constantes  simbólicas  em  qualquer programa, e sua sintaxe é a seguinte:  #define nome valor onde  #define  é  uma  diretiva  de  compilação  que  diz  ao  compilador  para  trocar  as  ocorrências do texto nome por valor. Observe que não há ; no final da instrução pois se trata de  um comando para o compilador e não para o processador. A  instrução #define deve ser escrita  antes da instrução de declaração da rotina principal.  Exemplo: a seguir definimos algumas constantes simbólicas.  #define PI 3.14159 #define ON 1 #define OFF 0 #define ENDERECO 0x378 int main(){ ... No exemplo acima, definimos PI como 3.14159. Isto significa que todas as ocorrências do  texto PI será trocado por 3.14159. Assim se escrevemos uma instrução:  área = PI * raio * raio; o compilador vai interpretar esta instrução como se fosse escrita assim:  área = 3.14159 * raio * raio; Poderíamos escrever estas instruções assim:  float pi = 3.14159; área = pi * área * área; porém este tipo de instrução tem duas desvantagens: Primeiro, reserva 4 bytes de memória  desnecessariamente.  Segundo,  esta  instrução  é  executada  mais  lentamente  pois  o  processador  precisa acessar a memória para verificar qual é o valor de pi.  Observe  também  que  no  exemplo  definimos  os  nomes  simbólicos  com  letras  maiúsculas.  Isto não é necessário, podemos  perfeitamente definir  nomes  simbólicos  usando  letras  minúsculas,  porém  faz  parte  do  jargão  dos  programadores  C  usar  letras  maiúsculas  para  definir  constantes  simbólicas.  13 
  14. 14.   O uso da diretiva #define não se restringe apenas ao apresentado acima, podemos usá‐la  para definir macro instruções. Este uso será detalhado nas próximas seções.  Constantes dos tipos básicos do C  Tipo de Dado  Exemplos de Constantes  char  'b' 'n' '0'  int  2 32000 ‐130 long int  100000 ‐467  short int  100 ‐30  unsigned int  50000 35678  float  0.0 23.7 ‐12.3e‐10 double  12546354334.0 ‐0.0000034236556    Constantes octais e hexadecimais  Muitas  vezes  precisamos  inserir  constantes  hexadecimais  (base  dezesseis)  ou  octais  (base  oito) no nosso programa. O C permite que se faça isto. As constantes hexadecimais começam com  0x. As constantes octais começam em 0.  Alguns exemplos:   Constante  Tipo 0xEF  Constante Hexadecimal (8 bits)  0x12A4  Constante Hexadecimal (16 bits)  03212  Constante Octal (12 bits)  034215432  Constante Octal (24 bits)    Nunca  escreva  portanto  013  achando  que  o  C  vai  compilar  isto  como  se  fosse  13.  Na  linguagem C 013 é diferente de 13!    2.7. Caracteres de controle da linguagem C  Estes  caracteres  devem  ser  representados  como  caracteres  alfanuméricos  (entre  ‘  ‘)  ou  como conteúdo de uma string.  Código  Significado b   Retrocesso (quot;backquot;) f    Alimentação de formulário (quot;form feedquot;) n    Nova linha (quot;new linequot;) t    Tabulação horizontal (quot;tabquot;)   quot;    Aspas    '    Apóstrofo    0     Nulo (0 em decimal)     Barra invertida 14 
  15. 15.   v    Tabulação vertical a   Sinal sonoro (quot;beepquot;) N    Constante octal (N é o valor da constante) xN  Constante hexadecimal (N é o valor da constante)   2.8. Instruções  Uma  instrução  em linguagem  C é uma  expressão  seguida  de  um  ponto e vírgula. Pode ser  uma atribuição, uma chamada de função, um teste de desvio ou um teste de laço.  Exemplo de instrução de atribuição:  x = 12; onde  o  sinal  de  igual  (=)  é  o  operador  de  atribuição.  Note‐se  que  o  operando  do  lado  esquerdo do operador de atribuição é sempre uma variável, e que o operando do lado direito deve  ser de um tipo de dado compatível com o tipo da variável.  A  linguagem  de  programação  C  permite  utilizar  o  operador  de  atribuição  em  expressões,  junto com operadores matemáticos, lógicos, relacionais, chamada de funções, e outros.  if ((produto = x * y) < 0) Funcionamento: Primeiramente C atribui o valor x * y a variável produto, para depois  avaliar a expressão, ou seja, comparar se o produto é menor (<) que zero.    2.9. Operadores Aritméticos  Os  operadores  aritméticos  são  usados  para  desenvolver  operações  matemáticas.  A  seguir  apresentamos a lista dos operadores aritméticos do C:  Operador Ação + Soma (inteira e ponto flutuante) - Subtração ou Troca de sinal (inteira e ponto flutuante) * Multiplicação (inteira e ponto flutuante) / Divisão (inteira e ponto flutuante) % Resto de divisão (de inteiros) ++ Incremento (inteiro e ponto flutuante) -- Decremento (inteiro e ponto flutuante)   O  C  possui  operadores  unários  e  binários.  Os  unários  agem  sobre  uma  variável  apenas,  modificando ou não o seu valor, e retornam o valor final da variável. Os binários usam duas variáveis  e retornam um terceiro valor, sem alterar as variáveis originais. A soma é um operador binário, pois  pega  duas  variáveis,  soma  seus  valores,  sem  alterar  as  variáveis,  e  retorna  esta  soma.  Outros  operadores binários são os operadores ‐ (subtração), *, / e %. O operador ‐ como troca de sinal é um  15 
  16. 16.   operador unário que não altera a variável sobre a qual é aplicado, pois ele retorna o valor da variável  multiplicado por ‐1.   O  operador  /  (divisão)  quando  aplicado  a  variáveis  inteiras,  nos  fornece  o  resultado  da  divisão inteira; quando aplicado a variáveis em ponto flutuante nos fornece o resultado da divisão  “real”. O operador % fornece o resto da divisão de dois inteiros.   Assim seja o seguinte trecho de código:   int a = 17, b = 3; int x, y; float z = 17., z1, z2; x = a / b; y = a % b; z1 = z / b; z2 = a/b; ao final da execução destas linhas, os valores calculados seriam  x = 5,  y = 2,  z1 = 5.666666  e  z2 = 5.0.  Note  que,  na  linha  correspondente  a  z2,  primeiramente  é  feita  uma  divisão  inteira  (pois  os  dois  operandos  são  inteiros).  Somente  após  efetuada  a  divisão  é  que  o  resultado é atribuído a uma variável float.  Os operadores de incremento e decremento são unários que alteram a variável sobre a qual  estão  aplicados.  O  que  eles  fazem  é  incrementar  ou  decrementar,  a  variável  sobre  a  qual  estão  aplicados, de 1. Então:  x++; x--; são equivalentes a:  x=x+1; x=x-1; Estes operadores podem ser pré‐fixados ou pós‐ fixados. A diferença é que quando são pré‐ fixados eles incrementam e retornam o valor da variável já incrementada. Quando são pós‐fixados  eles retornam o valor da variável sem o incremento e depois incrementam a variável. Então, em:   x=23; y=x++; teremos, no final, y=23 e x=24. Em:  x=23; y=++x; teremos, no final, y=24 e x=24.    16 
  17. 17.   Observações:  • Todos  os  operadores  são  definidos  para  os  tipos  inteiros  e  não  inteiros,  exceto  o  operador resto (%) que não é definido para variáveis dos tipos não inteiros.  • Para  qualquer tipo  inteiro, a adição de um  ao maior número da faixa  daquele tipo  produz o menor número da faixa. Os erros de estouro nem sempre são detectados,  cabendo  ao  programador  tomar  cuidado  ao  dimensionar  as  variáveis  do  programa  para que eles não ocorram.  Exemplo:  unsigned char x; x = 255; x = x + 1; /* x deveria assumir 256, no entanto estoura a faixa e retorna para o menor valor que é 0 */   2.10. Operadores relacionais e Lógicos  São operadores que permitem comparar valores, ou seja, são utilizados principalmente em  comandos que possuem condições:  Operador Ação > Maior do que >= Maior ou igual a < Menor do que <= Menor ou igual a == Igual a != Diferente de   Os  operadores  relacionais  retornam  verdadeiro  (1)  ou  falso  (0).  Para  verificar  o  funcionamento dos operadores relacionais, execute o programa abaixo:  /* Este programa ilustra o funcionamento dos operadores relacionais. */ #include <stdio.h> int main(){ int i, j; printf(quot;nEntre com dois números inteiros: quot;); scanf(quot;%d%dquot;, &i, &j); printf(quot;n%d == %d é %dnquot;, i, j, i==j); printf(quot;n%d != %d é %dnquot;, i, j, i!=j); printf(quot;n%d <= %d é %dnquot;, i, j, i<=j); printf(quot;n%d >= %d é %dnquot;, i, j, i>=j); printf(quot;n%d < %d é %dnquot;, i, j, i<j); printf(quot;n%d > %d é %dnquot;, i, j, i>j); return(0); } 17 
  18. 18.   Você pode notar que o resultado dos operadores relacionais é sempre igual a 0 (falso) ou 1  (verdadeiro).  Para fazer operações com valores lógicos (verdadeiro e falso) temos os operadores lógicos:     Operador Ação && AND (E) || OR (OU) ! NOT (NÃO)   Exemplo: No trecho de programa abaixo a operação j++ será executada, pois o resultado da  expressão lógica é verdadeiro:  int i = 5, j =7; if ( (i > 3) && ( j <= 7) && ( i != j) ) j++; V AND V AND V =V   2.11. Operadores Lógicos Bit a Bit  O  C  permite  que  se  faça  operações  lógicas  quot;bit‐a‐bitquot;  em  números.  Ou  seja,  neste  caso,  o  número é representado por sua forma binária e as operações são feitas em cada bit dele. Imagine  um número inteiro de 16 bits, a variável i, armazenando o valor 2. A representação binária de i,  será: 0000000000000010 (quinze zeros e um único 1 na segunda posição da direita para a esquerda).  Poderemos fazer operações em cada um dos bits deste número. Por exemplo, se fizermos a negação  do  número  (operação  binária  NOT,  ou  operador  binário  ~  em  C),  isto  é,  ~i,  o  número  se  transformará  em  1111111111111101.  As  operações  binárias  ajudam  programadores  que  queiram  trabalhar com o computador em quot;baixo nívelquot;. As operações  lógicas bit a bit só podem ser usadas  nos tipos char, int e long int. Os operadores são:  Operador  Ação &  AND |  OR ^  XOR (OR exclusivo) ~  NOT >>  Deslocamento de bits à direita <<  Deslocamento de bits à esquerda   Os operadores &, |, ^ e ~ são as operações lógicas bit a bit. A forma geral dos operadores de  deslocamento é:   valor>>número_de_deslocamentos valor<<número_de_deslocamentos O  número_de_deslocamentos  indica  o  quanto  cada  bit  irá  ser  deslocado.    Por  exemplo, para a variável i anterior, armazenando o número 2:   18 
  19. 19.   i << 3; fará  com  que  i  agora  tenha  a  representação  binária:    0000000000010000,  isto  é,  o  valor  armazenado em i passa a ser igual a 16.    2.12. Expressões  Expressões  são  combinações  de  variáveis,  constantes  e  operadores.  Quando  montamos  expressões  temos  que  levar  em  consideração  a  ordem  com  que  os  operadores  são  executados,  conforme a tabela de precedências da linguagem C.   Exemplos de expressões:   Anos=Dias/365.25; i = i+3; c = a*b + d/e; c = a*(b+d)/e; Conversão de tipos em expressões  Quando o C avalia expressões onde temos variáveis de tipos diferentes o compilador verifica  se as conversões são possíveis. Se não são, ele não compilará o programa, dando uma mensagem de  erro. Se as conversões forem possíveis ele as faz, seguindo as regras abaixo:     • Todos  os  chars  e  short ints  são  convertidos  para  ints.  Todos  os  floats  são convertidos para doubles.   • Para pares de operandos de tipos diferentes: se um deles é long double o outro  é  convertido  para  long double;  se  um  deles  é  double  o  outro  é  convertido  para double; se um é long o outro é convertido para long; se um é unsigned  o outro é convertido para unsigned.   Exemplo:  float x, res; char c; ... res = x/c; /* o valor de x/c é convertido para um float, embora c seja originalmente um char */    Conversão explícita de tipos (type casts)  É possível forçar uma expressão a ser de um tipo específico, sem no entanto mudar os tipos  das  variáveis  envolvidas  nesta  expressão.  Esse  tipo  de  operação  chama‐se  conversão  explícita  de  tipo, ou type cast.  A forma geral de um type cast é:  19 
  20. 20.   (tipo) expressão; onde tipo é um dos tipos de dado padrão da linguagem C.  As operações de type cast são muito úteis em expressões nas quais alguma operação resulta  em perda de precisão devido ao tipo das variáveis ou constantes envolvidas. Por exemplo:  float res; int op1,op2; op1 = 3; op2 = 2; res = op1 / op2; /* res recebe 1, já que op1 e op2 são ambos números do tipo int e o resultado da sua divisão também é int */ res = (float)op1 / op2; /* res recebe 1.5, já que o type cast forçou o operando op1 a ser um float nesta operação. O resultado da divisão, por consequência, também é float */ Expressões que Podem ser Abreviadas  O C admite as seguintes equivalências, que podem ser usadas para simplificar expressões ou  para facilitar o entendimento de um programa:    Expressão Original Expressão Equivalente x=x+k; x+=k; x=x‐k; x‐=k; x=x*k; x*=k; x=x/k; x/=k; x=x>>k; x>>=k; x=x<<k; x<<=k; x=x&k; x&=k; etc...   Encadeando expressões: o operador ,  O  operador  ,  determina  uma  lista  de  expressões  que  devem  ser  executadas  seqüencialmente.  Em  síntese,  a  vírgula  diz  ao  compilador:  execute  as  duas  expressões  separadas  pela vírgula, em seqüência.  O valor retornado por uma expressão com o operador , é sempre dado  pela expressão mais à direita. No exemplo abaixo:   x=(y=2,y+3); o valor 2 vai ser atribuído a y, se somará 3 a y e o retorno (5) será atribuído à variável x .  Pode‐se encadear quantos operadores ,  forem necessários.      20 
  21. 21.   2.13. Tabela de Precedências do C  Esta é a tabela de precedência dos operadores em C. Alguns (poucos) operadores ainda não  foram estudados, e serão apresentados em aulas posteriores.  Maior () [] -> ! ~ ++ -- . -(unário) */% +- << >> <<= >>= == != & ^ | && || ? = += -= *= /= Menor ,       2.14. Espaçamento e parênteses  Podemos colocar espaços em uma expressão para torná‐la mais legível. O uso de parênteses  redundantes ou adicionais não causará erros ou diminuirá a velocidade de execução da expressão.  Exemplo:  a=b/9.67-56.89*x-34.7; a = (b / 9.67) – (56.89 * x) – 34.7; /* equivalente */   2.15. Estrutura de um programa em C  Uma particularidade interessante no programa C é seu aspecto modular e funcional, em que  o  próprio  programa  principal  é  uma  função.  Esta  forma  de  apresentação  da  linguagem  facilita  o  desenvolvimento  de  programas,  pois  permite  o  emprego  de  formas  estruturadas  e  modulares  encontradas em outras linguagens.       21 
  22. 22.   A  estrutura  de  um  programa  em  C  possui  os  seguintes  elementos,  sendo  que  aqueles  delimitados por colchetes são opcionais:  [ definições de pré-processamento ] [ definições de tipo ] [ declarações de variáveis globais ] [ protótipos de funções ] [ funções ] int main ( ){ /* definições de variáveis */ /* corpo da função principal, com declarações de suas variáveis, seus comandos e funções */ } Definições de pré‐processamento são comandos interpretados pelo compilador, em tempo  de compilação, que dizem respeito a operações realizadas pelo compilador para geração de código.  Geralmente  iniciam  com  uma  cerquilha  (#)  e  não  são  comandos  da  linguagem  C  (detalhados  posteriormente).  Exemplo:   #include <stdio.h> /* comando de pré-processador, utilizado para indicar ao compilador que ele deve ´colar´ as definições do arquivo stdio.h neste arquivo antes de compilá-lo */ Definições  de  tipos  são  definições  de  estruturas  ou  tipos  de  dados  especiais,  introduzidos  pelo usuário para facilitar a manipulação de dados pelo programa (detalhados posteriormente).  Declarações de variáveis globais são feitas quando é necessário utilizar variáveis globais no  programa. O conceito de variável global e as vantagens e desvantagens do seu uso dizem respeito à  modularização (funções) de um programa em C.  Protótipos de funções e funções também dizem respeito a questões de modularização.  main()  é  a  função  principal  de  um  programa  em  C,  contendo  o  código  que  será  inicialmente executado quando o programa em si for executado. Todo programa em C deve conter a  função  main(),  do  contrário  será  gerado  um  erro  durante  o  processo  de  geração  do  programa  (mais especificamente, na etapa de ligação).  22 
  23. 23.   3. Funções básicas de entrada e saída  Esta  seção  descreve  algumas  das  funções  básicas  de  E/S,  que  serão  utilizadas  inicialmente  para  prover  o  programador  de  um  canal  de  entrada  de  dados  via  teclado  e  um  canal  de  saída  de  dados via monitor.  3.1. Função printf( )   (biblioteca stdio.h)  A função printf( ) é basicamente utilizada para enviar informações ao monitor, ou seja,  imprimir informações. O seu protótipo é o seguinte:  printf(quot;string de controlequot;, lista de variáveis); String de controle: é uma máscara que especifica (formata) o que será  impresso e de que  maneira será impresso na tela.  Exemplo:   Instrução  Saída  Ola’, Mundo!  printf(“Ola’, Mundo!“); linha 1  printf(“linha 1 nlinha 2 “); linha 2    Observe  que  na  primeira  instrução,  a  saída  é  exatamente  igual  à  string  de  controle.  Já  na  segunda instrução a impressão se deu em duas linhas. Isto se deve ao n que representa o código  ASCII para quebra de linha .  Nesta  mascara  é  possível  reservar  espaço  para  o  valor  de  alguma  variável  usando  especificadores de formato. Um especificador de formato marca o lugar e o formato de impressão  das variáveis contidas na lista variáveis. Deve haver um especificador de formato para cada variável  a ser impressa. Todos os especificadores de formato começam com um %.  Exemplo:  Código  Imprime  printf (quot;%-5.2fquot;,456.671); | 456.67|  | 2.67| printf (quot;%5.2fquot;,2.671); |Ola       |  printf (quot;%-10squot;,quot;Olaquot;);   Nos exemplos o quot;pipequot; ( | ) indica o início e o fim do campo mas não são escritos na tela.  Depois do sinal %, seguem‐se alguns modificadores, cuja sintaxe é a seguinte:  % [flag] [tamanho] [.precisão] espeficadores_formato [flag] justificação de saída: (Opcional)  23 
  24. 24.   • (-)  :  Alinha  o  resultado  à  esquerda.  Preenche  o  restante  do  campo  com  brancos.  Se  não  é  colocado,  alinha  o  resultado  à  direita  e  preenche  o  restante à esquerda com zeros ou brancos.   • (+): O resultado sempre começa com o sinal + ou ‐  • (#):  Especifica  que  o  argumento  será  impresso  usando  uma  das  formas  alternativas  [tamanho] especificação de tamanho (Opcional)  • n:  pelo  menos  n  dígitos  serão  impressos  (dígitos  faltantes  serão  completados por brancos).  • 0n:  pelo  menos  n  dígitos  serão  impressos  (dígitos  faltantes  serão  completados por zeros).  [.precisão] especificador de precisão, dígitos a direita do ponto decimal. (Opcional)  • (nada) padrão: 6 dígitos para reais.  • .0: nenhum digito decimal.  • .n: são impressos n dígitos decimais.  especificadores_formado:  comando de formatação de tipo (Requerido)  Código  Tipo  Formato String (vetor de caracteres)  s char * Inteiro decimal com sinal  d int Inteiro decimal com sinal i int Inteiro octal sem sinal  o int Inteiro decimal sem sinal  u int Inteiro hexadecimal sem sinal (com a, b, c, d, e, f)  x int Inteiro hexadecimal sem sinal (com A, B, C, D, E, F) X int Valor com sinal da forma [‐]dddd.dddd  f float Valor com sinal da forma [‐]d.dddd e [+/‐]ddd  e float Valor com sinal na forma e ou f baseado na precisão do valor dado  g float Mesmo que e, mas com E para expoente E float Mesmo que g, mas com E para expoente  G float Um caracter  c char O caracter % é impresso  % nada Armazena o número de caracteres escritos até o momento  n int * ponteiro  imprime como um ponteiro  p           24 
  25. 25.   Os principais caracteres de controle especiais que auxiliam a formação da impressão na tela  são:  Código  Significado  sinal audível  a retrocesso do cursor b alimentação de formulário  f nova linha  n retorno de carro r tabulação horizontal t aspas  ’ apóstrofo  ’ nulo (zero) 0 barra invertida  tabulação vertical  v sinal sonoro  a constante octal (onde N é um octal) N constante hexadecimal (onde N é um hexadecimal)  xN   Exemplos:  1)  int n = 15; printf(“O valor de n eh %d”, n); /* exibe ´O valor de n eh 15´. Note-se que todo o conteúdo da string de dados e formato é exibido literalmente, com exceção do especificador %d, que é substituído pelo valor em formato inteiro da variável n */ 2)  char carac = ´A´; float num = 3.16; printf(“A letra eh %c e o numero eh %f”, carac, num); /* exibe ´A letra eh A e o numero eh 3.16´. Neste caso, o especificador %c (primeiro da string) é substituído pelo valor da variável carac e o especificador %f é substituído pelo valor da variável num. Note-se que os tipos dos especificadores e das variáveis são compatíveis */   Função scanf()  (biblioteca stdio.h)  A  função  scanf  é  utilizada  para  receber  dados  de  uma  entrada  de  dados  padrão.  Consideraremos,  para  fins  de  simplificação,  que  essa  entrada  padrão  é  sempre  o  teclado.  O  protótipo de scanf é o seguinte:  scanf (string de formato, &var1, &var2, …, &varN); 25 
  26. 26.   onde a string de formato contém os especificadores de formato na seqüência e relativos a  cada  um  dos  dados  que  se  pretende  receber.  Para  uma  lista  dos  especificadores  de  formato  mais  utilizados, ver seção 3.1.  var1 a varN identificam as variáveis nas quais serão armazenados os valores recebidos por  scanf, na mesma ordem determinada pelos especificadores de formato. O número N deve ser igual  ao número de especificadores de formato fornecidos.  IMPORTANTE: o operador de endereço (&) DEVE obrigatoriamente ser utilizado diante dos  identificadores das variáveis, do contrário ocorre um erro. Para maiores detalhes, consultar a teoria  sobre ponteiros.    Exemplos:  1)  int t; printf(“Digite um inteiro: “); scanf(“%d”, &t); /* aguarda a digitação de um número do tipo int. O número digitado é armazenado na variável t quando o usuário digita ENTER */ 2) char carac1; float i; printf(“Digite um caracter e um float, separados por vírgula: “); scanf(“%c, %f”, &carac1, &i); /* neste caso, os especificadores de formato %c e %f estão separados por vírgula, o que significa que o usuário deve digitar os valores também separados por vírgula e na ordem correta */   3.2. Dois Primeiros Programas  Vejamos um primeiro programa em C:   #include <stdio.h> /* Um Primeiro Programa */ int main () { printf (quot;Ola! Eu estou vivo!nquot;); return(0); } Compilando  e  executando  este  programa  você  verá  que  ele  coloca  a  mensagem  Ola!  Eu  estou vivo! na tela.    26 
  27. 27.   Análise do Programa   A linha #include <stdio.h> diz ao compilador que ele deve incluir o arquivo‐cabeçalho  stdio.h. Neste arquivo existem declarações de funções úteis para entrada e saída de dados (std =  standard,  padrão  em  inglês;  io  =  Input/Output,  entrada  e  saída  ==>  stdio  =  Entrada  e  saída  padronizadas). Toda vez que você quiser usar uma destas funções deve‐se incluir este comando. O C  possui diversos Arquivos‐cabeçalho.   Ao  fazer  um  programa,  uma  boa  idéia  é  usar  comentários  que  ajudem  a  elucidar  o  funcionamento  do  mesmo.  No  caso  acima  temos  um  comentário:  /* Um Primeiro Programa */.  O  compilador  C  desconsidera  qualquer  coisa  que  esteja  começando  com  /* e terminando com */. Um comentário pode, inclusive, ter mais de uma linha.    A  linha  int main()  indica  que  estamos  definindo  uma  função  de  nome  main.  Todos  os  programas  em  C  têm  que  ter  uma  função  main,  pois  é  esta  função  que  será  chamada  quando  o  programa for executado. O conteúdo da função é delimitado por chaves { }. O código que estiver  dentro  das  chaves  será  executado  seqüencialmente  quando  a  função  for  chamada.  A  palavra  int  indica  que  esta  função  retorna  um  inteiro.  O  que  significa  este  retorno  será  visto  posteriormente,  quando estudarmos um pouco mais detalhadamente as funções do C. A última linha do programa,  return(0); , indica o número inteiro que está sendo retornado pela função, no caso o número 0.   A única coisa que o programa realmente faz é chamar a função printf(), passando a string  (uma  string  é  uma  seqüência  de  caracteres,  como  veremos  brevemente)  quot;Ola!  Eu  estou  vivo!nquot;  como  argumento.  É  por  causa  do  uso  da  função  printf()  pelo  programa  que  devemos  incluir  o  arquivo‐ cabeçalho stdio.h. A função printf() neste caso irá apenas colocar a string na tela do  computador.  O  n  é  uma  constante  chamada  de  constante  barra  invertida.  No  caso,  o  n  é  a  constante  barra  invertida  de  quot;new  linequot;  e  ele  é  interpretado  como  um  comando  de  mudança  de  linha, isto é, após imprimir Ola! Eu estou vivo! o cursor passará para a próxima linha. É importante  observar também que os comandos do C terminam com ; .  Podemos agora tentar um programa mais complicado:     #include <stdio.h> int main (){ int Dias; /* Declaracao de Variaveis */ float Anos; printf (quot;Entre com o número de dias: quot;); /* Entrada de Dados */ scanf (quot;%dquot;,&Dias); Anos=Dias/365.25; /* Conversao Dias->Anos */ printf (quot;nn%d dias equivalem a %f anos.nquot;,Dias,Anos); return(0); } Análise do Programa   São  declaradas  duas  variáveis  chamadas  Dias  e  Anos.  A  primeira  é  um  int  (inteiro)  e  a  segunda  um  float  (ponto  flutuante).  As  variáveis  declaradas  como  ponto  flutuante  existem  para  armazenar números que possuem casas decimais, como 5,1497.   É feita então uma chamada à função printf(), que coloca uma mensagem na tela.   27 
  28. 28.   Queremos agora ler um dado que será fornecido pelo usuário e colocá‐lo na variável inteira  Dias. Para tanto usamos a função scanf(). A string quot;%dquot; diz à função que iremos ler um inteiro.  O  segundo  parâmetro  passado  à  função  diz  que  o  dado  lido  deverá  ser  armazenado  na  variável  Dias. É importante ressaltar a necessidade de se colocar um & antes do nome da variável a ser lida  quando  se  usa  a  função  scanf().  O  motivo  disto  só  ficará  claro  mais  tarde.  Observe  que,  no  C,  quando temos mais de um parâmetro para uma função, eles serão separados por vírgula.   Temos  então  uma  expressão  matemática  simples  que  atribui  a  Anos  o  valor  de  Dias  dividido por  365.25  (365.25  é  uma  constante ponto flutuante  365,25). Como  Anos  é uma variável  float o compilador fará uma conversão automática entre os tipos das variáveis (veremos isto com  detalhes mais tarde).   A  segunda  chamada  à  função  printf()  tem  três  argumentos.  A  string  quot;nn%d dias equivalem a %f anos.nquot;  diz  à  função  para  pular  duas  linhas,  colocar  um  inteiro  na  tela,  colocar  a  mensagem  quot;dias  equivalem  aquot;,  colocar  um  valor  float  na  tela,  colocar  a  mensagem  quot;anos.quot; e pular outra linha. Os outros parâmetros são as variáveis, Dias e Anos, das quais devem  ser lidos os valores do inteiro e do float, respectivamente.    28 
  29. 29.     4. Estruturas de controle  As  estruturas  de  controle  de  fluxo  são  fundamentais  para  qualquer  linguagem  de  programação.  Sem  elas  só  haveria  uma  maneira  do  programa  ser  executado:  de  cima  para  baixo  comando por comando. Não haveria condições, repetições ou saltos. A linguagem C possui diversos  comandos de controle de fluxo. É possível resolver todos os problemas sem utilizar todas elas, mas  devemos nos lembrar que a elegância e facilidade de entendimento de um programa dependem do  uso correto das estruturas no local certo.    4.1. Comando simples  São comandos, que no fluxo de controle do programa, são sempre executados passando a  execução para a próxima instrução, ou seja, todos os comandos de seqüência são executados desde  que eles não dependem de um comando de seleção.  Exemplo: (todas as instruções abaixo são de seqüência)   system(“clear”); // limpa a tela printf(quot;Digite um valor: quot;); scanf(quot;%fquot;,&valor); // entrada de dados via teclado resp = valor * 1.25; // atribuição é um comando de seqüência   4.2. Bloco de comandos  Utiliza‐se chaves ( { } ) para delimitar blocos de comando em um programa em C. Estes são  mais  utilizados  no  agrupamento  de  instruções  para  execução  pelas  cláusulas  das  estruturas  condicionais e de repetição.    4.3. Estruturas de Seleção  Estrutura if-else  Sintaxe:  if ( condição ){ bloco de comandos 1; } else { bloco de comandos 2; } 29 
  30. 30.   condição é qualquer expressão que possa ser avaliada com o valor  verdadeiro (“true”) ou  falso (“false”). No caso de expressões que possuam um valor numérico ao invés de um valor lógico,  se o valor é diferente de zero a expressão é avaliada com valor lógico “true”, do contrário é avaliada  com o valor lógico “false”.  Caso a condição possua um valor lógico “true”, bloco de comandos 1 é executado. Se o  valor  lógico  da  condição  for  “false”,  bloco de comandos  2  é  executado.  Para  qualquer  um  dos  blocos, se este for formado por um único comando as chaves são opcionais.  A estrutura if-else é semelhante a uma estrutura condicional composta, em que um ou  outro bloco de comandos é executado; a cláusula else, no entanto, é opcional, e se for omitida a  estrutura passa a funcionar como uma estrutura condicional simples, em que um bloco de comandos  (no caso, o bloco 1) somente é executado se a condição for verdadeira.  Exemplos:  1)   int num; printf(“Digite um numero: “); scanf(“%d”, &num); if (num < 0){ /*testa se num é menor que zero */ /* bloco de comandos executado se a condição é verdadeira. Neste caso, como printf é um único comando as chaves poderiam ser omitidas */ printf(“nO número é menor que zero”); } else { /* bloco de comandos executado se a condição é falsa. Neste caso, como printf é um único comando as chaves poderiam ser omitidas */ printf(“nO número é maior que zero”); }   2)  if ((a == 2) && (b == 5)) /* condição com operação lógica */ printf(“nCondição satisfeita”); /* bloco de comandos */ system(“clear”); /* esta instrução não faz parte da estrutura condicional, logo é sempre executada */ Estrutura if-else-if      30 
  31. 31.   A estrutura if-else-if é apenas uma extensão da estrutura if-else. Sua forma geral  pode ser escrita como sendo:   if (condição_1){ bloco de comandos 1; } else if (condição_2){ bloco de comandos 2; } else if (condição_3){ bloco de comandos 3; } . . . else if (condição_n) { bloco de comandos n; } else declaração_default; A estrutura acima funciona da seguinte maneira: o programa começa a testar as condições  começando pela 1 e continua a testar até que ele ache uma expressão cujo resultado dê diferente de  zero.  Neste  caso  ele  executa  a  declaração  correspondente.  Só  uma  declaração  será  executada,  ou  seja, só será executada a declaração equivalente à primeira condição que der diferente de zero. A  última  declaração  (default) é  a  que  será executada  no caso  de todas  as condições  darem  zero e  é  opcional.   Um exemplo da estrutura acima:   #include <stdio.h> int main (){ int num; printf (quot;Digite um numero: quot;); scanf (quot;%dquot;,&num); if (num>10) printf (quot;nnO numero e maior que 10quot;); else if (num==10){ printf (quot;nnVoce acertou!nquot;); printf (quot;O numero e igual a 10.quot;); } else if (num<10) printf (quot;nnO numero e menor que 10quot;); return(0); }       ifs aninhados  O  if  aninhado  é  simplesmente  um  if  dentro  da  declaração  de  um  outro  if  externo.  O  único  cuidado  que  devemos  ter  é  o  de  saber  exatamente  a  qual  if  um  determinado  else  está  ligado.   31 
  32. 32.   Exemplo:     #include <stdio.h> int main (){ int a, m; printf (quot;Digite um ano e mês: quot;); scanf (quot;%d%dquot;,&a, &m); if (m == 3){ if ((a >=1) && (a <= 31)){ /* este if faz parte do bloco de comandos do if anterior */ printf(“Data OK”); } else{ /* este else é do if mais proximo (que faz parte do bloco de comandos) */ printf(“Data inválida”); } } return(0); } O Operador ?  Uma expressão como:   if (a>0) b=-150; else b=150; pode ser simplificada usando‐se o operador ? da seguinte maneira:   b=a>0?-150:150; De uma maneira geral expressões do tipo:   if (condição) expressão_1; else expressão_2; podem ser substituídas por:   condição ? expressão_1 : expressão_2; O  operador  ?  é  limitado  (não  atende  a  uma  gama  muito  grande  de  casos)  mas  pode  ser  usado para simplificar expressões complicadas. Uma aplicação interessante é a do contador circular.         32 
  33. 33.   Exemplo:   #include <stdio.h> int main(){ int index = 0, contador; char letras[5] = quot;Joaoquot;; for (contador=0; contador < 1000; contador++){ printf(quot;n%cquot;,letras[index]); (index==3) ? index=0: ++index; } } O nome Joao é escrito na tela verticalmente até a variável contador determinar o término  do  programa.  Enquanto  isto  a  variável  index  assume  os  valores  0,  1,  2,  3,  ,  0,  1,  ...  progressivamente.    Estrutura Switch  O  comando  if-else  e  o  comando  switch  são  os  dois  comandos  de  tomada  de  decisão.  Sem  dúvida  alguma  o  mais  importante  dos  dois  é  o if,  mas  o  comando  switch  tem  aplicações  valiosas. Mais uma vez vale lembrar que devemos usar o comando certo no local certo. Isto assegura  um código limpo e de fácil entendimento. O comando switch é próprio para se testar uma variável  em relação a diversos valores pré‐estabelecidos. Sua forma geral é:  switch (variável){ case constante_1 : seqüência de comandos; break; case constante_2 : seqüência de comandos; break; . . . default: seqüência de comandos; } O programa testa uma variável sucessivamente contra uma lista de constantes inteiras ou  caracteres (int ou char). Depois de encontrar uma coincidência, o programa executa o comando ou  bloco de comandos que estejam associados àquela constante. O comando default é executado se  não houver nenhuma coincidência.    O  comando  break  é  utilizado  para  obrigar  a  saída  do  comando switch, se o comando break for esquecido ao final de uma seqüência de comandos, a  execução  continuará  pela  próxima  declaração  case  até  que  um  break  ou  o  final  do  switch  seja  encontrado,  o  que  normalmente  é  indesejado.  A  opção  default  é  opcional.  Uma  declaração  switch é mais eficiente que um encadeamento if-else, além do que pode ser escrito de forma  muito  mais  “elegante”.  Observação:  A  variável  não  pode  ser  uma  string  (char  *)  e  nem  real  (float).      33 
  34. 34.   Exemplo  #include <stdio.h> int main (){ int digito; printf(quot;Dígito [0 .. 9]: quot;); scanf(quot;%dquot;, &digito); switch (digito){ case 0: printf(quot;Zeronquot;); break; case 1: printf(quot;Umnquot;); break; case 2: printf(quot;Doisnquot;); break; case 3: printf(quot;Trêsnquot;); break; case 4: printf(quot;Quatronquot;); break; case 5: printf(quot;Cinconquot;); break; case 6: printf(quot;Seisnquot;); break; case 7: printf(quot;Setenquot;); break; case 8: printf(quot;Oitonquot;); break; case 9: printf(quot;Novenquot;); break; default: printf(quot;ERRO: Não é um digitonquot;); } } 4.4. Estruturas de Repetição  Estrutura while  Sintaxe:  while (condição){ sequência de comandos; } O comando while avalia o valor lógico de condição; se o valor lógico for verdadeiro (true)  a seqüência de comandos é executada, caso contrário a execução do programa continua após a  estrutura  while.  Caso  a  seqüência  de  comandos  seja  formada  por  um  único  comando,  o  uso  das  chaves é opcional.  Após a execução da seqüência de comandos, o valor lógico de condição é reavaliado, e  se  continuar  sendo  verdadeiro  (true)  a  seqüência  de  comandos  é  executada  novamente.  Este  comportamento se repete até que o valor lógico da condição seja falso (false), quando a execução  da estrutura while é interrompida e continua na instrução seguinte.  34 
  35. 35.   Cada uma das execuções da seqüência de comandos é chamada de iteração do laço. No  caso  da  estrutura  while  o  número  de  iterações  pode  variar  de  0  até  N,  sendo  N o  número  da  iteração após a qual o teste da condição resulta em um valor lógico falso.  Observação: caso a condição seja verdadeira no primeiro teste e a seqüência de comandos  seja  executada,  é  necessário  que  esta  torne  a  condição  falsa  em  algum  momento;  do  contrário,  a  condição  sempre será reavaliada  como  verdadeira  e  a  seqüência de comandos será executada em  um número infinito de iterações.  O programa abaixo é executado enquanto i for menor que 100.   #include <stdio.h> int main (){ int i = 0; while ( i < 100){ printf(quot; %dquot;, i); i++; } return(0); } O programa abaixo espera o usuário digitar a tecla 'q' e só depois finaliza:     #include <stdio.h> int main (){ char Ch; Ch='0'; while (Ch!='q'){ scanf(quot;%cquot;, &Ch); } return(0); }   Estrutura do – while  Sintaxe:  do { sequência de comandos } while (condição);     A  seqüência de comandos  sempre  é  executada  inicialmente  em  uma  estrutura  do- while.  Após  a  sua  execução,  o  valor  lógico  da  condição  é  avaliado,  e  se  for  verdadeiro  (true)  a  seqüência  de  comandos  é  executada  novamente.  O  ciclo  se  repete  até  que  o  valor  lógico  da  35 
  36. 36.   condição seja falso (false), quando a execução continua na instrução seguinte à estrutura do-while.  Caso a seqüência de comandos seja formada por um único comando, o uso das chaves é opcional.  Diferentemente  do  que  ocorre  na  estrutura  while,  na  estrutura  do-while  o  número  de  iterações varia entre 1 e N, onde N é o número da iteração após a qual o teste da condição resulta  em um valor lógico falso.    Observação: assim como na estrutura while, caso a condição seja verdadeira no primeiro  teste é necessário que a seqüência de comandos torne a condição falsa em algum momento.  Um dos usos da estrutura do-while é em menus, nos quais você quer garantir que o valor  digitado pelo usuário seja válido, conforme apresentado abaixo:    #include <stdio.h> int main () { int i; do{ printf (quot;nnEscolha a fruta pelo numero:nnquot;); printf (quot;t(1)...Mamaonquot;); printf (quot;t(2)...Abacaxinquot;); printf (quot;t(3)...Laranjannquot;); scanf(quot;%dquot;, &i); } while ((i<1)||(i>3)); switch (i){ case 1: printf (quot;ttVoce escolheu Mamao.nquot;); break; case 2: printf (quot;ttVoce escolheu Abacaxi.nquot;); break; case 3: printf (quot;ttVoce escolheu Laranja.nquot;); break; } return(0); }   Estrutura for  Formato:  for (inicialização; condição; incremento){ seqüência de comandos; } A  inicialização  é executada uma  única  vez,  no  início  da execução da estrutura for,  e  normalmente é uma atribuição utilizada para inicializar alguma variável de controle do laço.   Após  a  inicialização,  o  valor  lógico  da  condição  é  testado.  Se  for  verdadeiro  (true),  a  seqüência de comandos é executada, do contrário a execução continua após a estrutura for. Ao  36 
  37. 37.   final  da  execução  da  seqüência  de  comandos,  o  comando  correspondente  ao  incremento  é  executado, e a condição volta a ser testada. O ciclo se repete até que o teste da condição resulte  em  um  valor  lógico  falso  (false),  quando  então  a  execução  prossegue  após  a  estrutura  for.  Caso  a  seqüência de comandos seja formada por um único comando, o uso das chaves é opcional.  A estrutura for é equivalente a uma estrutura while com o seguinte formato:  inicialização while (condição){ seqüência de comandos; incremento; } Observações:  • Qualquer  uma  das  cláusulas  do  cabeçalho  (inicialização,  condição  ou  incremento)  pode ser omitida; no caso da omissão da inicialização ou do incremento considera‐se  que  estes  são  comandos  nulos  (ou  seja,  não  executam  nada),  já  na  omissão  da  condição  considera‐se  que  o  seu  valor  lógico  é  sempre  verdadeiro.  Os  sinais  de  ponto‐e‐vírgula que separam cada uma das cláusulas não podem ser omitidos.  • As cláusulas de inicialização e incremento podem se constituir de vários comandos  cada uma; nesse caso, os comandos devem ser separados entre si por vírgulas.    Exemplos:      1)   /* neste caso, x é usado como variável de controle do laço (controla a execução entre 1 e 100) e também tem o seu valor impresso pela função printf */ for (x = 1; x <= 100; x++){ printf(“%d”, x); } 2)  /* neste caso a sequência de comandos é nula, e o laço é utilizado somente para “gastar tempo” contando de 0 a 999 */ for (x = 0; x< 1000; x++);   3)   37 
  38. 38.   /* não há incremento, e o laço é executado até que o valor digitado pelo usuário seja 10 */ for (x = 0; x != 10;) scanf(“%d”, &x);   4)   /* duas variáveis são inicializadas, testadas e incrementadas */ for (x = 0, y = 0; x + y < 100; x++, y++) printf(“%d”, x + y); O Comando break  O comando break pode quebrar a execução de um comando (como no caso do switch) ou  interromper  a  execução  de  qualquer  loop  (como  no  caso  do  for,  do  while  ou  do  do while).  O  break  faz com que a execução do programa continue na primeira linha seguinte ao laço ou bloco  que está sendo interrompido.   Observe que um break causará uma saída somente do laço mais interno. Por exemplo:  for(t=0; t<100; ++t){ count=1; for(;;){ printf(quot;%dquot;, count); count++; if(count==10) break; } } O código acima imprimirá os números de 1 a 10 cem vezes na tela. Toda vez que o break é  encontrado, o controle é devolvido para o laço for externo.  Outra observação é o fato que um break usado dentro de uma declaração switch afetará  somente os dados relacionados com o switch e não qualquer outro laço em que o switch estiver.    O Comando continue  O  comando  continue  pode  ser  visto  como  sendo  o  oposto  do  break.  Ele  só  funciona  dentro  de  um  laço.  Quando  o  comando  continue  é  encontrado,  o  laço  pula  para  a  próxima  iteração, sem o abandono do laço, ao contrário do que acontecia no comando break.  O programa  abaixo exemplifica o uso do continue:       38 

×