Você está na página 1de 114

LINGUAGEM DE PROGRAMAO C BSICO PARTE I

Maio/2010

Sumrio
INTRODUO ...................................................................................................................................... 8 A LINGUAGEM C SENSVEL ESCRITA .......................................................................................... 8 ESTRUTURA DE UM PROGRAMA ..................................................................................................... 8 DOIS PROGRAMAS ............................................................................................................................ 10 PRIMEIRO PROGRAMA .................................................................................................................. 10 SEGUNDO PROGRAMA .................................................................................................................. 11 AUTO AVALIAO ......................................................................................................................... 12 FUNES CONCEITOS BSICOS ...................................................................................................... 13 ARGUMENTOS ............................................................................................................................... 14 RETORNO DE VALORES.................................................................................................................. 16 Forma Geral de uma Funo ..................................................................................................... 17 AUTO AVALIAO ......................................................................................................................... 17 ENTRADA E SADA BSICAS ........................................................................................................... 17 Caracteres ................................................................................................................................. 17 A funo printf() ........................................................................................................................ 23 A funo scanf()......................................................................................................................... 24 AUTO AVALIAO ......................................................................................................................... 24 CONTROLE DE FLUXO .................................................................................................................... 25 Comando de Desvio Condicional............................................................................................... 25 for .............................................................................................................................................. 26 AUTO AVALIAO ......................................................................................................................... 28

COMENTRIOS .............................................................................................................................. 29 PALAVRAS RESERVADAS DA LINGUAGEM C.................................................................................. 29 AUTO AVALIAO ......................................................................................................................... 29 VARIVEIS, CONSTANTES, OPERADORES E EXPRESSES .................................................................. 32 NOMES DE VARIVEIS ................................................................................................................... 32 TIPOS DE VARIVEIS EM C............................................................................................................. 32 DECLARAO E INICIALIZAO DE VARIVEIS .............................................................................. 33 AUTO AVALIAO ......................................................................................................................... 36 CONSTANTES ................................................................................................................................. 36 Constantes de Tipos Bsicos ..................................................................................................... 37 Constantes Hexadecimais e Octais............................................................................................ 37 Constantes string....................................................................................................................... 37 Constantes de Barra Invertida................................................................................................... 38 OPERADORES ARITMTICOS E DE ATRIBUIO ............................................................................ 38 AUTO AVALIAO ......................................................................................................................... 41 OPERADORES REALACIONAIS E LGICOS...................................................................................... 41 Operadores relacionais ............................................................................................................. 41 Operadores lgicos.................................................................................................................... 42 Operadores Lgicos Bit a Bit ..................................................................................................... 44 AUTO AVALIAO ......................................................................................................................... 45 EXPRESSES .................................................................................................................................. 45 Converso de Tipos em Expresses .......................................................................................... 46 Expresses que Podem Ser Abreviadas .................................................................................... 46 Encadeamento de Expresses O Operador , (vrgula)............................................................ 46 Tabela de Precedncia em C ..................................................................................................... 47

MODELADORES (CASTS) ................................................................................................................ 48 AUTO AVALIAO ......................................................................................................................... 48 ESTRUTURAS DE CONTROLE DE FLUXO............................................................................................. 52 O COMANDO IF ............................................................................................................................. 52 O else ......................................................................................................................................... 53 O if-else-if .................................................................................................................................. 54 A Expresso Condicional ........................................................................................................... 55 Ifs Aninhados ............................................................................................................................. 55 O Operador ? (interrogao) ..................................................................................................... 57 O COMANDO SWITCH ................................................................................................................... 57 AUTO AVALIAO ......................................................................................................................... 59 ESTRUTURAS DE REPETIO (LAOS) ........................................................................................... 59 Lao Infinito ............................................................................................................................... 60 Lao sem Contedo ................................................................................................................... 61 O COMANDO WHILE ..................................................................................................................... 61 O COMANDO DO-WHILE ............................................................................................................... 62 O COMANDO BREAK ..................................................................................................................... 63 O COMANDO CONTINUE ............................................................................................................... 64 O COMANDO GOTO ...................................................................................................................... 65 AUTO AVALIAO ......................................................................................................................... 68 VETORES, STRINGS, MATRIZES .......................................................................................................... 73 VETORES ........................................................................................................................................ 73 AUTO AVALIAO ......................................................................................................................... 74 STRINGS ......................................................................................................................................... 75 gets ............................................................................................................................................ 76

strcpy ......................................................................................................................................... 76 strcat.......................................................................................................................................... 77 strlen ......................................................................................................................................... 77 strcmp ....................................................................................................................................... 78 AUTOAVALIAO .......................................................................................................................... 78 MATRIZES ...................................................................................................................................... 78 Matrizes bidimenesionais ......................................................................................................... 78 Matrizes de strings .................................................................................................................... 79 MATRIZES MULTIDIMENSIONAIS .................................................................................................. 80 Inicializao ............................................................................................................................... 80 Inicializao sem Especificao de Tamanho ............................................................................ 81 AUTO AVALIAO ......................................................................................................................... 81 DIRETIVAS DE COMPILAO ............................................................................................................. 82 A DIRETIVA INCLUDE ..................................................................................................................... 83 AS DIRETIVAS DEFINE E UNDEF ..................................................................................................... 83 Define ........................................................................................................................................ 83 Undef ......................................................................................................................................... 86 Ifdef e Endif ............................................................................................................................... 86 Ifndef_ ....................................................................................................................................... 86 If................................................................................................................................................. 87 Else ............................................................................................................................................ 87 Elif .............................................................................................................................................. 88 ENTRADAS E SADAS PADRONIZADAS ............................................................................................... 89 INTRODUO ................................................................................................................................ 89 LEITURA E ESCRITA DE CARACTERES ............................................................................................. 90

Getche e getch .......................................................................................................................... 90 Putchar ...................................................................................................................................... 91 LEITURA E ESCRITA DE STRING ...................................................................................................... 91 Gets ........................................................................................................................................... 91 Puts ............................................................................................................................................ 92 FORMATAO DE ENTRADA E DE SADA ...................................................................................... 92 Printf .......................................................................................................................................... 92 Scanf .......................................................................................................................................... 94 Sprintf e sscanf .......................................................................................................................... 95 ABRIR E FECHAR ARQUIVOS .......................................................................................................... 96 FOPEN............................................................................................................................................ 96 Exit ............................................................................................................................................. 98 Fclose......................................................................................................................................... 99 LEITURA E ESCRITA DE CARACTERES EM ARQUIVOS .................................................................... 99 Putc............................................................................................................................................ 99 Getc ......................................................................................................................................... 100 Feof.......................................................................................................................................... 100 OUTROS COMANDOS DE ACESSO A ARQUIVOS.......................................................................... 103 Arquivos Pr-Definidos............................................................................................................ 103 Fgets ........................................................................................................................................ 103 Fputs ........................................................................................................................................ 104 Ferror e perror......................................................................................................................... 104 Fread........................................................................................................................................ 105 Fwrite ...................................................................................................................................... 106 Fseek........................................................................................................................................ 107

Rewind..................................................................................................................................... 107 Remove.................................................................................................................................... 107 FLUXOS PADRO ......................................................................................................................... 108 Fprintf ...................................................................................................................................... 109 Fscanf ...................................................................................................................................... 109 AUTO AVALIAO ....................................................................................................................... 110 CONSIDERAES FINAIS .................................................................................................................. 113 REFERNCIAS ................................................................................................................................... 114

INTRODUO

A LINGUAGEM C SENSVEL ESCRITA


Uma importante caracterstica da linguagem C que ela sensvel escrita (do ingls Case Sensitive), ou seja, letras maisculas e minsculas fazem diferena. Quando se declara uma varivel com o nome Contador, ela ser diferente de contador, CONTADOR, cONTadOr e todas as demais variaes possveis que difiram do nome originalmente declarado para essa varivel. Da mesma maneira, os comandos for e while, por exemplo, s podem ser escritos em minsculas, caso contrrio o compilador no os considerar comandos, mas variveis.

ESTRUTURA DE UM PROGRAMA
Uma particularidade interessante no programa C seu aspecto modular e funcional, em que, o prprio programa principal uma funo. Esta forma de apresentao da linguagem facilita o desenvolvimento de programas, pois permite o emprego de formas estruturadas e modulares. <definies de pr-processamento> <prottipos de funes> <declaraes de variveis globais> void main(void) { /* corpo da funo principal, com declaraes de suas variveis, seus comandos e funes */ } <tipo> func( [lista de parmetros] ) <declarao dos parmetros> { /* corpo da funo func( ) com suas declaraes de variveis, comandos e funes */

}
Tabela 1 - Estrutura de um programa em Linguagem C

Primeiramente, so inseridas as definies de pr-processamento. Essas definies so comandos iniciados com o smbolo # e so processadas antes que a compilao do cdigo efetivamente tenha incio, da o nome de definies de pr-processamento. Os prottipos de funes que sero utilizados no programa devem ser declarados1 anteriormente sua utilizao. Por exemplo, se a funo main precisa de uma funo que est definida abaixo dela, essa funo deve ser declarada antes. Caso uma funo invocada por uma funo anterior no seja declarada antes dessa funo o compilador C informar que tal funo invocada no foi declarada/definida. As variveis que so declaradas fora do corpo de funes so tidas como variveis globais. Essas variveis so referenciadas por todas as funes. A funo main uma funo que deve existir em todo programa escrito em C. A sintaxe apresentada neste exemplo, diz que esta funo tanto receber um parmetro vazio2 (void), quanto retornar um valor vazio. As demais funes so definidas da forma como se apresenta na Figura 1. Primeiramente o tipo de retorno declarado, depois se deve declarar o nome da funo, seguido de seus parmetros. Cada parmetro contido na lista de parmetros deve ser declarado, antes da abertura de chave ({). Podemos tambm declarar os parmetros na prpria lista de parmetros. Isto ser melhor bem evidenciado quando estivermos estudando as funes em C. Vale lembrar que a estrutura na Figura 1 no fixa, apesar de ser recomendada. A estrutura pode ser alterada dependendo da experincia do programador.

importante salientar a diferena entre declarao e definio de funo. Uma funo primeiramente declarada, depois ela definida, ou seja, implementada. Nada, porm, impede que ela seja declara e definida simultaneamente.
2

Podemos entender vazio (void) como sendo nada (inexistncia)

10

DOIS PROGRAMAS

PRIMEIRO PROGRAMA
O primeiro, e mais simples, programa em C apresentado mostrado abaixo: #include <stdio.h> /* Um Primeiro Programa */ int main () { printf ("Oi mundo!\n"); return(0); } Aps compilar este exemplo ele dever exibir a mensagem Oi mundo!, na tela (s isso). Como esta a primeira vez em que um programa apresentado, uma anlise do programa exibido acima ser feita, linha por linha at o fim desta seo. A linha #include <stdio.h> informa ao compilador que ele deve incluir o arquivo de cabealho stdio.h. Neste arquivo, existem declaraes de funes teis e bsicas para entrada e sada de dados (std = standard, padro em ingls; io = Input/Output, entrada e sada; portanto, stdio = entrada e sada padronizadas). Toda vez que voc quiser usar uma destas funes deve-se incluir este comando. O C possui diversos arquivos de cabealhos. Quando se cria um programa, uma boa prtica usar comentrios que ajudem a elucidar o seu propsito. No caso acima h um comentrio: /* Um Primeiro Programa */. O compilador C ignora qualquer coisa escrita entre /* e */. Um comentrio pode, inclusive, ter mais de uma linha. Pode-se questionar que existe outro tipo de comentrio utilizado na linguagem C, o comentrio que comece com //. O comentrio // permite que o resto da linha aps o // seja ignorado pelo compilador C. Este tipo de comentrio muito utilizado, porm ele no faz parte do C ANSI. A linha int main () indica que a definio de uma funo de nome main. Todos os programas em C tm uma funo main, pois essa funo ser chamada,

11

primeiramente, quando o programa for executado. O contedo da funo delimitado por chaves {}. O cdigo que estiver dentro das chaves ser executado sequencialmente quando a funo for chamada. A palavra int indica que esta funo retorna um valor inteiro. O seu significado ser visto posteriormente, quando estudarmos mais detalhadamente as funes do C. A ltima linha do programa, return(0);, indica o nmero inteiro que est sendo retornado pela funo, no caso o nmero 0. A nica coisa que o programa realmente faz chamar a funo printf ();, passando a string (uma string uma seqncia de caracteres, como ser visto adiante) "Oi mundo!\n" como argumento. O cabealho stdio.h necessrio no programa por causa do uso dessa funo, que neste caso exibir o contedo da string na tela do computador. O \n uma constante chamada de constante barra invertida. No caso, o \n a constante barra invertida de nova linha (new line ou Line Feed <LF>), e ela interpretada como um comando de mudana de linha, isto , aps imprimir Oi mundo! o cursor (linha piscante) ser deslocado para a prxima linha. importante observar tambm que os comandos do C terminam com ; (ponto e vrgula).

SEGUNDO PROGRAMA
Vejamos agora um programa mais complexo:
#include <stdio.h> int main () { /* Declaracao de Variaveis */ int Dias; float Anos; /* Entrada de Dados */ printf ("Entre com o nmero de dias: "); scanf ("%d",&Dias); /* Conversao Dias->Anos */ Anos=Dias/365.25; printf ("\n\n%d dias equivalem a %f anos.\n",Dias,Anos); return(0); }

Vamos entender como o programa acima funciona. So declaradas duas variveis chamadas Dias e Anos. A primeira um int (inteiro) e a segunda um float (ponto flutuante). As variveis declaradas como ponto flutuante existem para armazenar valores

12

reais (fracionrios), como 5,1497. feita ento uma chamada funo printf(), que exibe uma mensagem na tela. Queremos agora ler um dado que ser fornecido pelo usurio e coloc-lo na varivel inteira Dias. Para tanto usamos a funo scanf(). A string %d diz funo que iremos ler um valor inteiro. O segundo parmetro passado funo diz que o dado lido dever ser armazenado na varivel Dias. importante ressaltar a necessidade de se colocar um & antes do nome da varivel a ser lida quando se usa a funo scanf(). O motivo disto ser esclarecido adiante. importante notar que quando mais de um parmetro passado para uma funo, eles devem ser separados por vrgula. Temos ento uma expresso matemtica simples que atribui a Anos o valor de Dias dividido por 365.25 (365.25 uma constante do tipo ponto flutuante 365,25). Como Anos uma varivel float o compilador far uma converso automtica entre os tipos das variveis (isso ser visto com detalhes mais adiante). A segunda chamada funo printf() passa trs argumentos. A string "\n\n%d dias
equivalem a %f anos.\n",Dias,Anos instrui a funo para pular duas linhas,

exibir um contedo inteiro de uma varivel na tela, exibir a mensagem "dias equivalem
a anos., exibir um valor float na tela, exibir a mensagem anos e pular outra linha.

Os outros parmetros so as variveis, Anos e Dias, das quais devem ser lidos os valores int e float, respectivamente.

AUTO-AVALIAO
a) O que faz este programa? #include <stdio.h> int main() { int x; scanf("%d",&x); printf("%d",x); return(0); }

13

FUNES CONCEITOS BSICOS


Uma funo um bloco de cdigo de programa que pode ser usado diversas vezes em sua execuo. O uso de funes permite que o programa fique mais legvel, e melhor estruturado. Um programa C consiste, no fundo, de vrias funes declaradas juntas. Abaixo o tipo mais simples de funo:
#include <stdio.h> int mensagem () /* Funcao simples: s imprime Ola! */ { printf ("Ola! "); return(0); } int main () { mensagem(); printf ("Eu estou vivo!\n"); return(0); }

Este programa produz o mesmo resultado que o primeiro exemplo visto anteriormente. O que ele faz definir uma funo mensagem() que exibe uma string na tela e retorna 0. A chamada a ela feita pela funo principal main(), como visto anteriormente. A diferena fundamental entre a funo main() e as demais funes do programa que ela uma funo especial, cujo diferencial o fato de ser a primeira, e obrigatria, funo a ser executada em um programa.

14

ARGUMENTOS
Argumentos so os dados entradas que a funo recebe procedentes de uma chamada por um programa ou outra funo. Atravs dos argumentos passamos parmetros para uma funo. J vimos funes com argumentos. As funes printf() e scanf() so funes que recebem argumentos. Vamos ver outro exemplo simples de funo com argumentos:
#include <stdio.h> int square (int x) /* Calcula o quadrado de x */ { printf ("O quadrado e %d",(x*x)); return(0); } int main () { int num; printf ("Entre com um numero: "); scanf ("%d",&num); printf ("\n\n"); square(num); return(0); }

Na definio da funo square() informado que essa funo receber um argumento inteiro x. Quando feita a chamada funo, o inteiro num passado como argumento. H alguns pontos a considerar. Em primeiro lugar temos de satisfazer os requesitos da funo quanto ao tipo e quantidade de argumentos quando a chamamos. Apesar de existirem algumas converses de tipo, que o C faz automaticamente, importante ficar atento. Em segundo lugar, no importante o nome da varivel que se passa como argumento, ou seja, a varivel num, ao ser passada como argumento para square() copiada para a varivel x. A funo square() manipula apenas a varivel x. Se mudarmos o valor de x no interior da funo, o valor da varivel num permanece inalterado. Vamos dar um exemplo de funo de mais de um argumento. Repare que, neste caso, os argumentos so separados por vrgula e que necessrio explicitar o tipo de argumento, um a um. Note, tambm, que os argumentos passados para a funo no necessitam ser todos variveis porque mesmo sendo constantes sero copiados para as variveis

15

correspondentes da funo.

16

#include <stdio.h> int mult (float a, float b,float c) /* Multiplica 3 numeros */ { printf ("%f",a*b*c); return(0); } int main () { float x,y; x=23.5; y=12.9; mult (x,y,3.87); return(0); }

RETORNO DE VALORES
Muitas vezes necessrio fazer com que uma funo retorne um valor. As funes que vimos at aqui estavam retornando o nmero 0. Podemos especificar um tipo de retorno indicando-o antes do nome da funo. Mas para dizer ao C o que deve ser retornado, aps concluda a chamada e execuo de um a determinada funo, necessrio o uso do comando return ao final da funo chamada. Sabendo disso fcil fazer uma funo para multiplicar dois inteiros e que retorna o resultado da operao, como mostrado a seguir:
#include <stdio.h> int prod (int x,int y) { return (x*y); } int main () { int saida; saida=prod (12,7); printf ("A saida e: %d\n",saida); return(0); }

A funo prod retorna o valor de 12 multiplicado por 7, esse valor pode ser usado em uma expresso qualquer. No programa feita a atribuio deste resultado varivel saida, que exibida usando a funo printf(). Uma observao adicional: se no especificarmos o tipo de retorno de uma funo, o compilador C automaticamente supor que esse tipo de retorno inteiro. Porm, no uma boa prtica deixar de especificar o

17

valor de retorno, portanto esse valor deve sempre ser especificado. Com relao funo main(), o retorno sempre ser inteiro. Assim, a funo main() retornar zero quando ela executada sem qualquer tipo de erro. Mais um exemplo de funo, que agora recebe dois contedos do tipo float e tambm retorna um contedo do tipo float: #include <stdio.h> float prod (float x,float y) { return (x*y); } int main () { float saida; saida=prod (45.2,0.0067); printf ("A saida e: %f\n",saida); return(0); }

Forma Geral de uma Funo


tipo_de retorno nome_da_funo (lista_de_argumentos) { Cdigo_da_funo }

AUTO-AVALIAO
a) Escreva uma funo que receba e some (a funo deve somente fazer o clculo) dois inteiros e retorne o valor da soma.

ENTRADA E SADA BSICAS Caracteres


Os caracteres so dados do tipo char. O C trata cada caracter ('a', 'b', 'x', etc) como sendo uma varivel de um byte (8 bits). Um bit a menor unidade de armazenamento de informaes em um computador. Os inteiros (int) tm um nmero maior de bytes. Dependendo da implementao do compilador, eles podem ter 2 bytes (16 bits) ou 4 bytes (32bits). Isso ser melhor explicado posteriormente. Na linguagem C, tambm podemos usar uma varivel de tipo char para armazenar valores numricos inteiros, alm de us-la

18

para armazenar caracteres de texto. Para indicar um caracter de texto usamos apstrofes.

19

Exemplo de programa que manipula caracteres: #include <stdio.h> int main () { char Ch; Ch=D; printf ("%c",Ch); return(0); } No programa acima, %c indica que printf() deve colocar um caracter na tela. Como visto anteriormente, uma varivel do tipo char tambm usada para armazenar um

nmero inteiro. Este nmero conhecido como o cdigo ASCII correspondente ao caractere. Veja no programa mostrado a seguir: #include <stdio.h> int main () { char Ch; Ch=D; printf ("%d",Ch); /* Imprime o caracter como inteiro */ return(0); } Ser exibido o valor 68 na tela, que o cdigo ASCII correspondente ao caracter 'D' (d maisculo). Frequentemente necessrio ler um caracter fornecido pelo usurio. Para isto as funes mais utilizadas, quando em ambiente DOS ou Windows, so getch() e getche(). Ambas retornam o caracter referente tecla pressionada. getche() exibe o caracter na tela antes de retorn-lo e getch() apenas retorna o caracter sem exibi-lo na tela. Ambas as funes podem ser encontradas no arquivo de cabealho conio.h. Geralmente essas

funes no esto disponveis em ambientes Unix (compiladores cc e gcc), pois no fazem parte do padro ANSI. Podem ser substitudas pela funo scanf(), porm sem as mesmas funcionalidades.

20

Exemplo que usa a funo getch(). #include <stdio.h> #include <conio.h> /* Este programa usa conio.h */ int main () { char Ch; Ch=getch(); printf ("Voce pressionou a tecla %c",Ch); return(0); } A principal diferena entre uma da verso de programa que utiliza getch() e uma verso de programa que no utiliza getch() que no primeiro caso o usurio simplesmente aperta a tecla e o sistema l diretamente a tecla pressionada. No segundo caso, necessrio apertar tambm a tecla <ENTER>. Em C uma string um vetor de caracteres terminado com um caracter nulo. um caracter com valor inteiro igual a zero (cdigo ASCII igual a 0). O terminador nulo tambm pode ser escrito usando a conveno de barra invertida do C como sendo '\0'. Para declarar uma string usamos o: char nome_da_string[tamanho]; Declara um vetor de caracteres (uma string) com nmero de posies igual a tamanho. Note que, como temos que reservar um caractere para ser o terminador nulo, necessrio declarar o comprimento da string como sendo, no mnimo, um caractere maior que a maior string que pretendemos armazenar. Vamos supor que seja declarada uma string de 7 posies e seja armazenada a palavra Joo nela. Teremos: J o a o \0 _ _ No caso acima, as duas ltimas posies no usadas da string tm valores

indeterminados. Isto acontece porque o C no inicializa variveis, essa tarefa responsabilidade do programador. Portanto as nicas posies inicializadas so as que contm os caracteres 'J', 'o', 'a', 'o' e '\0'. Se quisermos ler uma string fornecida pelo usurio podemos usar a funo gets(). Um exemplo do uso desta funo apresentado a seguir. A funo gets() coloca o terminador nulo na string, quando a tecla "Enter" pressionada.

21

22

#include <stdio.h> int main () { char string[100]; printf ("Digite uma string: "); gets (string); printf ("\n\nVoce digitou %s",string); return(0); } Neste programa, o tamanho mximo da string que voc pode entrar uma string de 99 caracteres. Se voc entrar com uma string de comprimento maior, o programa ir aceitar, mas os resultados podem ser desastrosos. Veremos porque posteriormente. Como as strings so vetores de caracteres, para acessar um determinado caractere de uma string, basta "indexar", ou seja, usar um ndice (posicionador, apontador) para indicar o acesso a um caractere especfico dentro da string. Suponha uma string chamada str. possvel acessar a segunda letra de str da seguinte forma: str[1] = a; Por que o acesso segunda letra e no primeira? Porque em linguagem C, a primeira posio de uma string a posio zero. Assim, a primeira letra da string sempre estar na posio 0. A segunda letra sempre estar na posio 1 e assim sucessivamente. Abaixo um exemplo que exibe a segunda letra da string "Joao", apresentada acima. Em seguida, ser mudada essa letra e ser exibida a string alterada. #include <stdio.h> int main() { char str[10] = "Joao"; printf("\n\nString: %s", str); printf("\nSegunda letra: %c", str[1]); str[1] = U; printf("\nAgora a segunda letra eh: %c", str[1]); printf("\n\nString resultante: %s", str); return(0); } Nessa string, o terminador nulo est na posio 4. Das posies 0 a 4, sabemos que temos caracteres vlidos e, portanto, possvel manipul-los individualmente. Notar a forma como inicializada a string str com os caracteres 'J' 'o' 'a' 'o' e '\0' simplesmente declarando char str[10] = "Joao".

23

Veremos posteriormente que "Joao" (uma cadeia de caracteres entre aspas) denominada de string constante, isto , uma cadeia de caracteres pr-carregada com valores que no podem ser modificados. J a string str uma varivel do tipo char, pois possvel modificar o que nela est armazenado, como de fato foi feito. No programa acima, %s indica que printf() deve exibir uma cadeia de caracteres na tela. Vamos agora fazer uma abordagem inicial s duas funes usadas para entrada e sada.

A funo printf()
Forma geral da funo printf(): printf (string_de_controle,lista_de_argumentos); A string de controle informa o que deve, e como, ser exibido na tela. A string de controle informa no apenas os caracteres que devem ser exibidos na tela, mas tambm as variveis e suas respectivas posies. Isso feito usando-se os parmetros de controle, reconhecidos pela notao %. importante que, para cada parmetro de controle, exista um argumento correspondente na lista de argumentos. A figura abaixo mostra alguns dos parmetros %:

Tabela 2 - printf() Parmetros de controle

Exemplos de printf() e o que exibido: printf ("Teste %% %%") Teste % % printf ("%f",40.345) 40.345 printf ("Um caractere %c e um inteiro %d",D,120) Um caractere D e um inteiro 120 printf ("%s e um exemplo","Este") Este e um exemplo printf ("%s%d%%","Juros de ",10) Juros de 10% Maiores detalhes sobre a funo printf() (incluindo outros cdigos de controle) sero vistos posteriormente.

24

A funo scanf()
O formato geral da funo scanf() : scanf (string-de-controle,lista-de-argumentos); A funo scanf() permite a entrada de dados pelo usurio, atravs do teclado. Anloga funo printf() necessrio observar a correspondncia entre os parmetros declarados e a lista de argumentos. Alm disso, no esquecer o caractere & precedendo o nome da varivel na lista de argumentos.

AUTO AVALIAO
a) Escreva um programa que leia um caractere digitado pelo usurio, exiba o caractere digitado e o cdigo ASCII correspondente a este caractere. b) Escreva um programa que leia duas strings e sejam exibidas na tela. Exibir tambm a segunda letra de cada uma das strings.

25

CONTROLE DE FLUXO
Os comandos de controle de fluxo so aqueles que permitem ao programador alterar a seqncia de execuo do programa. Vamos fazer uma breve introduo a dois comandos de controle de fluxo. Outros comandos sero estudados posteriormente.

Comando de Desvio Condicional


IF O comando if representa uma alternativa de deciso, provocando um desvio na execuo seqencial de instrues. A sua forma geral : if (condio) declarao; A condio do comando if representa um expresso lgica a ser avaliada. Se o resultado da avaliao for verdadeiro a declarao executada. Se o resultado for falso a declarao no executada. A declarao pode ser um bloco de cdigo ou apenas um comando. interessante notar que, no caso da declarao ser um bloco de cdigo, no necessrio (e nem permitido) o uso do delimitador ; no final do bloco, entretanto, o bloco dever estar encerrado entre { }. Isto uma regra geral para blocos de cdigo. Exemplo: #include <stdio.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num); if (num>10) printf ("\n\nO numero e maior que 10"); if (num==10) { printf ("\n\nVoce acertou!\n"); printf ("O numero e igual a 10."); } if (num<10) printf ("\n\nO numero e menor que 10"); return (0); } A expresso num>10 avaliada e retorna um valor diferente de zero, se verdadeira, e zero, se falsa. No exemplo, se num for maior que 10, ser exibida a frase: "O nmero e maior que 10".

26

Se num igual a 10, sero executados dois comandos. Para que isso seja possvel, os comandos foram agrupados em um bloco que inicia imediatamente aps a declarao da expresso e termina aps o segundo printf(). O operador de igualdade == e no =. Isso porque o operador = representa a operao de atribuio. Pode parecer estranho primeira vista, mas se for escrito if (num=10) ... /* Isto esta errado */ o compilador iria atribuir o valor 10 varivel num e a expresso num=10 iria retornar 10, fazendo com que o nosso valor de num fosse modificado e fazendo com que a declarao fosse executada sempre. Este problema gera erros freqentes entre iniciantes e, portanto, muita ateno deve ser tomada. Os operadores de comparao so: == (igual), != (diferente de), > (maior que), < (menor que), >= (maior ou igual), <= (menor ou igual).

for
O lao for usado para repetir um comando, ou bloco de comandos, diversas vezes, de maneira que se possa ter um bom controle sobre o lao. Sua forma geral : for (inicializao;condio;incremento) declarao; A declarao no comando for tambm pode ser um bloco ({ } ) e neste caso o ; omitido. O melhor modo de se entender o lao for ver de que maneira ele funciona internamente. O lao for equivalente seguinte estrutura sequencial: inicializao; A = 0; B = 5; if (condio) if (A > B) { { declarao; printf(A menor que B); incremento; A = A + 1; "Volte para o comando if" Volte para o comando if
} }

O lao for executa a inicializao incondicionalmente e testa a condio. Se a condio for falsa, declarao e incremento no so executados. Se a condio for verdadeira, declarao e incremento so executados, e, a seguir, volta ao teste da condio.

27

Essas operaes se repetem at que o resultado da avaliao da expresso condicional seja falso. Abaixo um exemplo de programa que exibe 100 valores na tela: #include <stdio.h> int main () { int count; for (count=1;count<=100;count=count+1) printf ("%d ",count); return(0); } Outro exemplo interessante mostrado a seguir: o programa recebe uma string e conta quantos dos caracteres dessa string so iguais letra 'c' e exibe o resultado da contagem.
#include <stdio.h> int main () { char string[100]; /* String, ate 99 caracteres */ int i, cont; printf("\n\nDigite uma frase: "); gets(string); /* Le a string */ printf("\n\nFrase digitada:\n%s", string); cont = 0; for (i=0; string[i] != \0; i=i+1) { if ( string[i] == c ) /* Se for a letra c */ cont = cont +1; /* Incrementa o contador de caracteres */ } printf("\nNumero de caracteres c = %d", cont); return(0); }

Note o teste que est sendo feito no for: o caractere armazenado em string[i] comparado com '\0' (caractere final da string). Caso o caractere seja diferente de '\0', a condio verdadeira e o bloco do for executado. Dentro do bloco existe um if que testa se o caractere igual a 'c'. Caso seja, o contador de caracteres c incrementado. Mais um exemplo, envolvendo caracteres:
/* Este programa imprime o alfabeto: letras maisculas */ #include <stdio.h> int main() { char letra;

28

for(letra='A' ;letra<='Z';letra=letra+1) printf("%c ", letra); }

Este programa funciona porque as letras maisculas de A a Z possuem cdigo inteiro seqencial.

AUTO AVALIAO
Veja como voc est. a) Explique porque est errado escrever if (num=10). O que ocorrer? b) Escreva um programa que coloque os nmeros de 1 a 100 na tela na ordem inversa (comeando em 100 e terminando em 1). c) Escreva um programa que leia uma string, conte quantos caracteres desta string so iguais a 'a' e substitua os que forem iguais a 'a' por 'b'. O programa deve imprimir o nmero de caracteres modificados e a string modificada. d) O cdigo ASCII um conjunto de 256 smbolos (de 0 a 255). Escreva um programa que exiba todos os caracteres ASCII, pulando uma linha no final de cada caractere exibido, por exemplo: ASCII(64) = A.

29

COMENTRIOS
O uso de comentrios torna o cdigo do programa mais fcil de entender. Os comentrios do C devem comear com /* e terminar com */. O C padro no permite comentrios aninhados (um dentro do outro), mas alguns compiladores os aceitam.

PALAVRAS RESERVADAS DA LINGUAGEM C


Todas as linguagens de programao possuem palavras reservadas. As palavras reservadas no podem ser usadas a no ser para seus propsitos originais, isto , no podemos declarar funes ou variveis com os mesmos nomes. Como o C case sensitive podemos declarar uma varivel pelo nome For, apesar de haver uma palavra reservada for, mas isto no recomendvel, pois pode gerar confuso. Apresentamos a seguir as palavras reservadas do ANSI C. Veremos o significado destas palavras chave quando for oportuno. auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while

AUTO AVALIAO
1- A linguagem C tem este nome porque foi a sucessora da linguagem B. ( ) Verdadeiro ( ) Falso 2- Em C, variveis com nomes abc e Abc representam a mesma varivel. ( ) Verdadeiro ( ) Falso

30

3- O programa #include <stdio.h> main() { int x; scanf("%d",&x); printf("%d",x); } l uma varivel pelo teclado e a exibe na tela ( ) Verdadeiro ( ) Falso 4- A instruo #include <stdio.h> no programa anterior colocada para que possamos utilizar as funes scanf() e printf() ( ) Verdadeiro ( ) Falso 5- Os comentrios na linguagem C s podem ter uma linha de comprimento ( ) Verdadeiro ( ) Falso 6- String uma seqncia de caracteres terminada com um '\0'. Uma string pode ser armazenada em um vetor de caracteres ( ) Verdadeiro ( ) Falso 7- Sendo i uma varivel inteira, a seguinte chamada a scanf() vlida: scanf("%d", i); ( ) Verdadeiro ( ) Falso 8- O que faz o seguinte programa em C? #include <stdio.h> main() { int i =2; printf ("\n O valor de i = %d ", i); } ( ) Nada ( ) Exibe: O valor de i = 2 ( ) Exibe: \n O valor de i = %d ( ) Pula para a prxima linha e exibe: O valor de i = 2

31

9- O que uma funo em C? ( ) Parte de um programa ( ) Um bloco de cdigo que pode ser utilizado diversas vezes na execuo de um programa ( ) Uma estrutura da linguagem C que pode ser utilizada para que um programa fique mais organizado ( ) Um bloco de cdigo que pode receber parmetros, process-los e retornar alguma coisa ( ) Todas as opes acima 10- O comando printf ("%s%d%%","Juros de ",10); imprime: ( ) Juros de 10% ( ) %s%d%% Juros de 10 ( ) % Juros de 10 ( ) 10 Juros de ( ) Nenhuma das anteriores 11- O lao for de uma nica instruo termina com: ( ) Vrgula ( ) Chave de abertura ( ) Chave de fechamento ( ) Ponto e vrgula 12- A expresso de inicializao de um lao for ( ) Nunca executada; ( ) executada uma nica vez a cada iterao ( ) executada enquanto o lao no termina
( ) executada uma vez antes do lao ser iniciado

32

VARIVEIS, CONSTANTES, OPERADORES E EXPRESSES


Neste ponto, nunca demais relembrar os conceitos e fundamentos que se aplicam s variveis, constantes, operadores e expresses.

NOMES DE VARIVEIS
As variveis em C podem ter qualquer nome se duas condies forem satisfeitas: o nome deve comear com uma letra ou sublinhado ( _ ) e os caracteres subsequentes devem ser letras, nmeros ou sublinhado ( _ ). H apenas mais duas restries: o nome de uma varivel no pode ser igual a uma palavra reservada, nem igual ao nome de uma funo declarada pelo programador, ou pelas bibliotecas do C. Variveis de at 32 caracteres so aceitas. Outra considerao: bom sempre lembrar que o C "case sensitive" e, portanto, deve-se prestar ateno s maisculas e minsculas. Dvidas que eventualmente venham a surgir podero ser resolvidas consultando-se a sintaxe da linguagem C.

TIPOS DE VARIVEIS EM C
A linguagem C permite a declarao de 5 tipos bsicos: char, int, float, void e double. Os trs primeiros foram estudados anteriormente. O tipo double declara uma varivel em ponto flutuante de tamanho o que permite o armazenamento de dados com maior preciso. O tipo void o tipo vazio, ou um "tipo sem tipo". A aplicao deste tipo ser vista posteriormente. Para cada um dos tipos de variveis existem os modificadores de tipo. Os modificadores de tipo em C so quatro: signed, unsigned, short e long. s variveis declaradas como tipo float no se pode aplicar nenhum desses modificadores e s variveis do tipo double aplica-se apenas o modificador long. Os modificadores aplicam-se a quaisquer variveis do tipo inteiro. O propsito dos modificadores short e long permitir tamanhos diferentes de variveis de tipo inteiro onde isto for prtico. Inteiros menores (short) ou maiores (long). Variveis declaradas como int normalmente tero o tamanho da palavra de memria da mquina na qual o cdigo fonte for compilado. Assim, em mquinas

33

de 16 bits, uma varivel int ter tamanho de 16 bits (2 bytes) em mquinas de 32 bits ter tamanho de 32 bits (4 bytes). Na verdade, cada compilador livre para escolher tamanhos adequados para o hardware em questo, com a nica restrio de que os tipos short int e int devem ocupar pelo menos 16 bits e os tipos long int pelo menos 32 bits. O tipo short int no pode ter tamanho maior que o tipo int, que, por sua vez, no pode ter tamanho maior que long int. O modificador unsigned especifica variveis sem sinal. Uma varivel do tipo unsigned int armazenar contedo inteiros e positivos (maiores do que zero). A seguir apresentada tabela dos tipos de dados permitidos e seus contedos mximos e mnimos em um compilador tpico para um hardware de 16 bits. Tambm nesta tabela est especificado o formato que deve ser utilizado para utilizar os tipos de dados com as funes de entrada e sada, tais como scanf() e printf().

Tabela 3 - Tipos, tamanhos, valores mximos e mnimos de variveis

O tipo long double declara uma varivel de ponto flutuante com maior preciso e utiliza 80 bits ou 10 bytes. importante observar que os intervalos de ponto flutuante, na tabela acima, esto indicados em faixa de expoente, mas os nmeros podem assumir valores tanto positivos quanto negativos.

DECLARAO E INICIALIZAO DE VARIVEIS


As variveis em C devem ser declaradas antes de serem usadas. A forma geral da

34

declarao de variveis : tipo_da_varivel lista_de_variveis; As variveis da lista de variveis sero todas de mesmo tipo e devero ser separadas por vrgula. Como o tipo padro em C int, ao declarar variveis desse com algum dos modificadores de tipo permitidos, basta colocar o nome do modificador de tipo. Assim, para declarar uma varivel inteiro longo, basta declar-la como long. Por exemplo, as declaraes abaixo char ch, letra; long count; float pi; declaram duas variveis do tipo char de nomes ch e letra, uma varivel do tipo long int de nome count e uma varivel do tipo float de nome pi. Variveis podem ser declaradas em trs pontos diferentes em um programa escrito na linguagem C. O primeiro externo s funes do programa. As variveis declaradas nesse ponto so denominadas variveis globais e podem ser referenciadas por quaisquer instrues do programa independentemente do ponto onde essas instrues foram declaradas. Pode-se dizer que, como elas esto fora de todas as funes, todas as funes as enxergam. O segundo ponto no qual pode-se declarar variveis no incio de um bloco de cdigo. Essas variveis so denominadas locais e somente podem ser referenciadas por instrues declaradas dentro do bloco onde foram declaradas, isto , somente a funo na qual a varivel foi declarada pode referenci-la. O terceiro ponto em que se pode declarar variveis em uma lista de parmetros de uma funo. Mais uma vez, apesar dessas variveis receberem valores externos, somente so referenciadas pela funo em que foram declaradas.

35

No programa abaixo: #include <stdio.h> int contador; int func1(int j) { /* aqui viria o cdigo da funcao } int main() { char condicao; int i; for (i=0; i<100; i=i+1) { /* Bloco do for */ float f2; /* etc ... */ func1(i); } /* etc ... */ return(0); } A varivel contador global, e pode ser referenciada em qualquer parte do programa. As variveis condicao e i so declaradas no interior da funo main() e, portanto, somente podem ser referenciadas no interior dessa mesma funo, pois so locais. A varivel f2 varivel de bloco, isto , ela somente referenciada no interior do bloco associado instruo for, que por sua vez est no interior da funo main(). A varivel inteira j uma varivel declarada em uma lista de parmetros da funo func1. As regras que regem onde uma varivel vlida denominam-se regras de escopo (limites, fronteiras) da varivel. Outros dois detalhes devem ser ressaltados. Duas variveis globais no podem ter o mesmo nome. O mesmo vale para variveis locais de uma mesma funo. Entretanto, duas variveis locais, de funes diferentes, podem ter o mesmo nome sem que isso venha a se configurar qualquer conflito, devido ao escopo de cada uma dessas variveis. Variveis podem ter atribuio de valores iniciais no momento de sua declarao. Para isso usa-se a forma geral: tipo_da_varivel nome_da_varivel = constante; Isto importante, pois quando C cria uma varivel ele no a inicializa. Isto significa

36

que at que um primeiro valor seja atribudo varivel seu contedo indeterminado e que no pode ser utilizado para nada. No se deve presumir que uma varivel declarada possui contedo zero ou qualquer outro valor. Exemplos de inicializao so mostrados abaixo: char ch=D; int count=0; float pi=3.141; Ressalte-se, ainda, que em C, uma varivel tem que ser declarada no incio de um bloco de cdigo. Assim, o programa a seguir no vlido em C (embora seja vlido em C++). int main() { int i; int j; j = 10; int k = 20; /* Esta declaracao de varivel no vlida, pois no est sendo feita no incio do bloco */ return(0); }

AUTO AVALIAO
Para treinar: Escreva um programa que declare uma varivel inteira global e atribua o valor 10 a ela. Declare outras 5 variveis inteiras locais ao programa principal e atribua os valores 20, 30, ..., 60 a elas. Declare 6 variveis caracteres e atribua a elas as letras c, o, e, l, h, a. Finalmente, o programa dever exibir, usando todas as variveis declaradas: As variveis inteiras contem os nmeros: 10, 20, 30, 40, 50, 60 A espe'cie de animal armazenada nas variveis caractere e' coelha

CONSTANTES
Constantes so valores fixos e pr-definidos e que no so modificados durante a

37

execuo de um programa. Diversos casos de uso de constantes foram abordados anteriormente. So consideradas constantes, por exemplo, os nmeros e caracteres como 45.65 ou 'n'.

Constantes de Tipos Bsicos


Abaixo vemos as constantes relativas aos tipos bsicos da linguagem C:

Tabela 4 - Exemplos de constantes

Constantes Hexadecimais e Octais


Em determinadas situaes necessria a manipulao de constantes hexadecimais (base 16) ou octais (base 8) em programas escritos em linguagem C. Em as constantes hexadecimais iniciam com o prefixo 0x e as constantes octais iniciam com o prefixo 0. Alguns exemplos:

Tabela 5 - Exemplo de constantes hexadecimal e octal

Isso significa que a constante octal 013 no ser compilada como a constante decimal 13. Na linguagem C, 013 na base 8 diferente de 13 na base 10!

Constantes string
Anteriormente foi mostrado como C trata strings. necessrio notar o fato de que

38

uma string Joao , na realidade, uma constante do tipo string. Isso implica, por exemplo, no fato de que t diferente de t, pois t uma constante do tipo char, enquanto que t uma constante do tipo string com dois caracteres: o primeiro t e o segundo o delimitador \0.

Constantes de Barra Invertida


A linguagem, para facilitar a tarefa de programar, utiliza vrios caracteres denominados como cdigo de barra invertida. So caracteres utilizados principalmente nos processos de entrada e sada de dados para controle desses processos. Uma lista com alguns dos cdigos de barra invertida mostrada abaixo:

Tabela 6 - Constantes de barra invertida

OPERADORES ARITMTICOS E DE ATRIBUIO


Os operadores aritmticos so usados para desenvolver operaes matemticas. Abaixo uma lista dos operadores aritmticos em C:

39

Tabela 7 - Operadores aritmticos

A linguagem C possui operadores aritmticos unrios e binrios. Os operadores unrios agem sobre o contedo de apenas uma varivel, modificando ou no o seu valor, e retornam esse valor na mesma varivel. Os operadores binrios agem sobre o contedo de duas variveis e retorna o resultado da operao em uma terceira varivel, sem alterar os contedos originais dessas variveis. A adio um operador binrio - age sobre duas variveis - soma o contedo de duas variveis, sem modificar os contedos originais dessas variveis, e devolve o resultado da operao em uma terceira varivel. Essa situao apenas ocorre se for utilizada essa terceira varivel para armazenamento do resultado da operao, o que no obrigatrio. possvel utilizar uma das duas variveis envolvidas na operao como destino de armazenamento do resultado da operao, entretanto, o contedo original dessa varivel ser modificado. Por exemplo: a expresso C=A+B tem comportamento diferente da expresso A=A+B. O operador -, quando utilizado nas operaes de inverso de sinal torna-se operador unrio e altera o contedo da varivel sobre a qual aplicado, pois retorna esse contedo multiplicado por -1. O operador / (diviso) quando aplicado a variveis inteiras, fornece o resultado da diviso inteira; quando aplicado a variveis em ponto flutuante nos fornece o resultado da diviso "real". O operador % fornece o resto da diviso de dois inteiros. Considerando o seguinte trecho de cdigo: int a = 17, b = 3; int x, y; float z = 17. , z1, z2;

40

x = a / b; y = a % b; z1 = z / b; z2 = a/b; ao final da execuo destas linhas, os valores calculados so x = 5, y = 2, z1 = 5.666666 e z2 = 5.0 . Na linha correspondente expresso z2=a/b, primeiramente feita uma diviso inteira, tendo em vista que as variveis a e b so do tipo int. Somente aps efetuada a diviso que o resultado atribudo a uma varivel do tipo float, no caso z2. Os operadores de incremento e decremento so unrios e alteram o contedo da varivel sobre a qual agem. O que eles fazem incrementar ou decrementar o contedo da varivel de 1 unidade. Assim: x++; x--; so equivalentes a x=x+1; x=x-1; Estes operadores podem ser pr-fixados ou ps-fixados. A diferena que quando so pr-fixados eles incrementam e retornam o valor da varivel j incrementada. Quando so ps-fixados eles retornam o valor da varivel sem o incremento e depois incrementam a varivel. Ento se x=23; y=x++; teremos y=23 e x=24. Em x=23; y=++x; teremos y=24 e x=24. Uma curiosidade: a linguagem de programao C++ tem este nome por ser considerada uma evoluo da linguagem C padro. A linguagem C++ igual linguagem C, porm oferece extenses que permitem a programao orientada a objeto, o que um recurso extra. O operador de atribuio em C o =. Esse operador atribui o contedo expresso direita do operador a uma varivel expressa esquerda do operador. direita do operador

41

pode ser indicada uma varivel ou a avaliao de uma expresso aritmtica. Isto significa que as seguintes expresses so vlidas: x=y=z=1.5; /* Expressao 1 */ if (k=w) ... /* Expressao 2 */ A expresso 1 vlida. Primeiramente atribudo o valor 1.5 varivel z, em seguida o contedo da varivel z atribudo varivel y e, finalmente o contedo da varivel y atribudo varivel x. A expresso 2 ser verdadeira se o contedo da varivel w for diferente de zero, pois esse ser o resultado retornado pela operao de atribuio k=w. Pense bem antes de usar a expresso dois, pois ela pode gerar erros de interpretao. Nas instrues de desvio condicional so avaliadas expresses lgicas nas quais os operadores utilizados so de relao e no de atribuio.

AUTO AVALIAO
Para treinar: Indique o contedo das variveis x, y e z depois da seguinte seqncia de operaes: int x,y,z; x=y=10; z=++x; x=-x; y++; x=x+y-(z--);

OPERADORES REALACIONAIS E LGICOS Operadores relacionais


Os operadores relacionais em C executam comparaes entre operandos. Os operandos podem ser representados por variveis, variveis e constantes e resultados de avaliao de expresses aritmticas.

42

Tabela 8 - Operadores relacionais

O resultado da avaliao de uma expresso lgica verdadeiro (1) ou falso (0). Para verificar o funcionamento dos operadores relacionais, execute o programa abaixo:
/* Este programa mostra o funcionamento dos operadores relacionais. */

#include <stdio.h> int main() { int i, j; printf("\nEntre com dois numeros inteiros: "); scanf("%d%d", &i, &j); printf("\n%d == %d %d\n", i, j, i==j); printf("\n%d != %d %d\n", i, j, i!=j); printf("\n%d <= %d %d\n", i, j, i<=j); printf("\n%d >= %d %d\n", i, j, i>=j); printf("\n%d < %d %d\n", i, j, i<j); printf("\n%d > %d %d\n", i, j, i>j); return(0); }

possvel notar que o resultado da avaliao das expresses relacionais escritas no programa sempre igual a 0 (falso) ou 1 (verdadeiro).

Operadores lgicos
Nas expresses lgicas compostas so utilizados os operadores lgicos. Uma expresso lgica composta formada por duas ou mais expresses lgicas simples e so combinadas pelos operadores lgicos.

Tabela 9 - Operadores lgicos

O uso combinado de operadores relacionais e lgicos proporciona a construo de uma grande variedade de expresses lgicas . A tabela-verdade abaixo, mostra os resultados produzidos pelo uso combinado de operadores lgicos.

43

Tabela 10 - Resultados de avaliao com operadores lgicos OR e AND

O programa a seguir ilustra o funcionamento dos operadores lgicos. Compile-o e faa testes com vrios valores para i e j: #include <stdio.h> int main() { int i, j; printf("informe dois nmeros(cada um sendo 0 ou 1): "); scanf("%d%d", &i, &j); printf("%d AND %d %d\n", i, j, i && j); printf("%d OR %d %d\n", i, j, i || j); printf("NOT %d %d\n", i, !i); }

44

No trecho de programa abaixo, a operao j++ ser executada, pois o resultado da expresso lgica verdadeiro: int i = 5, j =7; if ( (i > 3) && ( j <= 7) && ( i != j) ) j++; V AND V AND V = V O programa abaixo, exibe na tela, somente os nmeros pares entre 1 e 100, apesar da variao de i ocorrer de 1 em 1: /* Imprime os nmeros pares entre 1 e 100. */ #include <stdio.h> int main() { int i; for(i=1; i<=100; i++) if(!(i%2)) printf("%d ",i); }
/* o operador de resto ser falso (zero) */ /* quando usado c/ nmero par. Esse resultado*/ /* invertido pelo !(operador lgico de negao) */

Operadores Lgicos Bit a Bit


A linguagem C permite operaes lgicas bit a bit sobre contedos numricos. Neste caso, o nmero representado por sua forma binria e as operaes so feitas em cada um de seus bits. Supondo-se um valor numrico inteiro de 16 bits e um a varivel i, que armazena o contedo 2. A representao binria de i, ser: 0000000000000010 (quinze zeros e um nico 1 na segunda posio da direita para a esquerda). possvel executar operaes lgicas em cada um dos bits dessa varivel. Por exemplo, a negao (!) do nmero (operao binria (unrio) NOT, ou operador binrio (unrio) - em C), isto , -i, inverte o contedo binrio armazenado na varivel i em 1111111111111101. As operaes lgicas bit a bit fornecem recursos aos programadores que precisem trabalhar com o computador em "baixo nvel". As operaes lgicas bit a bit s podem ser aplicadas a variveis de tipos char, int e long int.

45

Esses operadores so mostrados abaixo:

Tabela 11 - Operadores lgicos bit a bit

Os operadores &, |, ^ e ~ so os operadores lgicos bit a bit. A forma geral dos operadores de deslocamento : valor >> nmero_de_deslocamentos valor << nmero_de_deslocamentos importante saber que a posio do bit mais significativo (most significant bit (MSB)) dos tipos de dados em C fica a extrema esquerda do contedo armazenado, enquanto que a posio do bit menos significativo (lower significant bit (LSB)) fica a extrema direita. Por exemplo o inteiro 73, representado por 8 bits: 01001001, onde o MSB o primeiro zero esquerda, enquanto que o LSB o primeiro um direita. O nmero_de_deslocamentos indica o quanto cada bit ser deslocado. Por exemplo, para a varivel i anterior, armazenando o contedo 2: i << 3; alterr a representao binria de i seja 0000000000010000, isto , o contedo armazenado em i passa a ser 16.

AUTO AVALIAO
Para treinar. Indique o resultado a ser produzido pela avaliao das expresses lgicas abaixo: ((10>5)||(5>10)) (!(5==6)&&(5!=6)&&((2>1)||(5<=4)))

EXPRESSES
Expresses so combinaes de variveis, constantes e operadores. Quando expresses so escritas necessrio levar em considerao a ordem em que os operadores

46

so executados, conforme a tabela de precedncias da linguagem C. No demais lembrar que expresses podem ser classificadas em aritmticas e lgicas e, tanto uma , como a outra, obedecem as regras de precedncia de operadores Exemplos de expresses: Anos=Dias/365.25; i = i+3; c = a*b + d/e; c = a*(b+d)/e;

Converso de Tipos em Expresses


Quando C avalia expresses que envolvem variveis de tipos diferentes, o compilador verifica se as converses so possveis. Se no so, o programa no ser compilado, exibindo mensagem de erro. Se as converses forem possveis elas so feitas, seguindo as regras abaixo: 1. As variveis do tipo char e do tipo short int so convertidos para o tipo int. As variveis do tipo float so convertidos para o tipo double. 2. 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.

Expresses que Podem Ser Abreviadas


A linguagem C admite as seguintes equivalncias, que podem ser usadas para simplificar expresses ou para facilitar o entendimento de um programa: Expresso original
x x x x x x x = = = = = = = x x x x x x x + * / >> << & k; k; k; k; k; k; k;

Expresso equivalente
x x x x x x x += -= *= /= >>= <<= &= k; k; k; k; k; k; k;

Encadeamento de Expresses O Operador , (vrgula)


O operador vrgula (,) determina uma lista de expresses que devem ser executadas seqencialmente.

47

Em sntese, a vrgula diz ao compilador: execute as duas expresses separadas pela vrgula, em seqncia. O valor retornado por uma expresso com o operador vrgula (,) sempre dado pela expresso mais direita. No exemplo abaixo: x = ( y = 2 , y + 3 ); o contedo 2 ser atribudo varivel y, o valor ser 3 somado ao contedo da varivel y e o contedo final (5) ser atribudo varivel x . Pode-se encadear quantos operadores forem necessrios. O exemplo a seguir mostra outro uso para o operador vrgula (,) em um comando for: #include<stdio.h> int main() { int x, y; for(x=0 , y=0 ; x+y < 100 ; ++x , y++) /* Duas variveis de controle: x e y . Foi atribudo o valor zero a cada uma delas na inicializao do for e ambas so incrementadas na parte de incremento do for */ printf("\n%d ", x+y); /* o programa imprimir os nmeros pares de 0 a 98 */ }

Tabela de Precedncia em C
A tabela abaixo mostra a precedncia dos operadores em C. Alguns (poucos) operadores ainda no foram abordados e sero apresentados posteriormente. Maior precedncia () [] -> ! ~ ++ -- . -(unrio) (cast) *(unrio) &(unrio) sizeof */% +<< >> <<= >>= == != & ^ | && || ? = += -= *= /=

Menor precedncia

48

Tabela 12 - Precedncia na Linguagem C

Dica para iniciantes: No necessrio conhecer toda a tabela de precedncias. til que sejam conhecidas as principais relaes, mas aconselhvel que ao escrever o cdigo, as expresses sejam isoladas com parnteses, para tornar o seu programa mais legvel.

MODELADORES (CASTS)
Um modelador aplicado a uma expresso. Ele obriga a expresso a setornar de um tipo especificado. Sua forma geral : (tipo)expresso Um exemplo: #include <stdio.h> int main () { int num; float f; num=10; f = (float)num/7; /* Uso do modelador. Fora a transformao de uma varivel do tipo num em uma varivel do tipo float */ printf ("%f",f); return(0); } Sem o uso do modelador no exemplo acima, a linguagem C faria uma diviso inteira entre 10 e 7. O resultado seria 1 (um) e esse resultado convertido para float, mas continuaria a ser 1.0. Com o modelador o resultado correto produzido.

AUTO AVALIAO
Para treinar. Compile o exemplo acima sem usar o modelador, e verifique os resultados. Compile-o novamente usando o modelador e compare a sada com os resultados anteriores. Escolha a opo que inclui somente nomes vlidos para definio de variveis na linguagem C. ( ) If, a_b_2, H789, _yes ( ) i, j, int, obs

49

( ) 9xy, a36, x*y, --j ( ) 2_ou_1, \fim, *h, j ( ) Nenhuma das opes anteriores

50

Qual das instrues abaixo est errada? ( ( ( ( ( ( ) int i; ) long float x; ) long double y; ) long ijk; ) short int a; ) unsigned b;

Em um compilador para um hardware de 16 bits uma varivel do tipo double ocupa o mesmo espao que _____ variveis do tipo char ( ( ( ( ( ( ( ( ( ) Uma ) Duas ) Quatro ) Oito ) Dezesseis ) float z , z1=10.; ) float z; z = 10; ) float z = 10; ) z = 10;

Qual o trecho de programa que inicializa a varivel z?

O trecho de programa a seguir main() { char condicao; condicao = D; int i = 1; } ( ) Vlido na linguagem C ( ) No vlido na linguagem C 0101 uma constante __________ na linguagem C. ( ( ( ( ( ) Binria ) Hexadecimal ) Inteira ) Octal ) Ponto Flutuante

Em C, "t" e 't' representam a mesma constante. ( ) Verdadeiro ( ) Falso Indique o contedo das variveis x, y e z depois na seguinte sequncia de operaes: int x,y,z;

51

x=y=10; z=++x; x=-x; y++; x=x+y-(z--); ( ( ( ( ( ) x = 11, y = 11, z = 11 ) x = -11, y = 11, z = 10 ) x = -10, y = 11, z = 10 ) x = -10, y = 10, z = 10 ) Nenhuma das opes anteriores

Indique o contedo das variveis x, y e z depois na seguinte seqncia de operaes: int x,y; int a = 14, b = 3; float z; x = a/b; y = a%b; z = y/x; ( ( ( ( ( ( ( ( ( ( ( ) x = 4.66666, y = 2, z = 0.4286 ) x = 5, y =2, z= 0.4 ) x = 5, y = 2, z = 0. ) x = 4, y = 2, z = 0.5 ) x = 4, y =2, z = 0. ) Nenhuma das opes anteriores ) Verdadeira ) Falsa ) Invlida, pois a sintaxe est errada. ) Nem Verdadeira nem Falsa ) Nenhuma das opes anteriores

A operao lgica (-5 || 0)&&(3 >= 2)&&(1 != 0)||(3 < 0) :

Quais os contedos de a, b e c aps a execuo do cdigo abaixo? int a = 10, b = 20, c; c = a+++b; ( ( ( ( ( ) a = 11, b = 20, c =30 ) a = 10 , b = 21, c = 31 ) a = 11, b = 20, c = 31 ) a = 10, b = 21, c = 30 ) Nenhuma das opes anteriores

52

Qual o contedo das variveis v, x, y e z aps a execuo do seguinte trecho de cdigo int v = 0, x = 1, y = 2, z = 3; v += x+y; x *= y = z + 1; z %= v + v + v; v += x += y += 2;_ ( ) v=11, x=8, y=6, z=3 ( ) v=0, x=1, y=2, z=3 ( ) v=10, x=7, y=6, z=3 ( ) v=13, x=10, y=6, z=3 ( ) Nenhuma das opes anteriores

ESTRUTURAS DE CONTROLE DE FLUXO


As estruturas de controle de fluxo so fundamentais para qualquer linguagem de programao. Sem elas haveria apenas uma maneira de um programa ser executado: de cima para baixo comando por comando. No haveria desvios condicionais, estruturas de repetio ou saltos. A linguagem C possui diversos comandos de controle de fluxo. possvel resolver todos os problemas sem utilizar todas elas, mas importante lembrar que a elegncia e facilidade de entendimento de um programa dependem do uso correto das estruturas no local certo.

O COMANDO IF
O comando if foi visto anteriormente. Sua forma geral : if (condio) declarao; A expresso lgica, representada por uma condio, ser avaliada. Se o seu resultado for igual a zero, a declarao no ser executada. Se o resultado da expresso for diferente de zero a declarao ser executada. Abaixo reapresentado o exemplo de uso do comando if: #include <stdio.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num); if (num>10)

53

printf ("\n\nO numero e maior que 10"); if (num==10) { printf ("\n\nVoce acertou!\n"); printf ("O numero e igual a 10."); } if (num<10) printf ("\n\nO numero e menor que 10"); return(0); }

O else
Podemos pensar no comando else como sendo um complemento do comando if. O comando if completo tem a seguinte forma geral: if (condio) declarao_1; else declarao_2; A expresso lgica, representada por condio, avaliada. Se o resultado for diferente de zero a declarao 1 ser executada. Se o resultado da avaliao for igual a zero a declarao 2 ser executada. importante nunca esquecer que, ao usar a estrutura if-else, estamos garantindo que uma das duas declaraes ser executada. Em qualquer situao, uma ou outra, sempre ser executada. Abaixo est um exemplo do uso do if-else que deve funciona como o programa da seo anterior. #include <stdio.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num); if (num==10) { printf ("\n\nVoce acertou!\n"); printf ("O numero e igual a 10.\n"); } else { printf ("\n\nVoce errou!\n"); printf ("O numero e diferente de 10.\n"); } return(0); }

54

O if-else-if
A estrutura if-else-if apenas uma extenso da estrutura if-else. Sua forma geral pode ser escrita como sendo: if (condio_1) declarao_1; else if (condio_2) declarao_2; else if (condio_3) declarao_3; else if (condio_n) declarao_n; else declarao_default; A estrutura acima funciona da seguinte maneira: o programa inicia pela avaliao da expresso lgica, representada por condio_1 e continua a avaliao at que seja encontrada uma expresso cujo resultado seja diferente de zero. Neste caso ele executa a declarao correspondente. Somente uma declarao ser executada, ou seja, somente ser executada a declarao correspondente avaliao da expresso cujo resultado for diferente de zero. A ltima declarao (default) ser executada somente no caso em que os resultados da avaliao de todas as expresses lgicas forem iguais a zero, entretanto essa ltima declarao opcional. Um exemplo da estrutura acima: #include <stdio.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num); if (num>10) printf ("\n\nO numero e maior que 10"); else if (num==10) { printf ("\n\nVoce acertou!\n"); printf ("O numero e igual a 10."); } else if (num<10) printf ("\n\nO numero e menor que 10"); return(0); }

55

A Expresso Condicional
Ao avaliar uma expresso o compilador espera um valor de retorno para tomar uma deciso. Essa expresso no necessita ser uma expresso no sentido convencional. Uma varivel sozinha pode ser uma "expresso" e retorna o seu prprio contedo. Isto quer dizer que as seguintes expresses so possveis: int num; if (num!=0) ... if (num==0) ... for (i = 0; string[i] != \0; i++) e equivalem a int num; if (num) ... if (!num) ... for (i = 0; string[i]; i++) Isso quer dizer que podemos simplificar ainda mais algumas expresses simples.

Ifs Aninhados
O if aninhado simplesmente um if dentro da declarao de um outro if externo. O nico cuidado a ser observado saber exatamente a qual if um determinado else est associado. Um exemplo: #include <stdio.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num); if (num==10) { printf ("\n\nVoce acertou!\n"); printf ("O numero e igual a 10.\n"); } else { if (num>10) { printf ("O numero e maior que 10."); } else { printf ("O numero e menor que 10.");

56

} } return(0); }

57

O Operador ? (interrogao)
Uma expresso como a seguir: 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 expresses do tipo: if (condio) expresso_1; else expresso_2; podem ser substitudas por: condio?expresso_1:expresso_2; O operador ? limitado (no contempla uma gama muito grande de casos), mas pode ser usado para simplificar expresses complicadas. Uma aplicao interessante a do contador circular. Veja o exemplo: #include <stdio.h> int main() { int index = 0, contador; char letras[5] = "Joao"; for (contador=0; contador < 1000; contador++) { printf("\n%c",letras[index]); (index==3) ? index=0: ++index; } } O nome Joao exibido na tela verticalmente at a varivel contador determinar o trmino do programa. Enquanto isso a varivel index assume os contedos 0, 1, 2, 3, , 0, 1, ... progressivamente.

O COMANDO SWITCH
O comando if-else e o comando switch so comandos de tomada de deciso. Sem dvida alguma o mais importante dos dois o if, mas o comando switch tem aplicaes

58

valiosas. Mais uma vez vale lembrar que devemos usar o comando certo no local certo. Isto assegura um cdigo limpo e de fcil entendimento. O comando switch prprio para se testar uma varivel em relao a diversos valores pr-estabelecidos. Sua forma geral : switch (varivel) { case constante_1: declarao_1; break; case constante_2: declarao_2; break; . . . case constante_n: declarao_n; break; default: declarao_default; } Podemos fazer uma analogia entre o switch e a estrutura if-else-if apresentada anteriormente. A diferena fundamental que a estrutura switch no aceita expresses, apenas constantes. O comando switch avalia o contedo de uma varivel e executa a declarao cujo resultado corresponda ao contedo da varivel no instante da avaliao. A declarao default opcional e ser executada apenas se o contedo da varivel avaliada, for diferente dos valores constantes associados. O comando break provoca a interrupo do comando switch assim que qualquer das declaraes seja executada, mas essencial ao comando switch. Se aps a execuo da declarao no for encontrado o comando break, o programa em execuo. Isso pode ser til em algumas situaes, mas recomenda-se ateno, pois a aplicabilidade do comando switch pressupe o conhecimento prvio de um intervalo de contedos a ser armazenado (valores discretos) na varivel.

59

Exemplo do comando switch: #include <stdio.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num); switch (num) { case 9: printf ("\n\nO numero e igual a break; case 10: printf ("\n\nO numero e igual a break; case 11: printf ("\n\nO numero e igual a break; default: printf ("\n\nO numero nao e nem } return(0); }

9.\n"); 10.\n"); 11.\n"); 9 nem 10 nem 11.\n");

AUTO AVALIAO
Para treinar. Escreva um programa que pede para o usurio entrar com um nmero correspondente a um dos sete dias da semana e exiba na tela o nome correspondente a esse dia, utilizando o comando switch.

ESTRUTURAS DE REPETIO (LAOS)


O comando for foi o primeiro de uma srie de trs estruturas visto para controle de fluxo atravs de laos. As outras so while e do-while. Essa trs estruturas compem a segunda famlia de comandos de controle de fluxo e so estruturas de repetio controlada. Como visto anteriormente, o lao for usado para repetir um comando, ou bloco de comandos, diversas vezes, de maneira controlada. Sua forma geral : for (inicializao;condio;incremento) declarao; A semntica do lao for tambm j foi objeto de estudo anteriormente. O lao for na linguagem C bastante flexvel. Temos acesso inicializao,

60

condio e ao incremento. Qualquer um desses elementos pode ser representado p uma expresso qualquer em C, desde que ela seja vlida. Isto nos permite fazer o que quisermos com esse comando. Qualquer das trs formas do comando for, abaixo, so vlidas:
for (count = 1; count < 100 ; count++) { } for (count = 1; count < NUMERO_DE_ELEMENTOS ; count++) { } for (count = 1; count < BusqueNumeroDeElementos() ; count+=2) { }

Especial ateno ao ltimo exemplo: o incremento de dois em dois. Alm disso, o controle de repetio do lao chama uma funo (BusqueNumeroDeElementos() ) que retorna um valor a ser comparado com o contedo da varivel count.

Lao Infinito
Um lao infinito tem a forma for (inicializao; ;incremento) declarao; Um lao recebe esse nome porque ser executado infinitamente (a omisso de uma expresso lgica a ser avaliada ter sempre, como resultado, verdadeiro), a no ser que ele seja interrompido de modo forado. Para interromper um lao como este usa-se o comando break;. O comando break (quebra) interrompe um lao, infinito ou no) e o programa continuar a ser executado normalmente. Como exemplo, um programa que faz a leitura de uma tecla e sua exibio na tela, at que o usurio escolha uma tecla sinalizadora de final (um FLAG). O FLAG, neste caso, corresponde tecla correspondente letra 'X' ((maiscula), pode ser qualquer outra. No interior do lao a funo scanf() chamada duas vezes. Uma vez busca o caractere que digitado e na outra busca o caractere digitado na seqncia, que o caractere correspondente tecla <ENTER>.

61

#include <stdio.h> int main () { int Count; char ch; printf(" Digite uma letra - <X para sair> "); for (Count=1;;Count++) { scanf("%c", &ch); if (ch == X) break; printf("\nLetra: %c \n",ch); scanf("%c", &ch); } return(0); }

Lao sem Contedo


Loop sem contedo aquele no qual se omite uma declarao. Sua forma geral (ateno ao ponto e vrgula!): for (inicializao;condio;incremento); Uma das aplicaes desse tipo de estrutura gerar tempos de espera. O programa abaixo um exemplo disso. #include <stdio.h> int main () { long int i; printf("\a"); /* Imprime o caracter de alerta (um beep) */ for (i=0; i<10000000; i++); /* Espera 10.000.000 de iteracoes printf("\a"); /* Imprime outro caracter de alerta */ return(0); }

*/

O COMANDO WHILE
O comando while tem a seguinte forma geral: while (condio) declarao; O comando while tem semntica equivalente ao comando for: if (condio) { declarao; "Volte para o comando if" }

62

Da mesma maneira, o comando while avalia uma expresso lgica, representada por condio. Se o resultado for verdadeiro a declarao executada e a expresso lgica avaliada novamente, sucessivamente. Do mesmo modo, laos infinitos tambm podem ser construdos com essa estrutura, bem como omitir a declarao e fazer um lao sem contedo. Exemplo do uso do comando while: o programa abaixo executado enquanto i for menor que 100. A sua implementao com um lao for seria mais natural. #include <stdio.h> int main () { int i = 0; while ( i < 100) { printf(" %d", i); i++; } return(0); } No exemplo abaixo, o programa aguarda que o usurio digite a tecla 'q' e s depois finaliza: #include <stdio.h> int main () { char Ch; Ch=\0; while (Ch!=q) { scanf("%c", &Ch); } return(0); }

O COMANDO DO-WHILE
A terceira estrutura de repetio o comando do-while e sua forma geral : do { declarao; } while (condio); Mesmo que a declarao seja representada por apenas um comando considera-se

63

uma boa prtica encerr-lo entre chaves. O ponto-e-vrgula final obrigatrio. A seguir a semntica desse tipo de lao: declarao; if (condio) "Volta para a declarao" possvel perceber que a estrutura do-while executa a declarao, em seguida, avalia a expresso lgica, representada por condio, e se o resultado for verdadeiro, volta a executar a declarao. A diferena que o comando do-while, ao contrrio dos comandos for e while, a declarao ser executada pelo menos uma vez. Uma das aplicaes mais freqentes da estrutura do-while a implementao de menus, nos quais o propsito garantir que o valor digitado pelo usurio seja vlido, conforme mostrado abaixo: #include <stdio.h> int main () { int i; do { printf ("\n\nEscolha a fruta pelo numero:\n\n"); printf ("\t(1)...Mamao\n"); printf ("\t(2)...Abacaxi\n"); printf ("\t(3)...Laranja\n\n"); scanf("%d", &i); } while ((i<1)||(i>3)); switch (i) { case 1: printf ("\t\tVoce escolheu Mamao.\n"); break; case 2: printf ("\t\tVoce escolheu Abacaxi.\n"); break; case 3: printf ("\t\tVoce escolheu Laranja.\n"); break; } return(0); }

O COMANDO BREAK
O comando break foi visto anteriormente, em duas situaes distintas, a interrupo

64

dos comandos switch e for. Na verdade, essas so as duas situaes em que o comando break se aplica: ele interrompe (quebra) a execuo de um comando (switch) ou interrompe a execuo de qualquer lao (for, while ou do-while). O comando break faz com que a execuo do programa prossiga, sequencialmente, a partir da primeira linha aps o lao ou bloco de comando interrompido. Observe que um comando break causa a interrupo de execuo somente do lao mais interno. Por exemplo: for(t=0; t<100; ++t) { count=1; for(;;) { printf("%d", count); count++; if(count==10) break; } } O cdigo acima exibe os nmeros de 1 a 10, cem vezes na tela. Toda vez que o comando break executado, o controle devolvido para o lao for externo. Outra observao o fato que um comando break usado dentro de uma declarao do comando switch afetar somente os dados relacionados a esse comando e no qualquer outro lao em que o comando switch seja interno.

O COMANDO CONTINUE
O comando continue o oposto do comando break. Seu funcionamento est condicionado ao interior de um lao. Quando um comando continue encontrado, o lao volta para a prxima iterao (incio do lao), sem que o lao seja abandonado, ao contrrio do que ocorre com o comando break.

65

O programa abaixo exemplifica o uso do comando continue: #include <stdio.h> int main() { int opcao; while (opcao != 5) { printf("\n\n Escolha uma opcao entre 1 e 5: "); scanf("%d", &opcao); if ((opcao > 5)||(opcao <1)) continue; /* Opcao invalida: volta ao inicio do loop */ switch (opcao) { case 1: printf("\n --> Primeira opcao.."); break; case 2: printf("\n --> Segunda opcao.."); break; case 3: printf("\n --> Terceira opcao.."); break; case 4: printf("\n --> Quarta opcao.."); break; case 5: printf("\n --> Abandonando.."); break; } } return(0); } O programa acima ilustra uma aplicao simples para o comando continue. Recebe uma opo do usurio. Se a opo for invlida, o comando continue provoca o desvio do fluxo de execuo para o incio do lao. Caso a opo escolhida seja vlida o programa prossegue normalmente no fluxo de execuo.

O COMANDO GOTO
O comando goto ser mencionado apenas para mostrar a sua existncia. Esse comando o ltimo comando de controle de fluxo e pertence a uma classe parte: a dos comandos de desvio incondicional.

66

O comando goto realiza provoca um desvio para um ponto especfico do programa. Esse local determinado por um rtulo (label). Um rtulo, na linguagem C, uma marca no programa. Qualquer nome pode ser dado a essa marca. Sua forma geral pode ser considerada como abaixo: nome_do_rtulo: ... goto nome_do_rtulo; ... A restrio a ser considerada em relao ao uso do comando goto que o desvio provocado por esse comando no segue os padres de controle de fluxo caracterstico das estruturas de repetio (laos). Isso significa que um determinado trecho de programa, ignorado pelo uso do comando goto, somente ser executado em uma situao em que outro comando goto provoque um desvio para esse trecho ou, em uma situao inversa, a repetio de um trecho de programa, provocado pelo comando goto somente ser interrompida por outro comando goto no interior do mesmo trecho de programa que se repete. Ora, a utilizao indiscriminada e pouco criteriosa desse comando tende a causar srios problemas de controle de execuo de um programa, alm de dificultar sua construo e manuteno. Feita essa ressalva, um nome de rtulo deve ser declarado na posio para a qual ser feito o desvio seguido do delimitador : (dois pontos). O rtulo posicional e pode estar declarado antes da declarao do comando goto (mais natural, pois mantm coerncia com os laos de repetio) ou aps a declarao do comando goto, e esta a principal razo para a restrio ao seu uso. recomendvel que tanto o rtulo, como o comando estejam declarados dentro de uma mesma funo, caso contrrio os resultados so imprevisveis e potencialmente desastrosos. Como exemplo do uso do comando goto o comando for, visto anteriormente, reescrito de forma equivalente: inicializao; incio_do_loop: if (condio) { declarao; incremento; goto incio_do_loop;

67

} Assim sendo, o comando goto deve ser utilizado com moderao, pois o abuso tende a tornar o cdigo confuso. Esse comando no estritamente necessrio, e pode ser substitudo por outras estruturas de controle. Recomenda-se que o comando goto nunca seja usado. Em algumas situaes muito especficas o seu uso pode facilitar o entendimento do cdigo escrito, se for bem empregado. Uma das situaes em que seu emprego se torna til quando uma construo emprega vrios laos e desvios condicionais aninhados e necessrio, por qualquer motivo, abandonar esses laos e desvios condicionais, todos de uma vez. Neste caso um comando goto resolve o problema de modo mais elegante e rpido do que vrios comandos break, sem contar que uma quantidade muito grande desses comandos exigiro testes exaustivos que assegurem o perfeito funcionamento dessas interrupes. O exemplo imediatamente anterior pode ser reescrito usando-se o comando goto:
#include <stdio.h> int main() { int opcao; while (opcao != 5) { REFAZ: /* Nome do rtulo */ printf("\n\n Escolha uma opcao entre 1 e 5: "); scanf("%d", &opcao); if ((opcao > 5)||(opcao <1)) goto REFAZ; /* Opcao invalida: volta ao rotulo REFAZ */ switch (opcao) { case 1: printf("\n --> Primeira opcao.."); break; case 2: printf("\n --> Segunda opcao.."); break; case 3: printf("\n --> Terceira opcao.."); break; case 4: printf("\n --> Quarta opcao.."); break; case 5: _ printf("\n --> Abandonando..");

68

break; } } return(0); }

AUTO AVALIAO
Escreva um programa que solicite ao usurio a entrada de trs valores inteiros, correspondentes a dia, ms e ano, respectivamente. Repita esse procedimento at que os valores de entrada estejam nas faixas especificadas (dias entre 1 e 31, ms entre 1 e 12 e ano entre 1900 e 2100). Verifique se o ms e o nmero de dias informados so correspondentes (incluindo verificao de anos bissextos). Se os valores estiverem corretos exibir a data informada pelo usurio. Recomenda-se o uso de comentrios. Um ano considerado bissexto quando divisvel por 4 e no divisvel por 100, exceto para anos divisveis por 400, que tambm so bissextos. if(num) ...; equivalente a if(num!=0) ...; ( ) Verdadeiro ( ) Falso Qual o valor de x aps a seguinte seqncia de comandos: a b x x ( ( ( ( ( ( = = = = 10; 20; 0; (b > a) ? b : a;

)0 )2 ) 10 ) 20 ) 40 ) Nenhuma das opes anteriores

Qual o valor de x aps a seqncia de comandos: a = 1; b = 2; c = 3; x = 0; x = a < b ? a < c ? a : c : b < c ? b : c; (DICA: antes de tentar resolver, coloque parnteses na expresso acima, indicando a ordem de precedncia dos operadores) ( ( ( ( )0 )1 )2 )3

69

( ) Nenhuma das opes anteriores

70

Os trechos de programa a seguir so equivalentes entre si, sob o ponto de vista do que exibido: for (i = 0 ; i < 10; i++) printf("%d", i); e for (i = 0 ; i < 10; ++i) printf("%d", i); ( ) Verdadeiro ( ) Falso O trecho de programa a seguir switch(num) { case 1; printf("O numero e 1 "); break; case 2; printf("O numero e 2 "); break; default; printf("O numero e diferente de 1 e 2"); break; } ( ) Vlido na linguagem C ( ) No vlido na linguagem C Sendo num uma varivel inteira, o ser exibido pelo trecho de cdigo a seguir? num = 1; switch(num) { case 1: printf("O numero e 1 "); case 2: printf("O numero e 2 "); default: printf("O numero e diferente de 1 e 2"); } ( ( ( ( ( ) O numero e 1 ) O numero e 2 ) O numero e diferente de 1 e 2 ) O numero e 1 O numero e 2 ) O numero e 1 O numero e 2 O numero e diferente de 1 e 2

71

Os dois blocos de cdigo a seguir produzem o mesmo resultado: for( i = 0 ; i < 3 ; i++) for ( j =0 ; j < 3; j++) printf("i+j = %d \n", i+j); e for( i = 0 , j=0 ; i < 3 ; i++) for ( ; j < 3 ; j++) printf("i+j = %d \n", i+j); ( ) Verdadeiro ( ) Falso Qual a sada produzida pelo extrato de cdigo a seguir: int x; for ( x = 35 ; x > 0 ; x/=3) printf("%d " , x) ; ( ( ( ( ( ) 35 11 3 1 ) 11 3 1 ) 11 3 1 0 ) 35 11 3 ) Nenhuma das opes anteriores_

Os extratos de cdigo a seguir so equivalentes entre si: int x = 10; while (--x > 9) { printf("%d", x); } e int x = 10; do { printf("%d", x); } while(--x > 9); ( ) Verdadeiro ( ) Falso

72

Sendo i declarado e inicializado como: int i = 0; os seguintes extratos de cdigo: while (i = 5) { printf("%d %d %d \n", i, i+2, i+4); i = 0; } e if (i = 5) printf ("%d %d %d \n", i, i+2, i+4); ( ( ( ( ) So idnticos sob o ponto de vista do que exibem na tela ) No exibem nada na tela ) Tm sintaxe errada ) Um deles, exibe 5, 7 e 9 uma nica vez e, o outro entra em loop, exibindo estes valores indefinidamente ( ) Nenhuma das opes anteriores switch (t) { case t < 10: printf("Hoje ta fazendo muito frio"); break; case t < 25: printf("A temperatura est agradavel"); break; default: printf("Hoje ta' quente pra chuchu"); } ( ) Vlida na linguagem C ( ) No vlida na linguagem C O lao for a seguir int i; for ( i = 0 ; i <= 5; i++ , printf("%d ", i)); ( ( ( ( ( ) Imprime 0 1 2 3 4 5 ) No funciona, pois tem sintaxe errada ) Imprime 1 2 3 4 5 6 ) Imprime 1 2 3 4 5 ) Nenhuma das opes anteriores

A estrutura do switch abaixo :

73

VETORES, STRINGS, MATRIZES

VETORES
Vetores nada mais so que matrizes unidimensionais. So uma estrutura de dados muito utilizadas. importante notar que vetores, matrizes bidimensionais ou matrizes de qualquer dimenso so caracterizadas por terem todos os elementos pertencentes ao mesmo tipo de dado. A declarao de um vetor dada pela forma geral: tipo_da_varivel nome_da_varivel [tamanho]; Essa declarao aloca espao suficiente na memria para conter o nmero de elementos especificado por tamanho. Por exemplo, a declarao: float exemplo [20]; solicita a alocao de 4x20 = 80 bytes. Estes bytes so alocados de maneira contgua. Na linguagem C a identificao posicional de cada elemento do vetor comea sempre em zero. Isto significa que, no exemplo acima, os elementos sero indexados de 0 a 19, conforme mostrado abaixo: exemplo[0] exemplo[1] . . . exemplo[19] Mas, nada impede a referncia abaixo: exemplo[30] exemplo[103] Por qu? Porque C no verifica a validade dos ndices (posicionadores, apontadores) nos limites do vetor declarado. Este um cuidado que o programador deve observar. Se o programador no tiver ateno com os limites de validade para os ndices ele corre o risco de ter variveis sobrescritas ou provocar erros por violao de memria.

74

Exemplo de utilizao de vetores: #include <stdio.h> int main () { int num[100]; /* Declara um vetor de inteiros de 100 posicoes */ int count=0; int totalnums; do { printf ("\nEntre com um numero (-999 p/ terminar): "); scanf ("%d",&num[count]); count++; } while (num[count-1]!=-999); totalnums=count-1; printf ("\n\n\n\t Os nmeros que voc digitou foram:\n\n"); for (count=0;count<totalnums;count++) printf (" %d",num[count]); return(0); } No exemplo acima, o inteiro count inicializado com 0. O programa pede pela entrada de nmeros at que o usurio entre com o valor -999. Os nmeros so armazenados no vetor num. A cada valor armazenado, o contador do vetor incrementado para, na prxima iterao, escrever (armazenar) na prxima posio do vetor. Quando o usurio digitar o valor -999, o programa abandona o primeiro lao e armazena o total de valores carregados no vetor. Por fim, todos os nmeros so exibidos. bom lembrar aqui que nenhuma restrio feita quanto quantidade de nmeros digitados. Se o usurio digitar mais de 100 nmeros, o programa tentar ler normalmente, mas o programa os escrever em uma parte no alocada de memria, pois o espao alocado foi para somente 100 inteiros. Isso pode provocar os mais variados erros no instante da execuo do programa.

AUTO AVALIAO
Reescreva o exemplo acima, de maneira que, a cada leitura seja feita uma averiguao para assegurar que a dimenso do vetor no foi excedida. Caso esse limite seja excedido, o programa dever abandonar o lao de leitura automaticamente. O uso do limite representado pelo valor -999 no deve ser retirado.

75

STRINGS
Strings so vetores cujos elementos armazenam contedos do tipo char. As strings so de uso comum como vetores. Especial ateno deve ser dada ao fato de que strings tm como contedo em seu ltimo elemento a constante barra invetida '\0'. A declarao geral para uma string : char nome_da_string [tamanho]; Lembrar que tamanho da string deve prever o elemento para armazenamento do '\0' que indica final da cadeia. A biblioteca padro do C possui diversas funes que manipulam strings. Estas funes so teis, pois no possvel, por exemplo, igualar duas strings: string1=string2; /* NAO faca isto */ Fazer isto um desastre. A seo que trata de ponteiros explica o porqu. As strings devem ser igualadas elemento a elemento. Programas que tratam de string muitas vezes podem tirar bom proveito do fato de que uma string termina com '\0' (isto , o nmero inteiro 0). Veja, por exemplo, o programa abaixo que serve para igualar duas strings (isto , copia os caracteres de uma string para outra): #include <stdio.h> int main () { int count; char str1[100],str2[100]; /* Aqui o programa le str1 que sera copiada para str2 */ for (count=0;str1[count];count++) str2[count]=str1[count]; str2[count]=\0; /* Aqui o programa continua */ } A condio no lao for acima apoiada no fato de que a string que est sendo copiada termina em '\0'. Quando o elemento encontrado em str[count] igual a '\0', o valor retornado para o teste condicional falso (nulo). Desta forma a expresso que vinha sendo verdadeira (no zero) continuamente, torna-se falsa. Algumas funes bsicas para manipulao de strings.

76

gets
A funo l uma string do teclado. Sua forma geral : gets (nome_da_string); O programa abaixo demonstra o funcionamento da funo JHWV__: #include <stdio.h> int main () { char string[100]; printf ("Digite o seu nome: "); gets (string); printf ("\n\n Ola %s",string); return(0); } vlido passar para a funo printf() o nome da string. Mais adiante ser visto porque isso vlido. Como o primeiro argumento da funo printf() uma string tambm vlido fazer: printf (string); isso simplesmente exibir a string.

strcpy
Sua forma geral : strcpy (string_destino,string_origem); A funo strcpy() copia a string-origem para a string- destino. Seu funcionamento semelhante ao da funo apresentada na seo anterior. As funes apresentadas nestas sees esto no arquivo cabealho string.h. Exemplo de uso da funo strcpy(): #include <stdio.h> #include <string.h> int main () { char str1[100],str2[100],str3[100]; printf ("Entre com uma string: "); gets (str1); strcpy (str2,str1); /* Copia str1 em str2 */ strcpy (str3,"Voce digitou a string "); /* Copia "Voce digitou a string" em str3 */ printf ("\n\n%s%s",str3,str2); return(0);

77

strcat
A funo strcat() tem a forma geral: strcat (string_destino,string_origem); A string de origem permanecer inalterada e ser anexada ao fim da string de destino. Um exemplo: #include <stdio.h> #include <string.h> int main () { char str1[100],str2[100]; printf ("Entre com uma string: "); gets (str1); strcpy (str2,"Voce digitou a string "); strcat (str2,str1); /* str2 armazenara Voce digitou a string + o conteudo de str1 */ printf ("\n\n%s",str2); return(0); }

strlen
Sua forma geral : strlen (string); A funo strlen() retorna o comprimento da string fornecida. O terminador nulo no considerado. Isto quer dizer que, de fato, o comprimento real da string deve ser um a mais que o inteiro retornado por stralen(). Um exemplo do seu uso: #include <stdio.h> #include <string.h> int main () { int size; char str[100]; printf ("Entre com uma string: "); gets (str); size=strlen (str); printf ("\n\nA string que voce digitou tem tamanho %d",size); return(0); }

78

strcmp
Sua forma geral : strcmp (string1,string2); A funo strcmp() compara duas strings (string1 e string2). Se as duas forem idnticas a funo retorna zero. Se elas forem diferentes a funo retorna no-zero. Um exemplo da sua utilizao: #include <stdio.h> #include <string.h> int main () { char str1[100],str2[100]; printf ("Entre com uma string: "); gets (str1); printf ("\n\nEntre com outra string: "); gets (str2); if (strcmp(str1,str2)) printf ("\n\nAs duas strings so diferentes."); else printf ("\n\nAs duas strings so iguais."); return(0); }

AUTOAVALIAO
Escreva um programa que leia quatro palavras pelo teclado, e armazene cada palavra em uma string. Depois, concatene todas as strings lidas em uma nica string. Por fim apresentea como resultado ao final do programa.

MATRIZES Matrizes bidimenesionais


A forma geral da declarao de uma matriz bidimensional muito parecida com a declarao de um vetor: tipo_da_varivel nome_da_varivel [linhas][colunas]; muito importante ressaltar que, nesta estrutura, so necessrios dois indexadores (posicionadores, apontadores) para manipular um elemento da matriz, o ndice da esquerda indexa linhas e o da direita indexa colunas. Quando vamos preencher ou ler uma matriz em C o ndice mais direita varia mais rapidamente que o ndice esquerda, eventualmente. Mais uma vez bom frisar que, na linguagem C, os ndices variam de zero ao valor

79

declarado como dimenso da matriz, menos um; mas C no verifica isso para o usurio. Manter os ndices na faixa permitida tarefa do programador. Exemplo do uso de uma matriz: #include <stdio.h> int main () { int mtrx [20][10]; int i,j,count; count=1; for (i=0;i<20;i++) for (j=0;j<10;j++) { mtrx[i][j]=count; count++; printf("\nLinha:%d Col:%d INT:%d",i,j,mtrx[i][j]); } return(0); } No exemplo acima, a matriz preenchida, seqencialmente por linhas, com os nmeros de 1 a 200. recomendvel entender o funcionamento do programa acima antes de prosseguir.

Matrizes de strings
Matrizes de strings so matrizes bidimensionais. Imagine uma string. Ela um vetor. Se declarado um vetor de strings isso representar uma lista de vetores. Essa estrutura ser uma matriz bidimensional de elementos do tipo char. A forma geral de uma matriz de strings pode ser vista como sendo: char nome_da_varivel [num_de_strings][compr_das_strings]; Como acessar uma string individual? Fcil. s usar apenas o primeiro ndice. Ento, para acessar uma determinada string faa: nome_da_varivel [ndice]

80

Um exemplo de programa que l 5 strings e as exibe na tela: #include <stdio.h> int main () { char strings [5][100]; int count; for (count=0;count<5;count++) { printf ("\n\nDigite uma string: "); gets (strings[count]); } printf ("\n\n\nAs strings que voce digitou foram:\n\n"); for (count=0;count<5;count++) printf ("%s\n",strings[count]); return(0); }

MATRIZES MULTIDIMENSIONAIS
O uso de matrizes multidimensionais na linguagem C simples. Sua forma geral : tipo_da_varivel nome_da_varivel [tam1][tam2] ... [tamN]; Uma matriz N-dimensional funciona basicamente como outros tipos de matrizes. Basta lembrar que o ndice que varia mais rapidamente o ndice mais direita.

Inicializao
Assim como qualquer varivel ou vetor, tambm possvel a inicializao de matrizes. A forma geral de inicializao de uma matriz dada por: tipo_da_varivel nome_da_varivel [tam1][tam2] ... [tamN] = {lista_de_valores}; A lista de valores composta por valores (do mesmo tipo da varivel) separados por vrgula. Os valores devem ser fornecidos na ordem em que sero armazenados nos elementos da matriz. Abaixo alguns exemplos de inicializaes de matrizes: float vect [6] = { 1.3, 4.5, 2.7, 4.1, 0.0, 100.1 }; int matrx [3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; char str [10] = { J, o, a, o, \0 }; char str [10] = "Joao"; char str_vect [3][10] = { "Joao", "Maria", "Jose" }; O primeiro exemplo mostra inicializao de vetores. O segundo exemplo mostra a inicializao de matrizes multidimensionais, matrx inicializada com 1, 2, 3 e 4 em sua

81

primeira linha, 5, 6, 7 e 8 na segunda linha e 9, 10, 11 e 12 na ltima linha. No terceiro exemplo vemos como inicializar uma string e, no quarto exemplo, um modo mais compacto de inicializar uma string. O quinto exemplo combina as duas tcnicas para inicializar um vetor de strings. Repare que devemos incluir ; (ponto e vrgula) no final da inicializao.

Inicializao sem Especificao de Tamanho


Em algumas situaes possvel inicializar matrizes cujo tamanho no conhecido previamente. O compilador C, neste caso, verifica o tamanho declarado e considera como sendo esse o tamanho da matriz. Isto ocorre na hora da compilao e no poder mais ser mudado durante o programa, sendo muito til, por exemplo, quando da inicializao de uma string e no se quer contar quantos caracteres sero necessrios. Alguns exemplos: char mess [] = "Linguagem C: flexibilidade e poder."; int matrx [][2] = { 1,2,2,4,3,6,4,8,5,10 }; No primeiro exemplo, a string mess tem tamanho 36. Reparar que o artifcio para realizar a inicializao sem especificao de tamanho no especificar o tamanho! No segundo exemplo o valor no especificado 5.

AUTO AVALIAO
O que exibido peloo programa a seguir? Tente entend-lo e responder. A seguir, executeo e comprove o resultado. # include <stdio.h> int main() { int t, i, M[3][4]; for (t=0; t<3; ++t) for (i=0; i<4; ++i) M[t][i] = (t*4)+i+1; for (t=0; t<3; ++t) { for (i=0; i<4; ++i) printf ("%3d ", M[t][i]); printf ("\n"); } return(0); } Escreva um programa em C que calcule e mostre a mdia dos 8 elementos vizinhos de cada elemento da matriz A de NxN elementos definida por aij = N * i + j. Faa N = 5.

82

Obs.: Nem todo elemento de matriz tem 8 vizinhos. Alguns apresentam 3 vizinhos e outros 5 vizinhos (os elementos na borda da matriz).

DIRETIVAS DE COMPILAO
O pr-processador C um programa que examina o programa fonte escrito em C e executa certas modificaes nele, tomando como referncia as Diretivas de Compilao. As diretivas de compilao so comandos que no so compilados, sendo dirigidos ao prprocessador, que executado pelo compilador antes da execuo do processo de compilao propriamente dito. Portanto, o pr-processador modifica o programa fonte, entregando para o compilador um programa modificado. Todas as diretivas de compilao so iniciadas pelo caractere #. As diretivas podem ser declaradas em qualquer parte do programa. J vimos, e usamos muito, a diretiva #include. Sabemos que ela no gera cdigo, mas diz ao compilador que ele deve incluir um arquivo externo no momento da compilao. As diretivas estudadas, de maneira breve, so definidas pelo padro ANSI e so elas: #if_ #else #include #ifdef_ #elif #define #ifndef_ #endif #undef

83

A DIRETIVA INCLUDE
Essa diretiva foi usada em diversos exemplos mostrados anteriormente. Ela informa ao compilador que deve ser includo, durante o processo da compilao, um arquivo especificado. Sua forma geral : #include "nome_do_arquivo" ou #include <nome_do_arquivo> A diferena entre usar ou < > somente a ordem de procura nos diretrios pelo arquivo especificado. Se for necessrios informar o nome do arquivo com o caminho de destino completo, ou se o arquivo estiver no diretrio de trabalho, use . Se o arquivo estiver nos caminhos de procura pr-estabelecidos pelo compilador, isto , se ele for um arquivo do prprio sistema (como o caso de arquivos como stdio.h ou string.h) use < >. No h ponto e vrgula aps a diretiva de compilao. Esta uma caracterstica importante de todas as diretivas de compilao e no somente da diretiva #include. Essa diretiva inclue o que conhecido como arquivos cabealho.

Arquivoscabealhos so aqueles que declarados no incio de programas escritos na linguagem C. Os exemplos apresentados declaram diversos deses arquivos, dependendo da necessidade. Invariavelmente esses arquivos terminam em .h. A extenso .h vem de header (cabealho em ingls).

AS DIRETIVAS DEFINE E UNDEF Define


A diretiva define tem a seguinte forma geral: #define nome_da_macro sequncia_de_caracteres Quando essa diretiva declarada, o compilador instrudo para que, toda vez que for encontrado nome_da_macro no programa a ser compilado, substitu-lo pela sequncia_de_caracteres fornecida. Isto muito til para deixar o programa mais genrico.

84

Um exemplo: #include <stdio.h> #define PI 3.1416 #define VERSAO "2.02" int main () { printf ("Programa versao %s",VERSAO); printf ("O numero pi vale: %f",PI); return 0; } Se for necessrio alterar o valor de PI, ou de VERSAO, no programa acima, basta alter-los no incio do programa. Isto torna o programa mais flexvel, ao inv de procurar todas as referncias a esses valores no programa. H quem diga que, em um programa, nunca se deve usar constantes como 10, 3.1416, etc., pois estes so nmeros que ningum sabe o que significam (muitas pessoas os chamam de "nmeros mgicos"). Ao invs disso, deve-se declar-los usando uma diretiva #define. convencionado em programao (que deve ser seguida, pois torna o programa mais legvel) na linguagem C que as macros declaradas pela diretiva #define devem ser todas em maisculas. Outro uso da diretiva #define o de simplesmente definir uma macro. Neste caso usa-se a seguinte forma geral: #define nome_da_macro Nesse caso o objetivo no usar a macro no programa (pois ela seria substituda por nada), mas, sim, definir uma macro para ser usada como uma espcie de sinalizao (flag). Isso quer dizer que estamos definindo um valor como sendo "verdadeiro" para depois ser verificado. Tambm possvel definir macros com argumentos, como no exemplo a seguir: #define max(A,B) ((A>B) ? (A):(B)) #define min(A,B) ((A<B) ? (A):(B)) ... x = max(i,j); y = min(t,r); Embora se assemelhe a uma chamada de funo, o uso de max (ou min) simplesmente substitui, em tempo de compilao, o cdigo especificado. Cada ocorrncia de um parmetro formal (A ou B, na definio) ser substitudo pelo argumento real correspondente. Assim, a linha de cdigo:

85

x = max(i,j); ser substituda pela linha:_ x = ((i)>(j) ? (i):(j)); A linha de cdigo: x = max(p+q,r+s); ser substituda pela linha: x = ((p+q)>(r+s) ? (p+q):(r+s)); Isso pode ser muito til. As macros max e min no possuem especificao de tipo. Logo, elas funcionam corretamente para qualquer tipo de dado, desde que os argumentos passados forem coerentes. Mas isso pode representar tambm algumas armadilhas. Veja que a linha x = max(p++,r++); ser substituda pelo cdigo x = ((p++)>(r++) ? (p++):(r++)); e em conseqncia, incrementar o maior valor duas vezes. Outra armadilha em macros est relacionada com o uso de parnteses. Seja a macro: #define SQR(X) X*X Imagine a utilizao da macro na expresso abaixo: y = SQR(A+B); Ao fazer isto, a substituio que ser efetuada no estar correta. A expresso gerada ser: y = A+B*A+B; que obviamente diferente de (A+B)*(A+B) ! A soluo para este problema incluir parnteses na definio da macro: #define SQR(X)(X)*(X) Quando utilizada, a diretiva #define nunca se deve deixar espaos em branco no identificador. Por exemplo, a macro: #define PRINT (i) printf(" %d \n", i) no funcionar corretamente porque existe um espao em branco entre PRINT e (i). Ao se remover o espao, a macro funcionar corretamente e poder ser utilizada para imprimir o nmero inteiro i, saltando em seguida para a prxima linha.

86

Undef
A diretiva #undef tem a seguinte forma geral: #undef nome_da_macro Ela faz com que uma macro definida seja apagada da tabela interna que guarda as macros.O compilador passa a partir deste ponto a no reconhercer essa macro.

Ifdef e Endif
So diretivas de compilao condicional. Elas so muito parecidas com os comandos de execuo condicional da linguagem C. A forma geral dessa diretivas : #ifdef nome_da_macro sequncia_de_declaraes #endif A seqncia de declaraes ser compilada apenas se o nome da macro estiver definido. A diretiva de compilao #endif util para definir o fim de uma seqncia de declaraes para toda diretiva de compilao condicional. As linhas #define PORT_0 0x378 ... /* Linhas de codigo qualquer... */ ... #ifdef PORT_0 #define PORTA PORT_0 #include "../sys/port.h" #endif demonstram como estas diretivas podem ser utilizadas. Caso PORT_0

tenha sido

previamente definido, a macro PORTA definida e o header file port.h includo.

Ifndef_
A diretiva #ifndef inversa diretiva #ifdef. Sua forma geral : #ifndef nome_da_macro sequncia_de_declaraes #endif A seqncia de declaraes ser compilada se o nome da macro no tiver sido definido.

87

If
A diretiva #if tem a seguinte forma geral: #if expresso_constante sequncia_de_declaraes #endif A seqncia de declaraes ser compilada se a expresso-constante for verdadeira. muito importante ressaltar que a expresso fornecida deve ser constante, ou seja, no deve ter qualquer varivel.

Else
A diretiva #else tem a seguinte forma geral: #if expresso_constante sequncia_de_declaraes #else sequncia_de_declaraes #endif Funciona como seu correspondente, o comando else. Imagine um sistema, e que se deseja que todo o cdigo possa ser compilado em duas diferentes plataformas (i.e. Unix e Dos). Para obter isto, "encapsula-se" toda a parte de entrada e sada em arquivos separados, que sero carregados de acordo com o arquivo cabealho carregado. Isto pode ser facilmente implementado da seguinte forma: #define SISTEMA DOS ... /*linhas de codigo..*/ ... #if SISTEMA == DOS #define CABECALHO "dos_io.h" #else #define CABECALHO "unix_io.h" #endif #include CABECALHO

88

Elif
A diretiva #elif usada para implementar a estrutura if-esle-if. Sua forma geral : #if expresso_constante_1 sequncia_de_declaraes_1 #elif expresso_constante_2 sequncia_de_declaraes_2 #elif expresso_constante_3 sequncia_de_declaraes_3 . . . #elif expresso_constante_n sequncia_de_declaraes_n #endif O funcionamento desta estrutura idntico ao funcionamento apresentado acima e permite encadeamento de desvios condicionais.

89

ENTRADAS E SADAS PADRONIZADAS

INTRODUO
O sistema de entrada e sada da linguagem C est estruturado na forma de uma biblioteca de funes. J vimos algumas destas funes que sero revistas. Novas funes tambm sero apresentadas. No objetivo explicar, em detalhes, todas as possveis funes da biblioteca de entrada e sada da linguagem C. A sintaxe completa destas funes pode ser encontrada no manual do compilador e em literatura complementar disponvel na biblioteca da Instituio. Alguns ambientes (IDE) de programao trazem uma descrio das funes na ajuda do compilador, que pode ser acessada on line. Um ponto a ressaltar que apresentada uma funo, primeiramente, ser apresentado o seu prottipo. presumvel a capacidade de interpretar as informaes que um prottipo nos passa. Se isso no se materializar, recomenda-se um estudo mais aprofundado sobre funes. Outro aspecto a considerar, quando se discute a entrada e sada na linguagem C o conceito de fluxo. Seja qual for o dispositivo de entrada e sada (discos, terminais, teclados, acionadores de fitas) que estiver em uso, o C vai enxerg-lo como um fluxo, que nada mais que um dispositivo lgico de entrada ou sada. Todos os fluxos so similares em seu funcionamento e independentes do dispositivo ao qual esto associados. Assim, as mesmas funes que descrevem o acesso a discos podem ser utilizadas para acesso a um terminal de vdeo. Todas as operaes de entrada e sada so realizadas por meio de fluxos. Na linguagem C, um arquivo entendido como um conceito que pode ser aplicado a arquivos em disco, terminais, modens, etc ... Um fluxo associado a um arquivo atravs de uma operao de abertura. Uma vez aberto, informaes podem ser trocadas entre o arquivo e o programa. Um arquivo dissociado de um fluxo atravs de uma operao de fechamento de arquivo.

90

LEITURA E ESCRITA DE CARACTERES


Uma das funes mais bsicas de um sistema a entrada e a sada de informaes em dispositivos. Esses dispositivos podem ser representados por um monitor de vdeo, uma impressora ou um arquivo em disco. Vejamos os principais comandos que C oferece para tal.

Getche e getch
As funes getch() e getche() no so definidas pelo padro ANSI. Porm, elas geralmente so includas em compiladores baseados no DOS, e se encontram no arquivo de cabealho conio.h. Vale a pena repetir: so funes comuns apenas para compiladores baseados em DOS e, se voc estiver utilizando um sistema operacional UNIX normalmente no ter estas funes disponveis. Prottipos: int getch (void); int getche (void); getch() aguarda que o usurio digite uma tecla e retorna este caractere. possvel estranhar o fato de que essa funo retorne um inteiro, mas no h problema pois este inteiro tal que, quando igualado a um contedo do tipo char, a converso feita corretamente. A funo getche() funciona exatamente como getch(). A diferena que getche() gera um "echo" na tela antes de retornar a tecla. Se a tecla pressionada for um caractere especial essas funes retornam zero. Nesse caso, deve-se usar as funes novamente para capturar o cdigo da tecla extendida pressionada. A funo equivalente a getche() no padro ANSI getchar(). O problema com essa funo que o caractere lido colocado em uma rea intermediria at que o usurio tecle <ENTER>, o que pode ser extremamente inconveniente em ambientes interativos.

91

Putchar
Prottipo: int putchar (int c); putchar() coloca o caractere c na tela. Este caractere colocado na posio atual do cursor. Mais uma vez os tipos so inteiros, mas voc no precisa se preocupar com este fato. O arquivo de cabealho stdio.h.

LEITURA E ESCRITA DE STRING Gets


Prottipo: char *gets (char *s); Entra uma string digitada pelo usurio, que ser armazenada na string s. O ponteiro que a funo retorna o prprio s. gets() no uma funo segura simplesmente porque pode ocorrer um transbordamento da quantidade de caracteres (posies) especificados, na declarao da string, como no exemplo abaixo: #include <stdio.h> int main() { char buffer[10]; printf("Entre com o seu nome"); gets(buffer); printf("O nome : %s", buffer); return 0; } Se o usurio digitar como entrada: Joao Carlos da Silva Neto ou seja, digitar um total de 25 caracteres (incluindo o delimitador '\0' ) sero utilizadas 26 posies para armazenar a cadeia. Como a string buffer[] s tem 10 caracteres, os 16 caracteres adicionais sero colocados na rea de memria subseqente ocupada por ela, escrevendo uma regio de memria que no est reservada cadeia. Este efeito conhecido como "estouro de buffer" e pode causar problemas imprevisveis. Uma forma de se evitar este problema usar a funo fgets(), conforme veremos posteriormente.

92

Puts
Prottipo: int puts (char *s); puts() exibe a cadeia s na tela.

FORMATAO DE ENTRADA E DE SADA


As funes que resumem todas as funes de entrada e sada formatada em C so as funes printf() e scanf(). O domnio destas funes fundamental ao programador.

Printf
Prottipo: int printf (char *str,...); As reticncias no prottipo da funo indicam que esta funo tem um nmero de argumentos varivel. Este nmero est diretamente relacionado com a cadeia de controle str, que deve ser fornecida como primeiro argumento. A string de controle tem dois componentes. O primeiro um conjunto de caracteres a serem exibidos na tela. O segundo componente so os comandos de formato. Como j vimos, os ltimos determinam uma exibio de variveis na sada. Os comandos de formato so precedidos de %. A cada comando de formato deve corresponder um argumento na funo printf(). Se isto no ocorrer podem ocorrer erros imprevisveis.

93

Abaixo apresentada a tabela de cdigos de formato:

Tabela 13 - Cdigos de formatao

Alguns exemplos: printf ("Um %%%c %s",'c',"char"); exibe %c char printf ("%X %f %e",107,49.67,49.67); exibe 6B 49.67 4.967e1 printf ("%d %o",10,10); exibe 10 12 possvel tambm indicar o tamanho do campo, justificao (alinhamento esquerda, direita ou centralizado, e o nmero de casas decimais. Para isto usam-se cdigos colocados entre o cdigo % e a letra que indica o tipo de formato. Um valor inteiro indica o tamanho mnimo, em caracteres, que deve ser reservado para a sada. A especificao do cdigo de formatao %5d indica que a sada dever ser formatada com cinco caracteres de comprimento, no mnimo. Se o valor a ser exibido tiver comprimento maior que aquele especificado, ento a sada ser formatada com o comprimento necessrio para exibio. Se o comprimento para a sada for menor que cinco, ento o contedo exibido ter cinco caracteres de comprimento e os caracteres restantes sero preenchidos com espaos em branco esquerda, visto tratar-se de formato de exibio de um valor inteiro. Caso se opte pelo preenchimento com zeros, colocar um zero

94

antes do valor de comprimento especificado. Assim, %05d especifica cinco casas para o contedo a ser exibido e, se este tiver menos do que cinco caracteres, ento o preenchimento ser feito com zeros esquerda. O alinhamento padro para contedo numrico direita. Para alterar esse padro e alinhar um contedo numrico esquerda usa-se um sinal - antes do nmero de casas. Ento %-5d formatar o contedo a ser exibido com um mnimo de cinco casas, alinhado esquerda. Alm disso, e no caso de contedo armazenado em ponto flutuante, possvel indicar a quantidade de caracteres decimais a ser exibida. Por exemplo, a notao %10.4f formata um contedo armazenado em ponto flutuante de comprimento total dez, sendo que quatro desses dez devem ser formatados como casas decimais. Entretanto, essa mesma notao, quando aplicada a contedos de tipo inteiro e string indica a quantidade mnima e mxima de casas a serem exibidas. Ento, %5.8d um contedo do tipo inteirointeiro com comprimento mnimo de cinco e mximo de oito caracteres a ser exibido. Alguns exemplos: printf ("%-5.2f",456.671); exibe |456.67| printf ("%5.2f",2.671); exibe | 2.67| printf ("%-10s","Ola"); exibe |Ola | Nos exemplos o "pipe" ( | ) indica o incio e o fim do campo, mas no so exibidos na tela.

Scanf
Prottipo: int scanf (char *str,...); A string de controle str determina, assim como na funo printf(), quantos parmetros a funo vai necessitar. Devemos sempre nos lembrar que a funo scanf() receber ponteiros como parmetros. Isso significa que as variveis que no sejam por natureza ponteiros devem ser passadas precedidas do operador &. Os especificadores de formato de entrada so muito parecidos com os da funo printf(). Os caracteres de converso d, i, u e x podem ser precedidos por h para indicar que um apontador para short ao invs de int aparece na lista de argumento, ou pela letra l (letra ele) para indicar que que um apontador para long aparece na lista de argumento. Semelhantemente, os caracteres de

95

converso e, f, e g podem ser precedidos por l para indicar que um apontador para Double ao invs de float est na lista de argumento. Exemplos:

Tabela 14 - Especificadores de formato da funo scanf()

Sprintf e sscanf
Sprintf() e sscanf() so semelhantes a printf() e scanf(). Porm, ao invs de escreverem na sada padro ou lerem da entrada padro, escrevem ou lem em uma string. Os prottipos so: int sprintf (char *destino, char *controle, ...); int sscanf (char *origem, char *controle, ...); Essas funes so muito utilizadas para fazer a converso entre dados na forma numrica e sua representao na forma de strings. No programa abaixo, por exemplo, a varivel i exibida em string1. Alm da representao de i como uma string, string1 tambm conter "Valor de i=" . #include <stdio.h> int main() { int i; char string1[20]; printf( " Entre um valor inteiro: "); scanf("%d", &i); sprintf(string1,"Valor de i = %d", i);

96

puts(string1); return 0; } No programa a seguir, utilizou-se a funo sscanf() para converter a informao armazenada em string1 em seu valor numrico: #include <stdio.h> int main() { int i, j, k; char string1[]= "10 20 30"; sscanf(string1, "%d %d %d", &i, &j, &k); printf("Valores lidos: %d, %d, %d", i, j, k); return 0;
}

ABRIR E FECHAR ARQUIVOS


O sistema de entrada e sada em C padro ANSI composto por uma srie de funes, cujos prottipos esto reunidos no arquivo de cabealho stdio.h. Todas essas funes aplicam o conceito de "ponteiro de arquivo". Este no um tipo propriamente dito, mas uma definio usando o comando typedef. Essa definio tambm est no arquivo stdio.h. Podemos declarar um ponteiro de arquivo da seguinte maneira: FILE *p; p ser ento um ponteiro para um arquivo. O uso desse tipo de ponteiro permite manipular arquivos em C.

FOPEN
a funo de abertura de arquivos. Seu prottipo : FILE *fopen (char *nome_do_arquivo,char *modo); O nome_do_arquivo determina qual arquivo dever ser aberto. Esse nome deve ser vlido no sistema operacional em que o programa for compilado. O modo de abertura diz funo fopen() que tipo de uso ser feito do arquivo.

97

A tabela abaixo mostra os valores de modo vlidos:

Tabela 14 - Modos de abertura de arquivos vlidos para a funo fopen()

Dessa maneira, possvel, para abrir um arquivo binrio para escrita, escrever: FILE *fp; /* Declarao da estrutura fp=fopen ("exemplo.bin","wb"); /* o arquivo se chama exemplo.bin e est localizado no diretrio corrente */ if (!fp) printf ("Erro na abertura do arquivo."); A expresso !fp verifica se o arquivo foi aberto com sucesso, porque no caso de um erro a funo fopen() retorna um ponteiro nullo (NULL). Aberto um arquivo, possvel ler ou escrever nesse arquivo utilizando as funes que apresentadas nas prximas pginas. Toda vez que se manipula arquivos, h uma espcie de posio atual no arquivo. Essa a posio de onde ser lido ou escrito o prximo caractere. Normalmente, num

98

acesso seqencial a um arquivo, no necessrio mexer nesta posio pois quando lemos um caractere a posio no arquivo automaticamente atualizada. Num acesso randmico (aleatrio) necessrio controle dessa posio.

Exit
O prottipo dessa funo : void exit (int codigo_de_retorno); Para utiliz-la deve-se declarar o arquivo de cabealho stdlib.h. Essa funo tem por objetivo cancelar (abortar) a execuo do programa. Pode ser chamada de qualquer ponto no programa e faz com que o programa termine e retorna, para o sistema operacional, um cdigo_de_retorno. A conveno mais usada que um programa retorne zero no caso de um trmino normal e retorne um nmero no nulo no caso de ter ocorrido um problema. A funo exit() se torna importante em casos como alocao dinmica e abertura de arquivos, pois nesses casos, se o programa no conseguir a memria necessria ou no puder abrir o arquivo, a melhor sada pode ser terminar a execuo do programa. O exemplo anterior pode ser reescrito, usando-se a funo exit() para garantir que o programa no deixar de abrir o arquivo: #include <stdio.h> #include <stdlib.h> /* Para a funo exit() */ main (void) { FILE *fp; ... fp=fopen ("exemplo.bin","wb"); if (!fp) { printf ("Erro na abertura do arquivo. programa."); exit (1); } ... return 0; }

Fim

de

99

Fclose
Quando terminado o uso de um arquivo que previamente aberto, deve-se fech-lo. Isso feito utilizando a funo fclose(): int fclose (FILE *fp); O ponteiro fp passado funo fclose() determina o arquivo a ser fechado. A funo retorna zero no caso de sucesso. Fechar um arquivo faz com que qualquer caractere que tenha permanecido no "buffer" associado ao fluxo de sada seja gravado. Mas, o que este "buffer"? Quando caracteres so enviados para escrita em um arquivo, estes caracteres so armazenados temporariamente em uma rea de memria (o "buffer") em vez de serem escritos imediatamente. Quando o "buffer" estiver cheio, seu contedo escrito de uma vez. A razo para se fazer isto tem a ver com a eficincia nas leituras e gravaes de arquivos. Se, para cada caractere a ser gravado, a cabea de gravao for posicionada em um ponto especfico do dispositivo, apenas para escrever aquele caractere, as operaes de escrita se tornariam extremamente lentas. Assim, essas gravaes s sero efetuadas quando houver um volume razovel de informaes a serem escritas ou quando o arquivo for fechado. A funo exit() fecha todos os arquivos que um programa tiver aberto.

LEITURA E ESCRITA DE CARACTERES EM ARQUIVOS Putc


A funo putc a primeira das funes de escrita de arquivo que veremos. Seu prottipo : int putc (int ch,FILE *fp); Escreve um caractere no arquivo.

100

O programa a seguir l uma string do teclado e escreve-a, caractere por caractere em um arquivo em disco (o arquivo.txt, que ser aberto no diretrio corrente). #include <stdio.h> #include <stdlib.h> int main() { FILE *fp; char string[100]; int i; fp = fopen("arquivo.txt","w"); /* Arquivo ASCII, para escrita */ if(!fp) { printf( "Erro na abertura do arquivo"); exit(0); } printf("Entre com a string a ser gravada no arquivo:"); gets(string); for(i=0; string[i]; i++) putc(string[i], fp); /* Grava a string, caractere a caractere */ fclose(fp); return 0; } Depois de executar este programa, verifique o contedo do arquivo arquivo.txt (pode usar qualquer editor de textos). Voc ver que a string digitada est armazenada nele.

Getc
Retorna um caractere lido de um arquivo. Seu prottipo : int getc (FILE *fp);

Feof
EOF ("End of file") indica o fim de um arquivo. s vezes, necessrio verificar se um arquivo chegou ao fim. Para isto podemos usar a funo feof(). Ela retorna no-zero se o arquivo chegou ao fim, caso contrrio retorna zero. Seu prottipo : int feof (FILE *fp); Outra forma de se verificar se o final do arquivo foi atingido comparar o caractere lido por getc com EOF. O programa a seguir abre um arquivo j existente e o l, caractere por caractere, at que o final do arquivo seja atingido. Os caracteres lidos so apresentados na tela:

101

#include <stdio.h> #include <stdlib.h> int main() { FILE *fp; char c; fp = fopen("arquivo.txt","r"); /* Arquivo ASCII, para if(!fp) { printf( "Erro na abertura do arquivo"); exit(0); } /* Enquanto no chegar ao final do arquivo */ while((c = getc(fp) ) != EOF) printf("%c", c); /* imprime o caracter lido */ fclose(fp); return 0; }

leitura */

A seguir apresentado um programa no qual vrias operaes com arquivos so realizadas, usando as funes apresentadas acima. Primeiro o arquivo aberto para a escrita, e escreve-se algo nele. Em seguida, o arquivo fechado e novamente aberto para a leitura.

102

Verifique o exemplo. #include <stdio.h> #include <stdlib.h> #include <string.h> void main() { FILE *p; char c, str[30], frase[80] = "Este e um arquivo chamado: "; int i; /* Le um nome para o arquivo a ser aberto: */ printf("\n\n Entre com um nome para o arquivo:\n"); gets(str); if (!(p = fopen(str,"w"))) /* Caso ocorra algum erro na abertura do arquivo.*/ { /* o programa aborta automaticamente */ printf("Erro! Impossivel abrir o arquivo!\n"); exit(1); } /* Se nao houve erro, imprime no arquivo e o fecha */ strcat(frase, str); for (i=0; frase[i]; i++) putc(frase[i],p); fclose(p); /* Abre novamente para leitura */ p = fopen(str,"r"); c = getc(p); /* Le o primeiro caracter */ while (!feof(p)) /* Enquanto no se chegar no final do arquivo */ { printf("%c",c); /* Imprime o caracter na tela */ c = getc(p); /* Le um novo caracter no arquivo */ } fclose(p); /* Fecha o arquivo */ }

103

OUTROS COMANDOS DE ACESSO A ARQUIVOS Arquivos Pr-Definidos


Quando se comea a execuo de um programa, o sistema automaticamente abre alguns arquivos pr-definidos: stdin: dispositivo de entrada padro (geralmente o teclado) stdout: dispositivo de sada padro (geralmente o vdeo) stderr: dispositivo de sada de erro padro (geralmente o vdeo) stdaux: dispositivo de sada auxiliar (em muitos sistemas, associado porta serial) stdprn: dispositivo de impresso padro (em muitos sistemas, associado porta paralela)

Cada uma destas constantes pode ser utilizada como um ponteiro para FILE, para acessar os perifricos associados a eles. Desta maneira, pode-se, por exemplo, usar: ch =getc(stdin); para efetuar a leitura de um caracter a partir do teclado, ou: putc(ch, stdout); para exibi-lo na tela.

Fgets
Para a leitura de uma string num arquivo podemos usar fgets() cujo prottipo : char *fgets (char *str, int tamanho,FILE *fp); A funo recebe 3 argumentos: a string a ser lida, o limite mximo de caracteres a serem lidos e o ponteiro para FILE, que est associado ao arquivo de onde a string ser lida. A funo l a string at que um caracter de nova linha seja lido ou tamanho 1caracteres tenham sido lidos. Se o caractere de nova linha ('\n') for lido, ele far parte da string, o que no acontece com a funo (). A string resultante sempre terminar com '\0' (por isto somente tamanho - 1 caracteres, no mximo, sero lidos). A funo () semelhante funo gets(), porm, alm de fazer a leitura a partir de um arquivo de dados e incluir o caractere de nova linha na string, ela ainda especifica o tamanho mximo da string de entrada. Como visto, a funo gets() no implementa esse controle, o que pode acarretar erros de "estouro de buffer". Portanto, levando-se em conta

104

que o ponteiro fp pode ser substitudo por stdin, uma alternativa ao uso de gets() usar a seguinte construo: fgets (str, tamanho, stdin); onde str ' a string que a ser lida e tamanho deve ser igual ao tamanho alocado para a string subtrado de 1, por causa do delimitador '\0'.

Fputs
Prottipo: char *fputs (char *str,FILE *fp); Escreve uma string em um arquivo.

Ferror e perror
Prottipo de ferror: int ferror (FILE *fp); A funo retorna zero, se nenhum erro ocorreu e um nmero diferente de zero se algum erro ocorreu durante o acesso ao arquivo. ferror() muito til quando necessrio verificar se cada acesso a um arquivo foi em sucedido, de modo a garantir a integridade de dados. Na maioria dos casos, se um arquivo pode ser aberto, ele pode ser lido ou gravado. Porm, existem situaes em que isso no ocorre. Por exemplo, pode acabar o espao em disco enquanto gravamos, ou o disco pode apresentar problemas que impedem a leitura. A funo perror() (print error) pode ser usada de maneira combinada com ferror(), cujo argumento uma string que normalmente indica em que parte do programa o problema ocorreu.

105

No exemplo a seguir, so usadas as funes ferror(), perror() e fputs() #include <stdio.h> #include <stdlib.h> int main() { FILE *pf; char string[100]; if((pf = fopen("arquivo.txt","w")) ==NULL) { printf("\nNao consigo abrir o arquivo ! "); exit(1); } do { printf("\nDigite uma nova string. Para terminar, digite <enter>: "); gets(string); fputs(string, pf); putc(\n, pf); if(ferror(pf)) { perror("Erro na gravacao"); fclose(pf); exit(1); } } while (strlen(string) > 0); fclose(pf); }

Fread
Podemos escrever e ler blocos de dados. Para tanto, usam-se as funes fread() e fwrite(). O prottipo de IUHDG__ : unsigned fread (void *buffer, int numero_de_bytes, int count, FILE *fp); buffer a regio de memria na qual sero armazenados os dados lidos. numero_de_bytes o tamanho da unidade a ser lida e count indica quantas unidades devem ser lidas. Isso significa que o nmero total de bytes lidos : numero_de_bytes*count A funo retorna o nmero de unidades efetivamente lidas. Esse nmero pode ser menor que count quando o fim do arquivo for encontrado ou ocorrer algum erro.

106

Quando o arquivo for aberto para dados binrios, fread() pode ler qualquer tipo de dados.

Fwrite
A funo fwrite() tem funcionamento semelhante a fread(), porm para escrita em arquivo. Seu prottipo : unsigned fwrite(void *buffer,int numero_de_bytes,int count,FILE *fp); A funo retorna o nmero de itens escritos. Este valor ser igual a count a menos que ocorra algum erro. O exemplo abaixo ilustra o uso de fwrite() e fread() para gravar e posteriormente ler uma varivel do tipo float em um arquivo binrio.
#include <stdio.h> #include <stdlib.h> int main() { FILE *pf; float pi = 3.1415; float pilido; if((pf = fopen("arquivo.bin", "wb")) == NULL) /* Abre arquivo binrio para escrita */ { printf("Erro na abertura do arquivo"); exit(1); } if(fwrite(&pi, sizeof(float), 1,pf) != 1) /* Escreve a varivel pi */ printf("Erro na escrita do arquivo"); fclose(pf); /* Fecha o arquivo */ if((pf = fopen("arquivo.bin", "rb")) == NULL) /* Abre o arquivo novamente para leitura */ { printf("Erro na abertura do arquivo"); exit(1); } if(fread(&pilido, sizeof(float), 1,pf) != 1) /* Le em pilido o valor da varivel armazenada anteriormente */ printf("Erro na leitura do arquivo"); printf("\nO valor de PI, lido do arquivo e': %f", pilido); fclose(pf); return(0); }

Note-se o uso do operador sizeof, que retorna o tamanho em bytes da varivel ou do

107

tipo de dado.

Fseek
Para buscas e acessos randmicos em arquivos usa-se a funo fseek(). Move a posio corrente de leitura ou escrita no arquivo de um valor especificado, a partir de um ponto especificado. Seu prottipo : int fseek (FILE *fp,long numbytes,int origem); O parmetro origem determina a partir de onde os numbytes de movimentao sero contados. Os valores possveis so definidos por macros no arquivo de cabealho stdio.h e so: Nome SEEK_SET Valor Significado 0 Incio do arquivo Ponto corrente no arquivo Fim do arquivo

SEEK_CUR 1 SEEK_END 2

Estabelecido o ponto a partir do qual a contagem ser iniciada, numbytes determina o deslocamento a ser feito, em bytes, a partir da posio corrente.

Rewind
A funo rewind() desloca a posio corrente do arquivo para o seu incio. Seu prottipo : void rewind (FILE *fp);

Remove
Prottipo: int remove (char *nome_do_arquivo); Apaga um arquivo especificado.

108

O exemplo anterior pode ser reescrito usando-se, por exemplo, fgets() e fputs(), ou fwrite() e fread(). A seguir apresentamos uma segunda verso em que so usadas as funes fgets() e fputs(), e que acrescenta algumas inovaes. #include <stdio.h> #include <string.h> #include <stdlib.h> int main() { FILE *p; char str[30], frase[] = "Este e um arquivo chamado: ", resposta[80]; int i; /* Le um nome para o arquivo a ser aberto: */ printf("\n\n Entre com um nome para o arquivo:\n"); fgets(str,29,stdin); /* Usa fgets como se fosse gets */ for(i=0; str[i]; i++) if(str[i]==\n) str[i]=0; /* Elimina o \n da string lida */ if (!(p = fopen(str,"w"))) /* Caso ocorra algum erro na abertura do arquivo..*/ { /* o programa aborta automaticamente */ printf("Erro! Impossivel abrir o arquivo!\n"); exit(1); } /* Se nao houve erro, imprime no arquivo, e o fecha ...*/ fputs(frase, p); fputs(str,p); fclose(p); /* abre novamente e le */ p = fopen(str,"r"); fgets(resposta, 79, p); printf("\n\n%s\n", resposta); fclose(p); /* Fecha o arquivo */ remove(str); /* Apaga o arquivo */ return(0); }

FLUXOS PADRO
Os fluxos padro em arquivos permitem ao programador ler e escrever em arquivos da maneira padro, tal qual ler e escrever tela.

109

Fprintf
A funo fprintf() funciona como a funo printf(). A diferena que a escrita feita em um arquivo e no a tela do computador. Prottipo: int fprintf (FILE *fp,char *str,...); A diferena do prottipo de fprintf() a especificao do arquivo destino (sada) atravs do ponteiro de arquivo.

Fscanf
Analogamente ao visto anteriormente, a funo fscanf() l dados de um arquivo e no do teclado do computador. Prottipo: int fscanf (FILE *fp,char *str,...); A diferena do prottipo de fscanf() a especificao do arquivo origem (entrada) atravs do ponteiro de arquivo. Exemplo simplificado de escrever um programa usando fscanf() e fprintf():
#include <stdio.h> #include <stdlib.h> int main() { FILE *p; char str[80],c; /* Le um nome para o arquivo a ser aberto: */ printf("\n\n Entre com um nome para o arquivo:\n"); gets(str); if (!(p = fopen(str,"w"))) /* Caso ocorra algum erro na abertura do arquivo..*/ { /* o programa aborta automaticamente */ printf("Erro! Impossivel abrir o arquivo!\n"); exit(1); } /* Se nao houve erro, imprime no arquivo, fecha ...*/ fprintf(p,"Este e um arquivo chamado:\n%s\n", str); fclose(p); /* abre novamente para a leitura */ p = fopen(str,"r"); while (!feof(p)) { fscanf(p,"%c",&c); printf("%c",c); } fclose(p); return(0); }

110

AUTO AVALIAO
Escreva um programa que leia uma lista de nomes e idades de um arquivo texto. Prepare um arquivo para ser lido com nomes e idades. Apresente os dados lidos em forma de tabela na tela. Use as funes de sua preferncia, mas faa pelo menos duas verses do programa usando funes de leitura diferentes. Alguns compiladores indicam que a funo gets(string) uma funo "perigosa". Qual a razo disto? ( ) A funo no pode ler inteiros ( ) Se string for um vetor de caracteres com poucas posies, o usurio pode digitar mais caracteres do que a string pode armazenar, causando srios problemas ( ) O usurio pode digitar algo que no seja caracter e o sistema no perceber ( ) A funo no trabalha bem em conjunto com a funo scanf ( ) Nenhuma das opes anteriores O comando printf("%d, %u, %p", i, i, &i); exibir: ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ) O endereo de i e o valor de i ) O valor de i, de i sem sinal e um ponteiro para i ) O valor de i, o valor de i e um ponteiro para i ) O valor de i, o valor de i sem sinal e o endereo de i ) Nenhuma das opes anteriores ) scanf("%f", &f) ) scanf("%6f", &f) ) scanf("%lf", &f) ) scanf("%10.6f", &f) ) Nenhuma das opes anteriores ) O nome do arquivo a ser aberto ) Que arquivo ser aberto, para acrescentar dados ) Que arquivo ser aberto, para trabalhar em modo texto ) Qual o ponteiro para o arquivo ) Nenhuma das opes anteriores ) getch() ) getche() ) getc() ) fgets() ) fread()

Dada a varivel double f qual ser a forma de se efetuar a leitura dessa varivel

O que no permitido especificar com a funo fopen()?

Para ler um caractere por vez de um arquivo, qual das seguintes funes voc usaria?

111

Como todos os arquivos precisam ser lidos seqencialmente, no h como ler dados no meio do arquivo, sem ter feito a leitura desde o seu incio. ( ( ( ( ( ) Verdadeiro ) Falso ) Depende do tipo de arquivo ) Depende do sistema operacional ) Nenhuma das opes anteriores

Dado o seguinte trecho de programa FILE *fp; fp = fopen("arquivo.txt", "r+"); O que est sendo feito? ( ( ( ( ( ( ( ( ( ( ) O arquivo arquivo.txt est sendo aberto em modo texto e somente pode ser lido ) O arquivo arquivo.txt est sendo fechado para escrita ) O arquivo arquivo.txt est sendo aberto em modo binrio, e pode ser lido ou escrito ) O arquivo arquivo.txt est sendo aberto em modo binrio e somente pode ser lido ) O arquivo arquivo.txt est sendo aberto em modo texto e pode ser lido ou escrito ) A funo fgets() l uma string de um arquivo, mas tambm pode ser utilizada ) fputs() escreve uma string em um arquivo ) fputs(string, stdprn) imprimir a string na impressora padro ) fseek() pode ser utilizada para procurar um determinado caractere em um arquivo ) Nenhuma das opes anteriores

Qual a afirmativa errada?

Para gravar diversas variveis de tipos diferentes em um arquivo texto, a funo mais apropriada : ( ( ( ( ( ) fwrite() ) fprintf() ) fputs() ) fscanf() ) Nenhuma das opes anteriores

112

Dado o seguinte programa: #include <stdio.h> int main() { FILE *fp; fp = fopen("arquivo.txt", "r"); fprintf(fp, "%d", 10); fclose(fp); return(0); } Qual afirmativa verdadeira? ( ( ( ( ( ) Compila sem erros ) Ao final da execuo, arquivo.txt conter uma linha com o nmero 10 ) A linha #include <stdio.h> no necessria neste cdigo ) No se deve usar return 0 neste cdigo, pois a funo main no int ) Nenhuma das opes anteriores

113

CONSIDERAES FINAIS
O propsito deste material apresentar os recursos bsicos disponveis na linguagem C para a constuo de programas. O aprendizado de uma linguagem como o C, bem como de qualquer outra linguagem de programao, depende da aplicao exaustiva dos conceitos de desenvolvimento de algoritmos, bem como o uso extensivo dos recursos da linguagem, de maneira a consolidar esse aprendizado. Porm, no material, no esto contemplados todos os detalhes da linguagem C e, por esse motivo, recomendvel consulta bibliogrfica complementar, disponvel na biblioteca da IES, no intuito de aprimorar o conhecimento. Uma segunda parte, como complementao deste material, ser preparada e abordar aspectos avanados da linguagem C, tais como: funes, alocao dinmica, tipos de dados definidos pelo usurio (programador), dentre outros.

114

REFERNCIAS
Kernighan, B. & Ritchie, D. C A Linguagem de Programao Padro ANSI. Editora Campus, 1990. Schildt, H. C Completo e Total. Editora McGraw-Hill, 1990. Carpenter, V. Learn C/C++: http://www.cyberdiem.com/vin/learn.html (uma coleo de referncias e tutoriais sobre as linguagens C e C++ disponvel na Internet) Mizrahi, V. V. Treinamento em Linguagem C - Mdulos 1 e 2. Editora McGraw-Hill, 1990

Você também pode gostar