Módulo 1 ± Apresentação do Histórico e das Características Básicas da Linguagem C

1.1 ± História da Linguagem C
A Linguagem C é uma linguagem de programação que tem sua origem em outras duas linguagens anteriores: a Linguagem BCPL e a Linguagem B. A Linguagem BCPL foi desenvolvida por Martin Richards. Esta linguagem influenciou a linguagem inventada por Ken Thompson, chamado B. Logo em seguida, Dennis Ritchie desenvolveu a Linguagem C que foi implementada em um DEC PDP-11, usando o sistema operacional UNIX. A Linguagem C, dada a sua simplicidade e flexibilidade, tornou-se ao longo do tempo uma das linguagens de programação mais usadas, sendo utilizada na criação e desenvolvimento de softwares e sistemas operacionais que se tornaram famosos em todo mundo, como por exemplo o Sistema Operacional Windows. Entretanto, a Linguagem C atinge seus limites a partir do ponto em que os programas escritos na linguagem atingem um certo tamanho, entre 25.000 e 100.000 linhas, devido à problemas de gerenciamento do código. Para resolver este problema, em 1980, enquanto trabalhava nos laboratórios da Bell, em Murray Bill, New Jersey, Bjarne Stroustrup acrescentou várias extensões à linguagem C e chamou inicialmente esta nova linguagem de ³C com classes´. Em 1983, o nome adotado para esta nova linguagem foi C++. Muitas modificações foram feitas na Linguagem C++ para que ela pudesse suportar a programação orientada a objetos (POO).

1.2 ± Compiladores e Interpretadores
Compiladores e Interpretadores são simplesmente programas sofisticados que agem sobre o código-fonte do seu programa, ou seja, depois que o código-fonte de um determinado programa é escrito ele é submetido à um Compilador ou um Interpretador que fará com que seja possível sua execução em uma determinada máquina. O Compilador lê o programa inteiro e converte-o em um código executável. Uma vez o programa compilado, uma linha de código-fonte está significativamente distante do código executável. O compilador não é necessário para executar o programa, desde que ele já esteja compilado, ou seja, neste caso não será necessário que se tenha um programa instalado na máquina que reconheça o código em questão. O Interpretador lê o código-fonte do seu programa uma linha por vez e executa uma instrução específica contida naquela linha. O interpretador deverá estar presente toda vez que o programa estiver sendo executado, ou seja, é necessário que um interpretador específico da linguagem utilizada esteja instalado na máquina.

Existem dois termos freqüentes: tempo de compilação e tempo de execução. O termo tempo de compilação refere-se aos eventos que acontecem durante o processo de compilação e tempo de execução, aos eventos que ocorrem enquanto o programa está sendo executado. Infelizmente, constantemente esses termos estão relacionados a mensagens de erros, como em erros de tempo de compilação e erros de tempo de execução.

1.3 ± Características da Linguagem C
Portabilidade entre máquinas e sistemas operacionais, ou seja, um código escrito em linguagem C poderá ser executado em diferentes máquinas independentemente da sua configuração física (hardware) e do sistema operacional residente. A linguagem C é estruturada, com isso desencoraja a utilização dos goto's ± desvios incondicionais -, que geram os chamados códigos "macarronada". O "goto" é substituído por diversos tipos de laços e desvios, tais como: while, dowhile, for; if-then-else, switch, que permitem ao programador exercer um controle lógico mais eficaz sobre os códigos fontes de seus programas. A linguagem C/C++ possui sub-rotinas com variáveis locais, isto é, funções cujas variáveis são visíveis apenas dentro desta função e somente no momento em que estas funções estejam sendo usadas. Assim as variáveis com mesmo nome, que pertençam a funções distintas, são protegidas dos efeitos colaterais (proteção de variáveis), isto é, uma modificação em nível funcional não acarretará mudança na variável em nível global. Desta forma, mudanças de valores de variáveis no corpo do programa principal não afetam as variáveis de funções e vice-versa, a não ser que o programador assim o queira. Código compacto e rápido, quando comparado ao código de outras linguagem de complexidade análoga. A linguagem C é Case-Sensitive. É importante saber que as letras maiúsculas e minúsculas são tratadas como caracteres distintos. Por exemplo, em algumas linguagens, os nomes de variáveis count, Count e COUNT são três maneiras de se especificar a mesma variável. Entretanto na linguagem C, serão três variáveis diferentes. Então, quando você digitar programas em C seja cuidadoso na utilização correta das letras.

1.4 ± Aplicações Escritas em C
Atualmente, nos Estados Unidos, C é a linguagem mais utilizada pelos programadores, por permitir, dadas suas características, a escrita de programas típicos do Assembler, BASIC, COBOL e Clipper, sempre com maior eficiência e portabilidade, como podemos constatar pelos exemplos abaixo relacionados: Sistema Operacional: UNIX (Sistema computadores e em mainframes). Operacional executável em micro

Montadores: Clipper (O utilitário de banco de dados mais usado no Brasil). Planilhas: 1,2,3 e Excel (A planilha eletrônica com maior volume de vendas mundial).

Banco de Dados: dBase III, IV e Access (o gerenciador de base de dados mais utilizado no mundo). InfoStar: O Editor de Texto mais utilizado nos USA no Sistema Operacional UNIX. Utilitários: FormTool (Editor de formulário mais vendido no mundo). Aplicações Gráficas: Efeitos Especiais de filmes com Star Trek e Star War. Linguagens como o Power Builder e o Visual Basic, respectivamente as linguagens mais utilizadas nos EUA e no Brasil. No Brasil utilizada por empresas especializadas na elaboração de vinhetas e outros efeitos especiais.

1.5 ± A Linguagem C Comparada à Outras Linguagens
Deve-se entender Nível Alto como sendo a capacidade da linguagem em compreender instruções escritas em ³dialetos´ próximos do inglês (Ada e Pascal, por exemplo) e Nível Baixo para aquelas linguagens que se aproximam do Assembly, que é a linguagem própria da máquina, compostas por instruções binárias e outras incompreensíveis para o ser humano não treinado para este propósito. Infelizmente, quanto mais clara uma linguagem for para o humano (simplicidade >) mais obscura o será para a máquina (velocidade <). A Linguagem C é freqüentemente referenciada como uma linguagem de nível médio, posicionando-se entre o Assembly (baixo nível) e o Pascal (alto nível). Uma das razões da invenção da linguagem C foi dar ao programador uma linguagem de alto nível que poderia ser utilizada como uma subst ituta para a linguagem Assembly. Entretanto, ainda que a linguagem C possua estruturas de controle de alto nível, como é encontrado na Pascal, ela também permite que o programador manipule bits, bytes e endereços de uma maneira mais proximamente ligada à máquina, ao contrário da abstração apresentadas por outras linguagens de alto nível. Por esse motivo, a linguagem C tem sido ocasionalmente chamada de ³código Assembly de alto nível´. Por sua natureza dupla, a linguagem C permite que sejam criado programas rápidos e eficientes sem a necessidade de se recorrer a linguagem Assembly. A filosofia que existe por trás da linguagem C é que o programador sabe realmente o que está fazendo. Por esse motivo, a linguagem C quase nunca ³coloca-se no caminho´ do programador, deixando-o livre para usar (ou abusar) dela de qualquer forma que queira. O motivo para essa ³liberdade na programação´ é permitir ao compilador C criar códigos muito rápidos e eficientes, já que ele deixa a responsabilidade da verificação de erros para você. Observemos o esquema a seguir: Nível Baixo VELOCIDADE
Assembler

Nível Médio Macro Assembler Forth C CLAREZA Fortran Basic COBOL

Nível Alto Pascal Ada MODULA-2

Antes da linguagem C tornar-se um padrão de fato (meados de 1.988, nos USA), tínhamos, aproximadamente, o seguinte perfil de mercado: - Aplicações de Banco de Dados - Mainframe: COBOL e gerenciadores - Micros: dBase, Clipper e BASIC e gerenciadores como Btrieve. - Aplicações Gráficas: Pascal. - Aplicações Científicas: FORTRAN e Pascal. - Utilitários, Sistemas Operacionais e Compiladores: Assembler. A chegada de poderosos compiladores C (Borland, Microsoft e ZortechSymantec), revolucionou totalmente estes conceitos pois passou a permitir a construção de praticamente qualquer tipo de aplicação na Linguagem C, normalmente mais rápidas do que na linguagem original e portável entre os diversos ambientes (³roda´ em DOS, UNIX, etc. com poucas mudanças). Devemos entender no entanto, que apenas temos uma relativa portabilidade, pois a verdadeira portabilidade depende necessariamente da implementação do sistema operacional, necessariamente aberto, o que não existe fora do mundo Unix. Quadro de características de linguagens:
Linguagens / Características Ideais Executáveis Curtos Executáveis Rápidos Portáveis Manipulação de Bits Assembler BASIC Pascal Clipper COBOL C

ótimo ótimo péssimo ótimo

fraco bom bom razoável

péssimo razoável ótimo péssimo

fraco fraco ótimo fraco

ótimo bom bom ótimo

O quadro anterior, deixa claro o porquê da revolução causada pela Linguagem C, dados os inúmeros pontos fortes da linguagem e a inexistência de pontos fracos da mesma. Não deve-se concluir apressadamente que poderemos desenvolver tudo em C e abandonarmos todas as outras linguagens, pelos seguintes motivos: - Alta base de programas escritos em Assembler, COBOL, BASIC, Pascal. - Conhecimento amplo de linguagens concorrentes como COBOL, Clipper e BASIC. - Melhor adaptação de alguma linguagem para tarefa específica como Gráficos (Pascal), Inteligência Artificial (Prolog, LISP), matemáticas (Pascal e FORTRAN), aplicações comerciais (COBOL, Clipper e BASIC). As versões atuais das linguagens BASIC, C, Clipper, Pascal e COBOL, estão muito mais semelhantes do que o eram ao tempo em que este quadro foi elaborado, portanto na prática muitas vezes este quadro, meramente teórico, pode tornar-se inaplicável. À médio prazo, pode-se afirmar que a linguagem C deverá ir desalojando as outras linguagens podendo até mesmo tornar-se um padrão de direito, porém devemos lembrar que algumas linguagens foram propostas para isto (Algol, PL/1) e não só não conseguiram atingir seus objetivos como praticamente desapareceram.

ou um valor maior que zero caso ele tenha sido finalizado por uma situação anormal. comandos de controle e chamadas à outras funções. A tabela a seguir apresenta alguns dos principais . começa com o símbolo # no início da linha.1 ± Comentários Os comentários servem principalmente para documentação do programa e são ignorados pelo compilador. esta função deve retornar 0 (zero) se o programa foi finalizado com sucesso. pois é o seu ponto de entrada.h e se encontram em algum diretório pré -definido pelo compilador. com o comando return. expressões. delimitado por um par de chaves {}. Normalmente a declaração desta função possui a seguinte forma: int main(void). ou seja.h . isto é. Sempre que o programa utilizar alguma função da biblioteca-padrão deve ser incluído o arquivo correspondente. 1.6.Funções de entrada e saída (I/O) string. um programa escrito em linguagem C. Abaixo. o programa começa a ser executado no início da função main e termina ao final desta função. muito simples que você pode rodar no seu compilador: /* Seu primeiro programa em linguagem C*/ #include <stdio.h> void main () { printf ("Bem vindo ao mundo da programação em C!!! \n"). chamadas pela função main.6 ± Estrutura de um Programa em Linguagem C Um programa em Linguagem C é formado por uma ou mais funções. sendo que pelo padrão ANSI.6. Estes arquivos. mas adiante será estudada outra forma de declaração para esta função. /* Aguarda pressionar Enter */ } 1. Os comentário iniciam com o símbolo /* e se estendem até aparecer o símbolo */. o programa pode possuir outras funções. em C.1. Ele serve para incluir alguns arquivos que contêm declaração das funções da biblioteca padrão. possuem a extensão .h . normalmente.Funções de tratamento de strings . sendo que estas devem ser. direta ou indiretamente. a execução do programa é finalizada. Ao concluir a função main. getchar(). contendo um conjunto de declarações.h da linguagem C: Descrição stdio. Um comentário pode aparecer em qualquer lugar no programa onde possa aparecer um espaço em branco e pode se estender por mais de uma linha. a linha que contêm a diretiva é substituída pelo conteúdo do arquivo especificado. Uma função denominada main é obrigatória em todos os programas. Além da função main. portanto não irão afetar o programa executável gerado. Cada função possui um nome exclusivo e corresponde à um bloco de código.2 ± Diretiva #include Toda a diretiva. A diretiva #include inclui o conteúdo de um outro arquivo dentro do programa atual. entre outras coisas. Sintaxe: #include < nome do arquivo > ou #include ³ nome do arquivo´ O primeiro caso é o mais utilizado.

Ele é usado para separar diferentes comandos dentro do seu código em C. o ponto-e-vírgula mostra ao compilador quando uma linha de comando termina e quando outra linha de comando se inicia.h .Funções de uso genérico A segunda forma. No caso do Interpretador. que tem a extensão . serve normalmente para incluir algum arquivo que tenha sido criado pelo pró prio programador ou por terceiros e que se encontre no diretório atual. Nele é mostrado que a Linguagem C foi desenvolvida por Dennis Ritchie e que ela é na verdade uma linguagem derivada de outras duas linguagens de programação anteriores. que o computador compreende. ele faz isso linha por linha do código-fonte. foi mostrada a diferença entre compilador e interpretador. o desenvolvimento de uma nova linguagem tornou-se inevitável.1 ± História da Linguagem C: apresenta um breve relato sobre o desenvolvimento da Linguagem de Programação C.3 ± Uso do Ponto-e-Vírgula Você pode não ter percebido.obj . Durante o processo de compilação executado pelo compilador.h . 1. você coloca seus comando em um arquivo-fonte. e com isso.2 ± Compiladores e Interpretadores: neste item. Mesmo sendo uma linguagem flexível e poderosa. Compiladores e Interpretadores são programas que ³traduzem´ um código-fonte de um programa para a linguagem que a máquina entende.Funções matemáticas ctype. ou seja. a Linguagem C chegou a seus limites. sendo desenvolvida a Linguagem C++. quando terminamos a declaração dos comandos printf() e getchar().7 ± Compreendendo os Tipos de Arquivo Ao criar um programa em linguagem C.h .exe .math. mas no código em C apresentado no item 1. y y 1. Com esta síntese você poderá relembrar conceitos vistos durante nosso estudo ou mesmo direcionar seu estudo. 1. a BCPL e a Linguagem B. é necessário que exista na . toda vez que o programa em questão é executado. se você esquecer do ponto-e-vírgula seu compilador irá acusar um erro pois ele não irá saber quando termina ou começa um determinado comando dentro do código que você digitou. caso você já tenha conhecimentos na Linguagem C. no mesmo diretório do programa que está sendo compilado. ou seja 1s e 0s. Ou seja.c . y y 1.Funções de teste e tratamento de caracteres stdlib.6 usamos duas vezes o ponto-e-vírgula.8 ± Síntese do Módulo É apresentado à seguir.6. o compilador irá criar um programa executável com a extensão . uma síntese do que foi tratado em cada item deste módulo. 1. Ou seja. Foram feitas várias modificações e melhorias na Linguagem C++ para que ela pudesse suportar a programação orientada a objeto (POO). Durante a compilação. que na verdade era a Linguagem C com novas características que superaram seus limites. Estes arquivos contém as instruções em forma binária. Se o seu programa for compilado com sucesso. o compilador cria em seu diretório outros arquivos com extensão . onde o nome do arquivo aparece entre aspas duplas.

Mas mostra-se que não é possível pensar em abandonar as outras linguagens e usar-se somente a Linguagem C. y y 1. ou seja. Mostrou-se que a Linguagem C se classifica como uma linguagem de nível médio. a linguagem C/C++ possui sub-rotinas com variáveis locais. Uma função denominada main é obrigatória em todos os programas. pois é o seu ponto de entrada.3 ± Características da Linguagem C: neste item. aos eventos que ocorrem enquanto o programa está sendo executado.2 ± Diretiva #include: neste subitem foi estudada a diretiva #include inclui o conteúdo de um outro arquivo dentro do programa atual. . portanto não irão afetar o programa executável gerado.5 ± A Linguagem C Comparada à Outras Linguagens: neste item foi feita uma comparação entre a Linguagem C e outras linguagens de programação. a Linguagem C é veloz e tem uma alta portabilidade. seu código é compacto e rápido.6. pois mesmo possuindo estruturas de controle de alto nível.6 ± Estrutura de um Programa em Linguagem C: foi estudado neste item que um programa em Linguagem C é formado por uma ou mais funções. y y 1. sistemas operacionais e até em efeitos especiais em filmes.exe e .7 ± Compreendendo os Tipos de Arquivo: foi explicado detalhadamente os tipos de arquivos usados na programação em Linguagem C. bytes e endereços de uma maneira bem próxima à máquina. como por exemplo.1 ± Comentários: comentários servem principalmente para documentação do programa e são ignorados pelo compilador.3 ± Uso do ponto-e-vírgula: foi visto que o ponto-e-vírgula é usado para separar diferentes comandos dentro do seu código em C. o programa começa a ser executado no início da função main e termina ao final desta função. Assembly. a Linguagem C é largamente utilizada no desenvolvimento de programas.6. Cobol. Além do mais. o Compilador cria um arquivo que pode ser lido pelo sistema operacional da máquina. Durante o processo de compilação executado pelo compilador. o ponto-e-vírgula mostra ao compilador quando uma linha de comando termina e quando outra linha de comando se inicia. comandos de controle e chamadas à outras funções. Clipper. como por exemplo. a linha que contêm a diretiva é substituída pelo conteúdo do arquivo especificado. . y y 1.c. os arquivos com extensão . a Linguagem C é estruturada.6. Foi visto também que o termo tempo de compilação refere-se aos eventos que acontecem durante o processo de compilação e tempo de execução. apresentou-se as principais características da Linguagem C. ou seja. Os comentário iniciam com o símbolo /* e se estendem até aparecer o símbolo */. delimitado por um par de chaves {}. entre elas: que a Linguagem C é portável.4 ± Aplicações Escritas em C: devido à sua compatibilidade com outras linguagens de programação. No caso do Compilador é gerado um programa executável. Cada função possui um nome exclusivo e corresponde à um bloco de código. y y 1. y y 1. a linguagem é case-sensitive. ela permite a manipulação de bits. expressões. Basic.obj . y y 1. contendo um conjunto de declarações. eliminando assim a necessidade de um interpretador instalado. y y 1.máquina um interpretador específico instalado para a linguagem de programação em que o programa em questão foi escrito. entre outras coisas. Ela serve para incluir alguns arquivos que contêm declaração das funções da biblioteca padrão. isto é. y y 1.

Módulo 2 ± Características e Definições Gerais da Linguagem C
2.1 Palavras Reservadas na Linguagem C
Na Linguagem C existem palavras que são de uso reservado, ou seja, não podese usá-las para escrever programas, por exemplo usando o nome de uma palavra reservada para referenciar uma variável. Uma palavra reservada é essencialmente um comando e, na maioria das vezes, as palavras reservadas de uma linguagem definem o que pode ser feito e como pode ser feito. O conjunto de palavras reservadas em Linguagem C especificado pelo padrão ANSI C são as relacionadas abaixo:
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

Como já foi dito no Módulo 1, a Linguagem C diferencia letras maiúsculas e minúsculas, ou seja, char é uma palavra reservada da Linguagem C mas CHAR ou ChAr não é. Reforçando o que já foi mencionado, as palavras reservadas só irão executar os comandos que lhes foram designados.

2.2 ± Nomes e Identificadores Usados na Linguagem C
A Linguagem C chama o que é usado para referenciar variáveis, funções, rótulos e vários outros objetos definidos pelo usuário de identificadores. Quanto aos nomes ou identificadores usados na declaração de variáveis, deve-se considerar as seguintes regras:
y y nomes de variáveis começam com uma letra ('A'..'Z', 'a'..'z') ou pelo underscore

('_');
y y após podem ser seguidos dígitos, letras e underscores; y y evitar o uso do '_' no primeiro caractere do identificador de uma variável, pois este tipo de identificadores é de uso do sistema;

y y normalmente ao declarar-se uma variável esta será inicializada com zero. Não se deve, no entanto, contar que isto sempre seja verdadeiro, portanto inicializa sempre as -se variáveis.

Aqui estão alguns exemplos de nomes de identificadores corretos e incorretos:

Correto count test23 high_balance

Incorreto 1count Olá! Aqui high..balance

Em C os primeiros 32 caracteres de um nome de identificador são significantes. Isso quer dizer que duas variáveis com os 32 primeiros caracteres em comum, diferindo somente no 33º , são consideradas iguais. Como você deve lembrar, em C, letras maiúsculas e minúsculas são tratadas como diferentes e distintas umas das outras. Por isso, count, Count e COUNT são três identificadores distintos.

Um identificador não pode ser o mesmo que uma palavra reservada e não devem ter o mesmo nome de uma função ± tanto uma função que você tenha escrito como uma função de biblioteca da linguagem C.

2.3 Tipos e Dados
Quando um programa é escrito em qualquer linguagem de programação é necessário a definição de algumas variáveis. Variáveis são instâncias em que serão armazenados valores utilizados durante a execução de programas. Estas variáveis podem ser modificadas para suportar diferentes tipos de dados. Na tabela abaixo constam os tipos básicos de dados da Linguagem C: Tipo Char Int Float double void Tamanho (em bits) 8 16 32 64 0 Intervalo -128 a 127 -32768 a 32767 3,4E-38 a 3,4E+38 1,7E-308 a 1,7E+308 sem valor

2.3.1 Modificadores de Tipos
Possuindo os tipos básicos de dados, pode-se ainda formatá-los para atender melhor as necessidades de cada situação. Com exceção do tipo void, todos os outros tipos básicos podem ter modificadores precedendo-os. Você pode ter como modificadores signed, unsigned, long e short. Os modificadores signed, unsigned, long e short podem ser aplicados aos tipos de base caractere e inteira. Entretanto, long, também pode ser aplicado ao tipo double. A tabela a seguir mostra todas as combinações permitidas dos tipos básicos e dos modificadores de tipo.

Tipo char unsigned char signed char int unsigned int signed int short int unsigned short int signed short int long int signed long int unsigned long int float double long double

Tamanho (em bits) 8 8 8 16 16 16 16 16 16 32 32 32 32 64 80

Intervalo -128 a 127 0 a 255 -128 a 127 -32768 a 32767 0 a 65535 -32768 a 32767 -32768 a 32767 0 a 65535 -32768 a 32767 -2147483648 a 2147483647 -2147483648 a 2147483647 0 a 4294967295 3,4E-38 a 3,4E+38 1,7E-308 a 1,7E+308 3,4E-4932 a 1,1E+4932

A linguagem C permite uma notação simplificada para declaração de inteiro unsigned, short ou long. Você pode simplesmente usar a palavra unsigned, short ou long sem o int. O int está implícito. Por exemplo:
unsigned x; unsigned int x;

declaram igualmente variáveis inteiras sem sinal.
Variáveis do tipo char podem ser usadas para armazenar valores outros que são simplesmente o conjunto de caracteres ASCII. Uma variável char pode ser usada também como um pequeno inteiro com intervalo de 128 a 127, e no lugar de um inteiro quando a situação não requer números grandes.

2.4 Definição de Variáveis
Variáveis são instâncias onde o programa em execução coloca os dados que estão sendo processados durante sua execução. As variáveis devem ser declaradas, ou seja, devem ser definidos nome, tipo e algumas vezes seu valor inicial. As variáveis são classificadas em variáveis locais e globais. Variáveis globais são aquelas declaradas fora do escopo das funções. Variáveis locais são aquelas declaradas no início de um bloco e seus escopos estão restritos aos blocos em que foram declaradas. A declaração de variáveis locais deve obrigatoriamente ser a primeira parte de um bloco, ou seja, deve vir logo após um caractere de abre chaves , '{'; e não deve ser intercalada com instruções ou comandos. Veja a sintaxe para se declarar uma variável:
<tipo> <nome>

Exemplos:

int mul = 100; char a, b, c; float valor;

2.5 Definição de Constantes
O conceito de constantes em linguagens de programação é atribuir um certo valor constante a um nome, e quando este nome for referenciado dentro do código do programa, será utilizado nas operações o valor atribuído a este nome. Ou seja, se for definida a constante PI com o valor 3,1415926536 , quando for encontrado no código o nomePI, será utilizado em seu lugar o valor 3,1415926536 . Na Linguagem C, constantes podem ser definidas da seguinte maneira :
#define <nome_da_constante> valor

Exemplos:
#define PI 3,1415926536 #define SINAL "aberto" #define MULT A*B

Observe que na definição de uma constante não há o ³;´ no final. Se for colocado, este fará parte do valor associado à constante.

2.5.1 Constantes Hexadecimais e Octais
Em programação algumas vezes é comum usar um sistema de numeração baseado em 8 ou 16 em vez de 10. O sistema numérico baseado em 8 é chamado octal e usa os dígitos de 0 a 7. Em octal, o número 10 é o mesmo que 8 em decimal. O sistema numérico de base 16 é chamado hexadecimal e usa os dígitos de 0 a 9 mais as letras de A até F, que equivalem a 10, 11, 12, 13, 14 e 15. Por exemplo, o número hexadecimal 10 é 16 em decimal. Por causa da freqüência com que estes dois sistemas numéricos são usados, a linguagem C permite que se especifique constantes inteiro em hexadecimal ou octal em vez de decimal, se preferir. Uma constante hexadecimal deve começar com 0x (um zero seguido de um x), seguido pela constante em formato hexadecimal. Uma constante octal começa com um zero. Aqui estão alguns exemplos:
hex = 0xFF; /* 255 em decimal */ oct = 011; /* 9 em decimal */

2.5.2 Constantes Strings
Outro tipo de constante suportada pela Linguagem C é o tipo string. Uma string é um conjunto de caracteres entre aspas. Por exemplo, você é um vencedor é uma string.

1 Operador de atribuição O operador ³=´ atribui um valor ou resultado de uma expressão contida a sua direita para a variável especificada a sua esquerda. a linguagem C fornece constantes caractere mais barra invertida especiais.Não confunda strings com caractere. printf (³este é um teste \n´).6. 2. .3 Códigos de Barra Invertida Colocar todas as constantes caractere entre aspas funciona para muitos caracteres. Exemplos: a = 10. são impossíveis de serem inseridos em uma string a partir do teclado. então.6 Operadores A linguagem C é muito rica em operadores internos. Uma constante caractere simples fica entre dois apóstrofos. 2. seguido de uma nova linha. como o retorno de carro. Por exemplo: ch = µ\t¶.5. A linguagem C possui três classes gerais de operadores: aritméticos. Por isso. imprime este é um teste na tela. Esse fragmento de código primeiro atribui uma tabulação a ch e. Entretanto a é uma string que contém somente uma letra. Um operador é um símbolo que diz ao compilador para realizar manipulações matemáticas e lógicas específicas. b = c * valor + getval(x). relacionais e lógicos e bit-a-bit. mas alguns. 2. Estes códigos são mostrados na tabela a seguir: Código \b \n \t \ \ \a \xN Significado Retrocesso Código \f \r \ ###BOT_TEXT### \v \N Significado Alimentação de formulário Retorno de carro Aspas Nulo Tabulação vertical Constante octal Nova linha Tabulação horizontal Apóstrofo Barra invertida Sinal sonoro Constante hexadecimal Usa-se um código de barra invertida exatamente da mesma maneira como usa qualquer outro caractere. por exemplo a .

uma terceira para contas a receber e uma quarta para gerar um balanço. Vamos citar o exemplo de um determinado programa.1 Funções A maioria dos programas apresentam a função main. resultando valores lógicos de TRUE (verdadeiro) ou FALSE (falso).3 Operadores Relacionais Operam sobre expressões. pode-se melhorar a clareza e compreensão do trabalho dividindo-o em partes menores. Se o programa for dividido em blocos menores e mais facilmente gerenciáveis. poderá evitar erros. À medida que o tamanho e a complexidade do programa aumentam.a = b = c = 1. Se fossem colocados todos os comandos do programa dentro da função main. Quando os programas tornam-se maiores e mais complexos. uma função diferentes para contas a pagar. e seria difícil de compreende-lo. São eles: Operador + * / % - Ação Soma subtração multiplicação divisão módulo da divisão (resto da divisão inteira) sinal negativo (operador unário) 2.6. usa a função printf para exibir uma mensagem: . Por exemplo. suponha um programa de contabilidade.2 Operadores Aritméticos São aqueles que operam sobre números e expressões. aumenta também a possibilidade de erros. Uma função é uma coleção nomeada de comandos que efetuam uma tarefa específica.6. o programa ficaria muito grande. resultando valores numéricos. /*Aceita associação sucessiva de valores*/ 2. chamadas funções. são eles: Operador <p class=MsoNormal a Ação Módulo 3 Funções na Linguagem C 3. a função ola_mundo. Poderia haver no programa uma função que efetuasse as operações normais de um contador.

Em muitos casos.h> void ola_pessoal(void) { printf("Ol } pessoal!\n"). Para usar uma função. Os programadores referenciam o uso de uma função como uma chamada da função. void main(void) { ola_pessoal(). Um parâmetro é a informação que o programa passa para a função. mude a função main dentro do programa anterior como mostrado aqui: void main(void) . usa a função oi_pessoal: #include <stdio. O void que aparece nos parâmetros diz que a função não usa parâmetros. iniciando a execução do programa com o primeiro comando da função. } A palavra chave void diz a Linguagem C que a função não retorna um valor. O programa a seguir. deve-se preceder o nome da função com void. as informações que se especifica dentro dos parênteses são parâmetros. imediatamente transfere a execução do programa para a função. Se a função não usa return para retornar um resultado. Quando uma função não usa parâmetros. quando os programas chamam printf. as funções usarão return para retornar o valor de um cálculo para a função chamadora. deve colocar void dentro dos -se parênteses. Para compreender melhor esse processo. a função main é executada primeiro. Como se pode ver. especifica-se o nome da função seguido de parênteses. a Linguagem C transfere a execução para o comando que segue imediatamente a chamada da função. Depois que o último comando da função termina. Por exemplo.void ola_mundo (void) { printf(³Olá mundo! \n´). o único comando em main é a chamada da função oi_pessoal. Quando C encontra a chamada da função. } Ao executar esse programa.

a Linguagem C considera a variável de cada função como distinta. que usa a variável contador em um laço for para exibir uma mensagem 3 vezes: #include <stdio. Portanto. elas deverão ser declaradas no início da função. oi_pessoal(). /* Variavel */ for (contador = 1. muitas delas requerem que as variáveis gerem resultados valiosos. Se uma função requer muitas variáveis. } void main(void) { tres_olas(). exatamente como feito em main. os nomes usados para essas variáveis são exclusivos para a função. } Quando se declara variáveis dentro de uma função.{ printf(³Prestes à chamar a função \n´). se o programa usa dez funções diferentes e cada função usa uma variável chamada contador. printf(³Voltei da chamada da função \n´). contador <= 3 . Para usar uma variável dentro de uma função. exa tamente como se faria dentro de main. contador++) printf("Oi pessoal! \n").h> void tres_olas(void) { int contador. precisa-se primeiro declarar a variável. o programa a seguir chama a função três_olas. } 3.2 Variáveis dentro das Funções À medida que as funções vão se tornando mais úteis nos programas. Por exemplo. .

contador <= 3. Exatamente como pode declarar variáveis em main. uma função pode chamar (usar) outra. usa-se o nome da função main para determinar o primeiro comando que o programa executará. } void main(void) { tres_olas(). Também é possível utilizar construções tais como if.h> void ola_pessoal(void) { printf("Ola. main chama a função tres_olas. Na verdade. Por exemplo. por sua vez. a regra é bem simples: tudo o que se pode fazer em main. } void tres_olas(void) { int contador. caso tenha perguntas sobre os tipos de operações que podem ser executadas dentro das funções. também pode declarar variáveis nas funções. for (contador = 1. o programa a seguir usa duas funções. de modo que. e for em suas funções. como mostrado aqui: #include <stdio. chama a função oi_pessoal três vezes para exibir mensagens na tela. } 3. Finalmente. pode-se fazer em uma função. contador++) ola_pessoal(). Quando o programa inicia.3.3 Main como uma Função Quando um programa é criado. main é uma função. que. pessoal! \n"). while.4 Introdução aos Parâmetros .

que chama a função oi_pessoal três vezes: void tres_olas(void) { int contador. ola_conta(100). contador <= 3. /*Exibe a mensagem 2 vez es*/ /*Exibe a mensagem 100 vezes*/ /*Exibe a mensagem uma vez*/ O programa a seguir ilustra como pode usar uma função com um parâmetro: . a função precisa especificar o nome e o tipo do parâmetro. a função ola_conta suporta um parâmetro do tipo int chamado msg_conta. for (contador = 1. considere a seguinte construção da função tres_olas. Quando outra função. como mostrado aqui: void ola_conta(int msg_conta) Neste caso. contador++) ola_pessoal(). quiser usar ola_conta. A maioria dos programas apresentados passou parâmetros para a função printf. Por exemplo. tal como main. } Uma função mais útil permite especificar. ola_conta(1). a função precisa especificar o valor que a Linguagem C atribui para o parâmetro msg_conta: ola_conta(2). o número de vezes que quer que o programa exiba a mensagem. À medida que o uso de funções for maior. Para usar um parâmetro.Um parâmetro é um valor passado a uma função. poderá passar parâmetros para as funções de modo a torná -las mais úteis. como um parâmetro.

ola_conta(5). pode-se passar um número irrestrito de parâmetros para uma função. portanto. as pesquisas mostram que. Quando a função usa mais de um parâmetro. } 3. quando o número de parâmetros excede sete. contador <= msg_conta. printf("Exibe a msg cinco vezes \n"). pessoal! \n").5 Parâmetros Múltiplos Em geral. precisa especificar o tipo e o nome de cada parâmetro e separar os parâmetros por vírgulas. contador++) oi_pessoal(). ficando. mais susceptível a erros.#include <stdio. como mostrado aqui: . } void main(void) { printf("Exibe a msg duas vezes\n").h> void oi_pessoal(void) { printf("Ola. a função mostra-se mais difícil de se compreender e usar corretamente. } void ola_conta(int msg_conta) { int contador. No entanto. for (contador = 1. ola_conta(2).

se uma função retorna um valor do tipo int. a função usa o comando return para retornar o resultado do cálculo ao chamador. se o chamador passar o valor 5 para a função. etc. Por exemplo.6 Retornando um Valor de uma Função Funções mais complexas normalmente realizam cálculos e retornam resultados. int num_cargo) { /*Comandos da função*/ } Quando o programa chamar a função. float sal.) determina o tipo da função.void uma_funcao(int idade. 40000. Por exemplo. } Como visto. como mostrado aqui: . como mostrado aqui: int uma_função(int valor) { /*Comandos da função*/ } A função a seguir. O tipo de valor que a função retorna (int. será necessário especificar valores para cada parâmetro. ou 125: int i_cubo(int valor) { return (valor *valor *valor). tal como printf. Pra fornecer um resultado ao chamador. O código dentro da função de chamada po atribuir o resultado da função de chamada (também conhecido como valor de retorno) a uma variável.00. como mostrado aqui: uma_funcao(33. 534). uma função precisará usar o comando return que será implementado como segue: return (resultado). é necessário preceder o nome da função com o nome do tipo. a função retornará o valor 5*5*5. float. retorna o cubo do valor inteiro que o programa especifica como seu parâmetro. char. 3. ou o código pode usar o valor de retorno dentro de uma terceira função.

printf("O cubo de 5 Ã %d \n". como mostrado a seguir (observe que o valor de retorno também é do tipo float): float f_cubo(float valor) { return (valor *valor *valor). } Os valores que são passados para uma função precisam corresponder aos tipos de parâmetros contidos dentro da declaração dessa função.h> int i_cubo(int valor) { return(valor * valor * valor).result = i_cubo(5). crie uma segunda função chamada f_cubo. i_cubo(5)). i_cubo(7)). printf(³O cubo de 5 é %d \n´. I_cubo(5)). . ele continua a execução da função chamadora. O programa não executa quaisquer outros comandos dentro da função após o comandoreturn. Por exemplo. } 3. printf("O cubo de 7 Ã %d \n". } void main(void) { printf("O cubo de 3 Ã %d \n". O programa a seguir usa a função i_cubo para determinar vários valores diferentes ao cubo: #include <stdio. i_cubo(3)). se quiser determinar o cubo de um valor em ponto flutuante. ela finaliza imediatamente a execução da função e retorna o valor especificado para o chamador.7 Comando Return Quando a Linguagem C encontra um comando return em uma função. Em vez disso.

} A função compara_valores examina dois valores listados na tabela abaixo: Resultado 0 1 2 Significado Os valores são iguais O primeiro valor é maior que o segundo O segundo valor é maior que o primeiro Como regra. Na maioria dos casos. considere a função compara_valores. mostrada a seguir: int compara_valores(int primeiro. int segundo) { if (primeiro == segu ndo) return (0). deve-se tentar limitar as funções a usar somente um comando return. else if (primeiro > segundo) return (1). if (primeiro == segundo) return = 0. else if (primeiro < segundo) return = 2. À medida que as funções se tornarem maiores e mais complexas. int segundo) { int result. cada um dos quais retornando um valor para uma condição específica. como mostrado aqui: int compara_valores(int primeiro. Por exemplo.Outros programas possuem funções que contêm múltiplos comandos return. . return(result). else if (primeiro > segundo) return = 1. pode-se reescrever a função para que ela use somente um comando return. else if (primeiro < segundo) return (2). ter muitos comandos return normalmente tornará as funções mais difíceis de compreender.

então utilize quantos comandos return forem necessários. Pode-se observar que. printf("O cubo de 3. 3. } . a Linguagem C permite colocar protótipos de função no seu programa. /*Retorna um parâmetro int*/ /* Retorna um parâmetro float*/ Como pode-se ver. como a função é simples. Portanto.h> int i_cubo(int).Colocando as funções antes dos seus chamadores dentro do código do seu programa. algumas vezes. No entanto.8 Protótipos de Função A maioria dos novos compiladores C precisa conhecer os tipos de retorno e de parâmetro de uma função antes do programa chamar a função. void main(void) { printf("O cubo de 3 Ã %d \n". se usar múltiplos return atingir os objetivos pré-estabelecidos. Deve-se escrever o código mais legível e facilmente modificável quanto possível.7 Ã %f \n". à medida que as funções se tornarem mais complexas. à medida que os programas ficam mais complexos. usar mais de um comando return produz um código mais legível do que a alternativa de um único return. a vantagem ficará mais clara. Antes que a função seja usada pela primeira vez. o protótipo da função especifica os tipos de parâmetro e de retorno da função. pode se tornar impossível colocar as funções sempre na ordem correta. pode-se ter dificuldades em compreender qual a vantagem de usar um único comando de return. considere um programa que use as funções i_cubo e f_cubo. float f_cubo(float). para descrever os tipos de parâmetro e de retorno de uma função.} Neste caso.7)). float f_cubo(float). o programa pode incluir um protótipo semelhante ao seguinte: int i_cubo(int). f_cubo(3. permitirá que o compilador C conheça as informações que ele deverá ter antes de encontrar a chamada da função. O programa a seguir usa dois protótipos de função para eliminar a necessidade de ordem da função: #include <stdio. Por exemplo. No entanto. i_cubo(3)).

int i_cubo(int valor) { return(valor * valor * valor). O programa a seguir usa a função valor_medio para determinar a média de três valores do tipo int. char. A função retorna a média usando um valor do tipo float (repare que o cabeçalho da função especifica o tipo de retorno da função): #include <stdio. } float f_cubo(float valor) { return(valor * valor * valor).) precisase informar ao compilador o tipo de retorno da função.h> . uma função criada para um determinado programa atende as necessidades de um segundo programa.10 Funções que não retornam Int Muitas funções retornam valores do tipo int. Para isto é só copiar a função de um para outro programa. 3. As duas ou três horas que serão gastas para ler a documentação da biblioteca de execução pouparão muitas horas de programação. Quando uma determinada função não retorna um valor do tipo int (em vez disso ela pode retornar float. etc. A maioria dos compiladores fornece centenas de funções de biblioteca de execução com propósito que vão de abertura e trabalho com arquivos para acessar informações do disco ou de diretório para determinar o tamanho de uma string de caracteres. double.9 Biblioteca de Execução Muitas vezes. Muitos compiladores referenciam essas funções internas como biblioteca de execução. não deixe de examinar as funções que seu compilador fornece. } 3. Antes de gastar um tempo enorme desenvolvendo uma ampla variedade de funções de propósito geral. A capacidade de reutilizar as funções em mais de um programa pode poupar um tempo considerável de programação e teste.

133 e 155 Ã %f \n".11 Variáveis Locais A Linguagem C permite declarar variáveis dentro de suas funções. respectivamente. A função valores_locais declara 3 variáveis a. pois seus nomes e valores somente têm significado dentro da função que contém a declaração da variável. a. 133. } void main(void) { printf("A média de 100.0). No entanto.b. O programa a seguir ilustra o conceito de uma variável local. printf("a contÃm %d b contÃm %d c contÃm %d \n". } 3. b=2. a. Essas variáveis são chamadas de variáveis locais. } void main(void) { printf("a contÃm %d b contÃm %d c contÃm %d \n". b e c.h> void valores_locais(void) { int a=1. e c estão indefinidos.c).float valor_medio(int a. #include <stdio. b. 2 e 3. e atribui às variáveis os valores 1. A função main tenta imprimir o valor de cada variável. c=3.b. dizendo que os símbolos a. 155)). int b. como os nomes dos valores são locais à função. o compilador gera erros. } .c). int c) { return ((a + b + c) / 3. valor_medio(100.

float b) { float result. depois.h> float soma(long int a. \n").. } void main(void) { long int i. float result = 0. mas usa uma função para somar os valores. usa o valor de retorno para retornar a execução do programa para a posição correta. time(&hora_inicio). como mostrado aqui: #include <stdio. os parâmetros e as variáveis locais na pilha. Para compreender melhor o impacto da sobrecarga da função no desempenho do seu programa. a Linguagem C descarta o espaço da pilha que continha as variáveis locais e parâmetros.12 . result = a + b. Quando a função termina. repete um laço novamente. Em seguida..h> #include <time. Embora o uso da pilha seja poderoso porque permite que o programa chame e passe as informações para as funções. também consome tempo de processamento. Os programadores chamam a quantidade de tempo que o computador requer para colocar e retirar informações da pilha de sobrecarga da função.Sobrecarga da Função Quando um programa usa uma função. a Linguagem C armazena o endereço de retorno. e. Primeiro o programa usa um laço para somar os valores de 1 a 100. .3. time_t hora_inicio.000. printf("Trabalhando. return(result). considere o programa a seguir. hora_parada.

printf("Usando função %d segundos hora_inicio). } \n". time(&hora_inicio). hora_parada - Na maioria dos sistemas. printf("Trabalhando. time(&hora_parada). result). Portanto. time(&hora_parada). todos os programas em Linguagem C podem usar variáveis globais. os cálculos baseados em funções podem requerer quase o dobro do tempo de processamento. hora_parada . valores e existência são conhecidos em todo o programa. é necessário considerar os benefícios que elas oferecem versus a sobrecarga no desempenho que introduzem. i++) result = soma(i. i++) result += i. quando usar funções dentro dos programas. b e c: . printf("Usando laço %d segundos \n".13 Declarando Variáveis Globais Além das variáveis locais.. cujos nomes.hora_inicio). i <= 100000L.for (i = 1. Em outras palavras.. i <= 100000L. \n"). O programa a seguir ilustra o uso de três variáveis globais a. a Linguagem C permite que os programas usem variáveis globais. for (i = 1. 3.

Embora as variáveis globais possam parecer convenientes. todas as funções do programa podem usar e alterar os valores da variável global simplesmente referenci ndo o nome da a variável global.h> . } void main(void) { valores_globais(). } Quando este programa é compilado e executado. o programa a seguir usa as variáveis globais a. as funções variaveis_globais e main exibem os valores da variável global. Declarando variáveis globais deste modo. c = 3. Por exemplo.h> int a = 1. c). o uso incorreto delas podem causar erros que são difíceis de depurar. a. b = 2. /* Variaveis globais */ void valores_globais(void) { printf("a contÃm %d b contÃm %d c contÃm %d \n". Observe que as variáveis globais são declaradas fora de todas as funções. b. 3. b. c). printf("a contÃm %d b contÃm %d c contÃm %d \n".#include <stdio. b e c.14 Solucionando os Conflitos de Nomes de Variáveis Locais e Globais Se um programa usa variáveis globais. algumas vezes o nome de uma variável global é o mesmo que aquele de uma variável local que seu programa declara dentro de uma função. A função conflito_a usa uma variável local chamada a e as variáveis globais b e c: #include <stdio. a.

o valor das variáveis que a função chamadora passou para a função não é modificada dentro da função chamadora. as alterações que a função conflito_a fez na variável a somente aparecem dentro da função. exibirá os valores. Como a Linguagem C usa chamada por valor. 3.15 Chamada por Valor Os programas passam informações para funções usando parâmetros.h> void exibe_e_altera(int primeiro. ois Quando a função terminar. o programa exibirá os valores das variáveis. printf("a contÃm %d b contÃm %d c contÃm %d \n". int terceiro) . Como você pode ver. } Quando nomes de variáveis globais e locais estiverem em conflito. c). printf("a contÃm %d b contÃm %d c contÃm %d \n". b e c) para a função exibe_e_altera. } void main(void) { conflito_a(). c=3. o programa a seguir passa três parâmetros (as variáveis a. int segundo. a. c). a Linguagem C usa uma técnica conhecida como chamada por valor para fornecer à função uma cópia dos valores dos parâmetros. /* Variáveis globais */ void conflito_a(void) { int a=100. somará 100 aos valores e dep exibirá o resultado. b=2. b. Usando a chamada por valor. Por exemplo. A função. como mostrado a seguir: #include <stdio. a. quaisquer modificações que a função fizer nos parâmetros existem apenas dentro da própria função. b. a Linguagem C usará sempre a variável local. Quando a função termina. por sua vez.int a=1. a função não altera os valores das variáveis dentro do chamador. Quando um parâmetro é passado a uma função.

Por exemplo.{ printf("Valores originais da função %d %d %d \n". terceiro += 100. os programas precisam passar o parâmetro para a função usando chamada por referência. exibe_e_altera(a.16 . Quando as funções alteram o valor de um parâmetro. printf("Valores finais em main %d %d %d \n". uma função tal como strupr precisa converter as letras em uma string de caractere para maiúsculas. segundo. segundo += 100. c). uma função que lê informações de um arquivo precisa colocar as informações em uma matriz de string de caracteres.b. c = 3. as funções recebem . as funções não podem modificar o valor de uma variável passada para uma função. primeiro += 100. terceiro). b = 2. primeiro. b. usando a chamada por valor. } void main(void) { int a = 1. as variáveis dentro de main estão inalteradas. No entanto. terceiro). A diferença entre chamada por valor e chamada por referência é que. a.c). segundo. Quando a função termina. } Como pode ser visto. na maioria dos programas. as alterações que a função faz nas variáveis somente são visíveis dentro da própria função. primeiro. Da mesma forma.Chamada por Referência Usando a chamada por valor. as funções modificarão as variáveis de um modo ou de outro. 3. printf("Valores finais da função %d %d %d \n".

Pode-se fazer os parâmetros que seguem a primeira string de caracteres serem números. mais adiante. Por exemplo. A estrutura básica da função printf() é dada a seguir: printf ("string de controle". O primeiro parâmetro precisa ser sempre uma string de caracteres. Quando o programa usa a função printf(). uma string ou mesmo um endereço de memória.1 ± Função PRINTF() Quando é necessário imprimir na tela um dado. Quando os programas trabalharem com variáveis. só que um E maiúsculo é usado se o formato %e for escolhido Exibe um número em notação octal . o valor da variável). um valor. uma tabela com os especificadores de formato: Código %c %d %i %e %E %f %g %G %o Significado Exibe um caractere Exibe um inteiro em formato decimal Exibe um inteiro Exibe um número em notação científica (com e minúsculo) Exibe um número em notação científica (com E maiúsculo) Exibe um ponto flutuante em formato decimal Usa %e ou %f.uma cópia do valor de um parâmetro. discute os Ponteiros em detalhes. A seguir. Módulo 4 ± Estudo das Funções PRINTF() e SCANF() 4. Por outro lado. A string de controle contém tanto caracteres para serem impressos na tela como códigos de formato que especificam como apresentar o restante dos argumentos. por ora. pode-se incluir especificadores de formato. usa-se o %d. usa-se a função printf(). com a chamada por referência. Para acessar posteriormente o valor na posição de memória para o qual o Ponteiro aponta. expressões. Para atribuir o endereço de uma variável a um ponteiro. lista de argumentos). é necessário usar o operador de endereço "&". as informações que instrui printf() a imprimir são chamadas parâmetros ou argumentos de printf(). alterações essas que permanecem após a função terminar. Esses especificadores de formato têm a forma de um sinal de porcentagem (%) seguido por uma letra. A função printf() suporta mais de um parâmetro. O Módulo sobre Ponteiros. as funções recebem o endereço de memória da variável. Quando for necessário que printf() exiba um valor ou uma variável. ou até outras strings de caracteres. pode-se usar %f. será possível usar printf() para exibir os valores de cada variável. é preciso fornecer informações sobre o tipo da variável dentro do primeiro parâmetro. Além de especificar caracteres dentro do primeiro parâmetro. Portanto. No entanto. as funções podem alterar o valor armazenado na posição de memória específica (em outras palavras. variáveis. Da mesma forma para exibir um valor em ponto flutuante. para exibir um valor inteiro. o que for menor O mesmo que %g. que instruem printf() como imprimir os outros parâmetros. Para usar a chamada por referência. seu programa precisar usar Ponteiros. pense em um Ponteiro simplesmente como um endereço de memória.

O exemplo a seguir ilustra o uso dos dois especificadores. #include <stdio. int peso = 80.1. No entanto. Se usar %d em lugar de %u. valor). pois %i é um legado do passado. valor.h> void main(void) { int valor = 255. valor).2 ± Exibindo um Valor Inteiro Octal ou Hexadecimal Muitas vezes nos programas é preciso exibir um valor inteiro em seu formato octal (base 8) ou hexadecimal (base 16).3 ± Exibindo Valores do Tipo Unsigned Int Para exibir valores do tipo unsigned int com a função printf().1 ± Exibindo Valores do Tipo int Usando Printf() Para exibir valores do tipo int com printf(). valor. 1 + 2). O especificador de formato %o (letra "o".%s %u %x %X %% %p Exibe uma string Exibe um decimal sem sinal Exibe um número em hexadecimal com letras minúsculas Exibe um número em hexadecimal com letras maiúsculas Exibe um sinal de % Exibe um ponteiro 4. Veja a seguir um exemplo que utiliza estes especificadores de formato: #include <stdio. e os compiladores futuros talvez deixem de aceitá-lo. Da mesma forma. printf("%d mais %d igual a %d \n".h> void main(void) { int idade = 41.1. %d e %u. valor). deve-se usar o especificador de formato %u. 4. printf("O valor decimal %d em octal à %o \n".h> . } 4. printf("Idade do usuario: %d peso: %d altura: %d \n". 1. printf() tratará o valor especificado como tipo int.1. O programa a seguir usa o especificador de formato %d para exibir valores e variáveis do tipo int: #include <stdio. valor. printf("O valor decimal %d em hexadecimal à %X \n". provavelmente exibindo o valor incorreto. 2. %x e %X instruem printf() a exibir uma valor em hexadecimal. idade. } Uma observação importante é que muitos compiladores C tratam o especificador de formato %i como idêntico a %d. sendo que no primeiro caso em minúsculo e no segundo imprime os valores em maiúsculo. não zero) instrui printf() a exibir uma valor em octal. int altura = 182. usa-se o especificador de formato %d. altura). peso. para criar-se novos programas . printf("O valor decimal %d em hexadecimal à %x \n". use o especificador %d.

%d e %ld: #include <stdio. printf ("Um milhão é %d \n". preco). deve-se usar o especificador de formato %c.h> void main(void) { printf("A letra à %c \n". printf("O custo do item à %f \n".4 ± Exibindo Valores do Tipo Long Int Para exibir valores do tipo long int com a função printf(). deve-se usar o especificador de formato %ld. } 4. printf("Exibindo 42000 como unsigned %u \n". #include <stdio. um_milhao). um_milhao). printf("O imposto sobre a venda do item à %f \n".1.5 ± Exibindo Valores do Tipo Float Para exibir valores do tipo float com a função printf(). printf("A letra à %c \n". } 4. 65). printf() tratará o valor especificado como tipo int.06. A seguir um exemplo que usa %f para exibir valores em ponto flutuante. valor). printf("Exibindo 42000 como int %d \n". provavelmente exibindo o valor incorreto. } 4.1. printf ("Um milhão é %ld \n". deve-se usar o especificador de formato %f.h> void main(void) { float preco = 525.75.1. 'A').7 ± Exibindo Valores de Ponto Flutuante em um Formato Exponencial . preco * imposto_vendas). } 4. O exemplo a seguir ilustra o uso dos dois especificadores.6 ± Exibindo Valores do Tipo Char Para exibir valores do tipo char com a função printf(). #include <stdio.void main(void) { unsigned int valor = 42000. valor). float imposto_vendas = 0. Se usar %d em lugar de %ld.1. A seguir um exemplo que usa %c para exibir a letra A em sua tela.h> void main(void) { long int um_milhao = 1000000.

8 ± Exibindo Valores em Ponto Flutuante A função printf() também suporta os especificadores %g e %G para imprimir valores em ponto flutuante. 2 * pi * raio).00001234). 0.1234 resulta em %g \n". faculdade). printf("Exibir 0. 0. A seguir um exemplo que usa %s para exibir uma string de caracteres: #include <stdio. deve-se usar o especificador de formato %p. A seguir um exemplo que usa %p para exibir um endereço de memória.00001234 resulta em %g \n".0031. &valor). #include <stdio. Quando usa-se esses especificadores de formato.9 ± Exibindo uma String de Caracteres Para exibir uma string de caracteres com a função printf().10 ± Exibindo um Endereço de Ponteiro Para exibir um endereço de ponteiro com a função printf().h> void main(void) { printf("Exibir 0. #include <stdio.h> void main(void) { char faculdade[255] = "Universidade Estadual Paulista". printf("O endereço da variável valor é %p \n".1. 2 * pi * raio). printf("A área do círculo é %e \n". Veja o exemplo que ilustra o uso do especificador %g: #include <stdi o. } . deve-se usar o especificador de formato %e ou %E. } 4. dependendo da técnica que exibirá a saída no formato mais significativo para o usuário.1. printf("O nome da minha universidade é %s \n".1. printf() decide se deve usar o formato %f ou %e. A diferença entre os dois é que %E instrui printf() a usar uma letra E maiúscula na saída.1234). float raio = 2.h> void main(void) { float pi = 3. deve-se usar o especificador de formato %s.Para exibir um valor em ponto flutuante em um formato exponencial com a função printf(). } 4. } 4.14159.h> void main(void) { int valor. printf("A área do círculo é %E \n".

valor). #include <stdio. printf() usará o número de caracteres que printf() requer para exibir o valor corretamente. valor). } 4.11 . } valor). int pos_int = 5. printf ("%3d \n". printf() colocava espaços antes do valor a ser exibido.Precedendo um Valor com um Sinal de Adição ou de Subtração Em muitos programas é necessário que printf() exiba o sinal para os valores positivos e negativos.23. float pos_flt = 100.1. float neg_flt = -100. printf ("%4d \n". Se o valor a ser exibido requer mais caracteres do que o especificado. printf ("%2d \n".h> void main(void) { int neg_int = -5.Saída de Inteiros Preenchida com Zeros No item anterior.1.4.neg_int. mas é possível configurá-lo de tal maneira que ele exiba zeros antes do valor ou caracter que é necessário exibir. O exemplo abaixo ilustra o uso desta propriedade. printf ("%02d \n". No caso anterior.1.h> void main(void) { int valor = 5. O dígito que for colocado após o % especifica o número mínimo de caracteres que printf() usará para exibir um valor inteiro. printf() predecerá o valor com três espaços. neg_flt. valor). Para instruir printf() a exibir um sinal de um valor. printf ("%01d \n". Para instruir printf() a preencher um valor com zeros. O exemplo a seguir ilustra o uso do sinal de adição dentro do especificador de formato. valor). coloca-se um 0 (zero) imediatamente após o % no especificador de formato. foi visto como formatar uma saída instruindo printf() a exibir um determinado número de dígitos.13 . valor). Por exemplo. será possível instruir printf() a exibir um número mínimo de caracteres. valor). printf("Os valores em ponto flutuante são %+f %+f \n".12 ± Formatando um Valor Inteiro Usando o especificador de formato %d. Esses zeros são chamados de zeros de preenchimento. pos_flt). caso seja especificado %5d e o valor a ser exibido for 10. antes do número desejado de dígitos.23. printf ("%03d \n".h> void main(void) { int valor = 5. Observe que o valor especifica o número mínimo de caracteres que a saída consumirá. #include <stdio. pos_int). 4. simplesmente inclua um sinal de adição imediatamente após o % no especificador de formato. Veja um exemplo que ilustra este caso logo a seguir: #include <stdio. printf ("%1d \n". . printf("Os valores inteiros são %+d and %+d \n".

#include <stdio. } 4.15 ± Formatando um Valor em Ponto Flutuante No item 3. printf() permite formatar a saída em ponto flutuante. valor. } 4. valor). valor. Usando técnicas de formatação similares. printf("O valor decimal %d em hexadecimal é %#x \n".h> void main(void) { float valor = 1. valor). printf ("%12. por exemplo). valor). #include <stdio. por exemplo). Usando uma técnica similar.1f \n".1.23456. #include <stdio.5f \n".h> void main(void) { float valor = 1.3 e\n". valor). O exemplo abaixo ilustra esta técnica. Veja o exemplo abaixo que ilustra o uso do sinal #. coloca-se um sinal # imediatamente após o % no especificador de formato. printf("O valor decimal %d em hexadecimal é %#X \n". printf ("%12. valor). valor). } 4.16 ± Formatando a Saída Exponencial No item anterior foi visto como usar o especificador de formato %f para formatar valores em ponto flutuante.1. printf ("%8. valor). em muitos casos é necessário que se preceda os valores em octal com um zero (0777. O primeiro valor diz a printf() o número mínimo de caracteres a serem exibidos.1. O segundo valor diz a printf() o número de dígitos a serem exibidos à direita do ponto decimal. Para instruir printf() a preceder um valor octal ou hexadecimal com o prefixo apropriado.14 Exibindo um Prefixo Antes dos Valores Octais ou Decimais Em muitos programas que apresentam valores octais ou hexadecimais.1e \n".11 foi visto como formatar um valor inteiro colocando o número desejado de dígitos imediatamente após o % no especificador de formato %d. valor). pode-se instruir pintf() a exibir a saída em ponto flutuante em um formato exponencial. printf ("%8.1. e os hexadecimais com 0x (oxFF.17 ± Justificando à Esquerda a Saída de Printf() . Quando formata-se um valor em ponto flutuante especifica dois valores. printf ("%8.printf ("%04d \n".5e \n". valor). valor).1. printf ("%12.23456.h> void main(void) { int valor = 255. } 4. valor.3f \n". Veja o exemplo a seguir que ilustra este caso. printf("O valo r decimal %d em octal é %#o \n".

h> void main(void) { int primeiro_conta.h> void main(void) { int int_valor = 5. segundo_conta). A Linguagem C define vários caracteres de escape (referenciados no Módulo 2 item 2. float flt_valor = 3. Dependendo do programa. printf("Justificado à esquerda % -5d valor\n". Um exemplo é o uso do caracter de nova linha (\n) para avançar a saída para o início da próxima linha.1.19 ± Trabalhando com os Caracteres Escape de Printf() Quando trabalha-se com string de caracteres. printf("Linha 1 \nLinha2\nLinha 3\n").20 ± Determinando o Número de Caracteres que Printf() Exibiu Quando usa-se o especificador de formato %n. } 4. ou alimentação de linha. 4. printf("Justificado à direita %5d valor \n". tais como tabulação. Em tais casos. int_valor).18 ± Combinando os Especificadores de Formato de Printf() Muitas vezes por rapidez e para que o código torne-se mais enxuto pode-se aproveitar dois ou mais especificadores de formato de printf(). flt_valor).4. printf("Primeiro conta %d Segundo conta %d \n". int segundo_conta. simplesmente coloque cada um dos especificadores logo após o %. printf("Universidade%n Estadual Paulista%n \n". Veja um exemplo. int_valor).2f valor \n".2f valor \n". printf("Justificado à direita %7. flt_valor). printf() atribuirá à uma variável (passada por ponteiro) um contador do número de caracteres que printf() exibiu.1. int_valor). primeiro_conta. &segundo_conta). } 4.h> void main(void) { int int_valor = 5. algumas vezes é necessário que printf() justifique o texto à esquerda. printf("Justificado à esquerda com sinal % -+3d\n". printf() exibirá o texto justificado à direita.33.3) para facilitar para você a inclusão de caracteres especiais dentro de uma string. pode-se usar caracteres especiais. #include <stdio.Por padrão. #include <stdio. printf("Justificado à esquerda % -7. .&primeiro_conta. coloque um sinal de subtração (-) imediatamente após o % no especificador de formato. quando for exibido o texto usando os caracteres de formatação. retorno do carro. O exemplo a seguir ilustra o uso desta técnica de formatação.1. Para justificar o texto à esquerda. #include <stdio.

lista de argumentos). o.2 ± Função SCANF() A função scanf( ) é uma das funções de entrada de dados da Linguagem C. Se printf() encontrar um erro. O exemplo a seguir.} 4. Esses códigos são listados na tabela a seguir. Os especificadores de formato de entrada são precedidos por um sinal % e dizem à função scanf( ) qual tipo de dado deve ser lido em seguida. que são usadas para controlar a conversão da entrada. } 4. A cadeia de formato pode conter: . A cadeia de formato geralmente contém especificações de conversão. ou por l (letra ele) para indicar que um apontador para long aparece na lista de argumentos.21 ± Usando o Valor de Retorno de Printf() Usar o especificador de formato %n é um modo de garantir que printf() teve sucesso ao exibir sua saída. Semelhantemente. u e x podem ser precedidos por h para indicarem que um apontador para short ao invés de int aparece na lista de argumentos.1. os caracteres de conversão e. freqüentemente ela é usada para a entrada de números inteiros ou de ponto flutuante. if (result == EOF) fprintf(stderr. que pode ser usada para ler virtualmente qualquer tipo de dado inserido por meio do teclado. quando printf() termina. #include <stdio. usa o valor de retorno de printf() para garantir que printf() foi bem sucedido. f e g podem ser precedidos por l (letra ele) para indicarem que um apontador para double ao invés de float está na lista de argumentos. retornará a constante EOF (que como será visto no módulo sobre sistema de arquivo.h> void main(void) { int result. i. Código %c %d %i %u %e %f %g %o %s %x %p Significado Lê um único caractere Lê um decimal inteiro Lê um decimal inteiro (não pode ser octal ou hexadecimal) Lê um decimal sem sinal Lê um número em ponto flutuante com sinal opcional Lê um número em ponto flutuante com ponto opcional Lê um número em ponto flutuante com expoente opcional (double) Lê um número em base octal Lê uma string Lê um número em base hexadecimal Lê um ponteiro Os caracteres de conversão d. indica o fim de um arquivo). Além disso. ele retorna o número total de caracteres que escreveu. "Erro dentro de printf \n"). result = printf("Universidade Estadual Paulista \n"). A forma geral da função scanf( ) é: scanf (³string de controle´.

Por exemplo. tabulações e novas linhas.b.2. &c). } Nesse caso. então. leia outro inteiro. um caractere * opcional de supressão de atribuição. nome). tornando o cód mais legível.4 ± Formatando a Entrada de Scanf() Os itens de dados de entrada devem ser separados por espaços. 4. scanf("%d. consistindo no caractere %. y y caracteres comuns (não %). ³%d.Lendo Valores em Variáveis Todas as variáveis usadas para receber valores por meio da função scanf() deverão ser passadas pelos seus endereços. ponto-e-vírgula e semelhantes não contam como operadores. } 4. deve-se usar o seguinte comando: #include <stdio.2 . igo #include <stdio. Então. para ler um inteiro em uma variável count.%d". Pode-se usar esta técnica para separa os especificadores de formato. scanf("%d ". &b). um número opcional especificando um tamanho máximo do campo. aceitará uma entrada dos .2.h> void main(void) { char nome[40]. que devem combinar com o próximo caractere não espaço do fluxo de entrada.h> void main(void) { int a. e um caractere de conversão. tabulações ou novas linhas.h> void main(void) { int count.y y espaços. um h ou l opcional indicando o tamanho do destino. Se o caractere especificado não é encontrado. scanf("%s". &a.2. nome já é um endereço e não precisa ser precedido pelo operador &. y y especificações de conversão.%d´ faz com que a função scanf() leia um inteiro.1 ± Usando Caracteres em Scanf() que Serão Descartados Um caractere que não seja um espaço em branco faz com que a função scanf( ) leia e descarte o caractere correspondente. &r. finalmente.2. } 4. leia uma vírgula (que será descartada) e. poderia usar a seguinte chamada à função scanf(): #include <stdio. Por exemplo. &count). Pontuações como vírgula. para ler uma string no vetor de caracteres nome.3 ± Lendo String de Caracteres As strings serão lidas em vetores (cadeias de caracteres) e o nome do vetor é o endereço do primeiro elemento do vetor. que serão ignorados. 4. a função scanf( ) terminará. Isso significa que scanf(³%d%d´.

2. mas suprimirá a sua atribuição. } A cláusula else é opcional. caso contrário o bloco que forma o destino de else será executado (desde que exista else).Estruturas de Fluxo de Controle 5. colocará o valor 10 em x descartando o sinal de divisão. scanf(³%c%c%c´. &x. Assim. Isto permite ao programador o desenvolvimento de programas complexos. retornará com o caractere ³x´ em a. você pode escrever: #include <stdio. &c). Esse modificador é um número inteiro colocado entre o sinal % e o código de comando de formato. quando da leitura de um único caractere. que limita o número de caracteres lidos para qualquer campo.font-fa Módulo 5 . um espaço em b e o caractere ³y´ em c. mas falhará com 10. e dará a y o valor 20.20. os códigos de formato da função scanf( ) devem ser correspondidos na ordem com as variáveis que estão recebendo a entrada na lista de argumento. Por exemplo. <span lang=EN-US style='font-size:10. } else { comandos. para ler não mais que 20 caracteres em str. esses últimos são lidos como qualquer outro caractere. &b. com uma entrada de ³x y´. o bloco que forma o destino de if será executado.0pt. 4. scanf(³%d%*c%d´. Como na função printf( ). Ainda que espaços. Se condição for verdadeira (qualquer coisa diferente de 0).mso-bidi-font-size:12.5 ± Determinando o Número Máximo de Caracteres a ser Lido Os comandos de formato podem especificar um campo modificador de comprimento máximo. . dando-se a entrada 10/20. tabulações e novas linhas sejam usados como separadores de campos. &y). A forma geral da declaração if é: if (condição) { comandos.0pt. Um * colocado depois do % e antes do código de formato lerá um dado de um tipo especificado.h> void main(void) { char str[40].1 ± A Declaração If A declaração if é usada quando é necessário testar em um programa duas ou mais condições. Por exemplo.números 10 20. &a.

&valor). y y Hexadecimal para Decimal. O comando if será demonstrado através de um programa simples que converte bases numéricas.2 ± O Encadeamento If-Else-If . printf (³%d em hexadecimal e: %x´. &valor). #include <stdio.1. O programa seguinte demonstra este princípio fundamental: #include <stdio. O programa permitirá que primeiro seja selecionado o tipo de conversão a partir de um menu e. printf (³2: hexadecimal para decimal \n´). valor. então a instrução ou bloco de instruções do else será executada. Com esta declaração podemos acrescentar ao teste condicional várias opções de escolha. int valor. } } 5. else printf (³O número é positivo ou nulo´). valor. valor). &i). Este programa será capaz de apresentar as seguintes conversões: y y Decimal para Hexadecimal. scanf (³%d´. scanf (³%x´. printf (³Informe um número: ´). } 5. printf (³Converter: \n´). scanf (³%d´. Se for falsa. } if (opcao == 2) { printf (³\nInforme o valor em hexadecimal: ´). if (i < 0) printf (³O número é negativo´). printf (³1: decimal para hexadecimal \n´). pode ser um comando simples ou um bloco de comandos. &opcao). nunca os dois. O destino dos dois.h> void main() { int i.Lembre-se que somente o código associado a if ou o código associado a else será executado.1 . if e else. valor).h> void main() { int opcao. printf (³%x em decimal e: %d´.Usando a Declaração Else É possível associar um else com qualquer if. if (opcao == 1) { printf (³\nInforme o valor em decimal: ´). solicitará o número a ser convertido. Se a expressão condicional associada a if é verdadeira.1. então. scanf (³%d´. printf (³\nInforme sua opção: ´). a instrução ou bloco de instruções associada será executada.

Ainda que não haja grande significado neste caso. então o else final será executado. scanf (³%d´. printf (³2: hexadecimal para decimal \n´). &opcao). Pode-se usar o encadeamento if-else-if para implementar o programa de conversão de base numérica desenvolvido anteriormente. e o resto do encadeamento é ignorado. int valor. } else { comandos. Se nenhuma das condições for verdadeira. o bloco associado a ela será executado. /* Programa de conversão de base numérica ± if-else-if decimal ---> hexadecimal hexadecimal ---> decimal */ #include <stdio. printf (³Converter: \n´). então nenhuma ação será realizada. printf (³1: decimal para hexadecimal \n´). O seguinte exemplo ilustra esta construção: if (condição) { comandos.h> void main() { int opcao. Na versão original. Assim que uma condição verdadeira é encontrada. if (opcao == 1) { printf (³ \nInforme o valor em decimal: ´). } else if (condição) { comandos.Uma construção comum em programação é o encadeamento if-else-if. printf (³\nInforme sua opção: ´). o resto das declarações é ignorado. a avaliação redundante de todos os ifs não é muito eficiente ou elegante. } else if (condição) { comandos. Se o else final não estiver presente e todas as outras condições forem falsas. mesmo se uma das declarações anteriores tivesse êxito. } As expressões condicionais serão avaliadas de cima para baixo. tão logo uma declaração if é satisfeita. O seguinte programa resolve este problema. cada declaração if era avaliada sucessivamente. Nessa versão de encadeamento if-else-if. .

&valor). valor. valor). scanf (³%x´. uma declaração if é usada para controlar o segundo número. são os ifs aninhados. a condição controlando o if é falsa e a instrução else é executada. valor. o else é ligado ao if mais próximo dentro do mesmo bloco de código que já não tenha uma declaração else associada a ele. printf (³%x em decimal e: % d´. if (b) printf (³%d \n´. } Essa abordagem funciona porque. Por exemplo. &a. scanf (³%d%d´.4 ± Ifs Aninhados Um dos muitos aspectos que causam confusão na declaração if. Não é necessário escrever uma declaração if como esta if (b != 0) printf (³%d \n´. a/b). Caso contrário. o tipo de expressão não precisa se restringir àquelas envolvendo operadores relacionais e lógicos. Considere este exemplo: if (x) if (y) printf (³1´). porque é redundante. Só é requerido que a expressão resulte em um valor zero ou não zero. a expressão é verdadeira (não zero) e a divisão é realizada. printf (³Informe dois números: ´). b. iniciantes na linguagem C confundem-se pelo fato de que qualquer expressão válida na linguagem C pode ser usada para controla a declaração if. este programa lê dois inteiros do teclado e mostra o quociente. Em C. . &valor). Para evitar um erro de divisão por zero. } else if (opcao == 2) { printf (³ \nInforme o valor em hexadecimal: ´). valor).scanf (³%d´. Um if aninhado é uma declaração if que é objeto de um if ou um else. se b for zero. &b). a/b). 5. } else { printf (³ \nA opção escolhida é inválida. Os ifs aninhados são incômodos por poderem dificultar saber qual else está associado a qual if.3 ± A Expressão Condicional Algumas vezes. #include <stdio. Isto é. Neste caso o else é associado à declaração if(y).h> void main() { int a. em qualquer linguagem de programação. else printf (³2´). else printf (³Não posso dividir por zero \n´).´) } } 5.1. printf (³%d em hexadecimal e: %x´.1.

Considere o seguinte laço for. 0 ou 1. que é. A seção valor_inicial atribui à variável de controle o valor inicial da variável. O comando for é geralmente chamado de laço for. deve-se usar chaves para sobrepor a sua associação normal.2 ± A Declaração For Uma operação que vários programas executarão comumente é repetir um conjunto de comandos um número específico de vezes. for (contador = 1. Para compreender melhor o processamento do laço for execute em seu compilador o seguinte programa: #include <stdio. A seção condição_final normalmente testa o valor da variável de controle para determinar se o programa executou os comandos um número desejado de vezes. a Linguagem C fornece o comando for. contador++) printf("%d \n". O else agora está associado ao if(x).h> void main(void) { int contador. O comando for contém quatro seções. Para auxiliar programas a repetir um ou mais comandos um certo número de vezes. pode-se querer calcular as notas dos exames de 30 alunos ou soar três vezes o alto-falante interno do computador. contador <= 10. Por exemplo. contador). contador++) printf("%d ". valor_incremento) comando. } . contador <= 5. printf("\nIniciando o segundo laco \n"). contador <= 10. condição_final. contador). na maioria das vezes. Quando um programa repetir comandos um número específico de vezes. for(valor_inicial. contador). já que ele não é parte do bloco de código do if(y). normalmente usará uma variável de controle. que contará o número de vezes que for executado os comandos. contador++) printf("%d ". for (contador = 100. contador <= 5. for (contador = 1. contador). A seção valor_incremento normalmente adiciona o valor 1 para a variável de controle toda a vez que os comandos são executados. 5. ele exibirá os números de 1 a 10 na sua tela: for(contador=1. como mostrado aqui: if (x) { if (y) printf (³1´). Finalmente a quarta seção do comando for é o comando ou comandos especificados. printf("\nIniciando o terceiro laco \n"). } else printf (³2´).Para fazer com que else seja associado à declaração if(x). contador++) printf("%d ".

conta <1000. 5. /* não faz nada */ Quando se coloca um laço nulo nos programas. Da mesma forma. Este é o chamado laço infinito: for (. ) /*comando*/ 5. conta++) printf("%d". o laço conterá o seguinte: for(. O teste repetido do laço consome tempo do processador. você poderá aumentar a condição final: for(contador=1. contador <= 100. de modo que o laço não é executado.Como pode-se verificar. o comando for à seguir ficará em execução perpetuamente. contador <= 10000. e. Quando o comando for testa o valor. se já foi atribuido o valor 0 à variável conta. será visto que o programa inicialmente atribui à variável de controle do laço o valor 100. o laço for a seguir omite as seções de inicialização e de incremento: for(. contador++) . testará e incrementará a variável de controle até que a variável de controle atenda a condição final. conta++). O segundo laço exibe os valores de 1 até 10. Depois. pode-se pular a seção de inicialização do laço. quando os programadores queriam que seus programas fizessem uma breve pausa. Por exemplo. conta). Por exemplo. No entanto. algumas vezes pode não ser necessário o uso de cada uma das seções do comando for. se for omitido uma das seções do laço for. o seguinte laço for não faz nada 100 vezes: for(contador=1. contador++) .1 ± Partes do Comando For são Opcionais Como foi visto no item anterior. teste. repetidamente. incremento) Dependendo do programa. /* não faz nada */ . eles colocavam um laço nulo ou "não faz nada" em seus programas. Por exemplo.2. . o que faz o programa retardar. o laço for atende imediatamente à condição final.2.2 ± Compreendendo um Laço Null No passado. precisa-se incluir o ponto-e-vírgula correspondente. a Linguagem C efetuará a inicialização do laço. para exibir os números de 0 até 999. ) printf("%d". um teste e um incremento: for(inicialização. O terceiro laço não exibe nenhum valor. o laço for usa três seções dentro do comando for: uma inicialização. Se o programa precisar de um retardo maior. o primeiro laço for exibe os números de 1 até 5. conta < 1000. . Se for examinado com atenção. depois. talvez para exibir alguma mensagem.

Caso contrário. de modo que o laço não termina. é necessário que uma variável contenha muitos valores. Esses laços intermináveis são chamados laços infinitos. pode pressionar -se Ctrl+C para finalizar o programa. tais como o laço nulo. o laço decrementa o valor para -1. Quando o programa entra em um laço infinito.2 ± Declarando uma Matriz Para declarar uma matriz. incrementa o valor para 0. float ou double). Na maioria dos casos. OS/2 ou Unix. Todo valor que você atribui a uma matriz precisa ser do mesmo tipo que o tipo da matriz. } /*causa do erro*/ Como pode-se verificar. Como resultado. a variável nota pode controlar as notas obtidas por 100 alunos em um exame. após o uso de matrizes. Especificamente. precisa-se garantir que o laço atenderá à sua condição final. Uma matriz é uma estrutura de dados que pode armazenar múltiplos valores do mesmo tipo. tal como o Windows. poderá causar problemas. os laços infinitos ocorrem como resultado de erro na programação. Por exemplo. Segundo. Primeiro. Para especificar o tamanho de uma . i++) { printf("%d". se o programa estiver rodando em um ambiente multitarefa. bem como o tamanho da matriz. Por exemplo. a duração do retardo diferirá simplesmente devido à diferença de velocidade entre os diferentes microprocessadores. Com o tempo. se o programa estiver rodando em um computador 286. ficará claro como é simples o uso de matrizes. considere o seguinte laço: for(i = 0. i <100.2. Por exemplo. 386 ou 486. Da mesma maneira. e. o segundo comando do laço decrementa o valor da variável de controle i. O programa a seguir ilustra um laço infinito: #include < stdio.h> void main(void) <span lang=EN-US style=' Módulo 6 ± Matrizes na Linguagem C 6. o valor nunca atinge 100. Neste módulo será mostrado como criar e trabalhar com matrizes em programas.Usar as técnicas de retardo. depois. i). 6. a variável salários poderia controlar os salários de cada funcionário em uma companhia. precisa-se especificar o tipo desejado (tal como int. o laço continuará sua execução para sempre. resultado = valor * --i. os laços "não fazem nada" consomem tempo que o processador poderia estar gastando fazendo trabalho importante em outro programa.1 ± Compreendendo as Matrizes Muitas vezes em programas.3 ± Compreendendo o Laço Infinito Quando são usados laços for. 5. pode-se criar uma matriz que possa conter 100 valores do tipo int e uma Segunda matriz com 25 valores do tipo float.

Dadas as matrizes anteriores. De forma similar. Por exemplo. coloca-se o número de valores que a matriz pode armazenar dentro de colchetes após o nome da matriz. os comandos a seguir atribuem valores ao último elemento de cada matriz: notas[99] = 65. salarios[49] = 250000. o último elemento da matriz ocorre uma posição antes do tamanho da matriz. float salar[100]. uma matriz de 100 elementos do tipo float irá requerer 100*4 bytes ou 400 bytes. sizeof(string)). salarios[0] = 35000. sizeof(notas)). Por exemplo. sizeof(salar)).Inicializando uma Matriz Muitos programas em Linguagem C inicializam as strings de caracteres como segue: . printf("Memoria para conter char s tring[100] %d bytes \n". char string[100]. usa o operador sizeof para exibir a quantidade de memória que os diferentes tipos de matrizes requerem: #include <stdio. printf("Memoria para conter int notas[100] %d bytes \n". printf("Memoria para conter float salar[100] %d bytes \n". Por outro lado.3 ± Compreendendo os Requisitos de Armazenamento de uma Matriz Ao declarar uma matriz. Como o primeiro elemento da matriz inicia no deslocamento 0. O programa abaixo. A quantidade real de memória que o compilador aloca depende do tipo da matriz. que pode armazenar 100 notas de exame do tipo int: int notas [100].h> void main(void) { int notas[100]. que contém 50 salários: float salarios [50].matriz.4 . o compilador aloca memória suficiente para conter o número de valores especificado. Quando uma matriz é declarada. os comandos a seguir atribuem os valores 80 e 35000 aos primeiros elementos da matriz: notas[0] = 80. Por exemplo. a Linguagem C aloca memória suficiente para conter todos os elementos. O primeiro item está na posição 0. } 6. 6. nas matrizes notas e salarios. uma matriz de 100 elementos do tipo int normalmente irá requerer 100*2 ou 200 bytes de memória. a declaração à seguir cria uma matriz chamada notas. a seguinte declaração cria uma matriz do tipo float.

85 e 80: int notas[5] = {80. notas[0]). inicializa a matriz notas e depois usa printf para exibir os valores dos elementos: #include <stdio.Ilha Solteira".0. 85. 70. 90. Quando declara-se matrizes de outros tipos.char titulo[] = "UNESP . o compilador alocará uma matriz de 64 bytes.6 ± Percorrendo em um Laço Elementos da Matriz Quando se referencia muitos elementos de uma matriz. 23000. Quando atribui-se valores iniciais a uma matriz. O comando a seguir. atribui quatro valores de ponto flutuante a uma matriz que pode armazenar 64 valores: float salar[64] = {25000.5 ± Acessando Elementos da Matriz Os valores armazenados em uma matriz são chamados elementos de matriz. 44000. Dependendo do compilador. 90. o tamanho da matriz é igual ao número de valores atribuídos. os programas podem usar uma variável para referenciar os elementos da . a seguinte declaração de matriz cria uma matriz grande o suficiente para conter três valores do tipo long: long planetas[] = {1234567L. printf("notas[3] %d \n". notas[1]). ele pode atribuir 0 aos elementos aos quais o programa não atribui valores explícitos. No segundo. Além disso.0.0. notas[4]). No entanto. No primeiro caso. o comando a seguir inicializa a matriz de inteiros notas com os valores 80. se não for especificado um tamanho de matriz. } 6. notas[3]).h> void main(void) { int notas[5] = {80. 654321L. 70. 85. o compilador alocará memória suficiente para conter somente os valores que você especificar. 70. printf("Valores da Matriz \n"). A maioria dos compiladores também inicializará as posições de bytes restantes com NULL. O programa a seguir. printf("notas[2] %d \n". pode inicializar matrizes da mesma forma. 80}. você especifica o nome da matriz e o elemento que deseja. char secao[64] = "Matrizes". o compilador alocará 22 bytes para armazenar a string. 90. Para acessar um elemento da matriz. inicializando os primeiro 8 caracteres com as letras "Matrizes" e o caracter NULL. 6. Por exemplo. 80}. não se deve assumir que o compilador inicializará os outros elementos.0}. no entanto. como regra. No caso anterior. 1221311L}. printf("notas[0] %d \n". é necessário delimitar os valores por abre e fecha chaves ( {} ). Por exemplo. Como uma alternativa. 32000. printf("notas[1] %d \n". printf("notas[4] %d \n". notas[2]). especificar números para cada elemento da matriz individualmente pode ser demorado e tedioso.

90. 90. for (i = 0. O programa a seguir declara uma matriz com base na constante TAM_MATRIZ. 85. 80}. 80}. 70. valores[i]). } Se mais tarde for necessário alterar o tamanho da matriz.h> void main(void) { int notas[5] = {80. } 6. int i. i < 5. Por exemplo. poderá alterar o valor atribuído à constante TAM_MATRIZ para que o programa automaticamente atualize os laços que controlam a matriz como o tamanho da matriz. assumindo que a variável i contenha o valor 2. matriz[i] = 80. i. quando os programas trabalham com matrizes. mas também usa a constante como a condição final para o laço for: #include <stdio. i < TAM_MATRIZ.7 ± Usando Constantes Para Definir as Matrizes Como visto. o programa não somente usa a constante para declarar a matriz. i. . 70. 80}. O código a seguir usa a variável i e um laço for para exibir os elementos da matriz notas: #include <stdio. valores[i]). Por exemplo.matriz. printf("Valores da Matriz \n"). for (i = 0. Como se vê. ma s também o laço for. notas[i]). 85. 85. for (i = 0. i++) printf("valores[%d] %d \n". i. o programa a seguir declara uma matriz de cinco valores e depois usa um laço for para exibir os valores da matriz: #include <stdio. int i. i < 5. o comando a seguir atribuiria o valor 80 a matriz[2]: i = 2. 70. maiores as chances de errar. suponha que seja necessário alterar o código anterior de tal forma que ele suporte 10 valores. i++) printf("valores[%d] %d \n".h> #define TAM_MATRIZ 5 void main(void) { int valores[TAM_MATRIZ] = {80. int i. Quanto mais alterações forem feitas em um programa. Precisará alterar não somente a declaração da matriz. 90. i++) printf("notas[%d] %d \n". é necessário especificar o tamanho da matriz. } Por exemplo.h> void main(void) { int valores[5] = {80.

80. não é necessário declarar o tamanho da matriz. 9. 100. Por exemplo. O programa a seguir passa três matrizes diferentes (de diferentes tamanhos) para a função exibe_valores: #include <stdio. } Quando uma função recebe uma matriz como parâmetro. for (i = 0. o programa não precisa especificar o tamanho da matriz na declaração do parâmetro. valores[i]). int conta[10] = {1. 7. exibe_matriz(notas. os colchetes após o nome da variável valor informam o compilador de que o parâmetro é uma matriz. 90.8 ± Passando uma Matriz a uma Função Quando declara-se uma função que trabalha com um parâmetro matriz. i++) printf("%d \n". 5). como mostrado a seguir: #include <stdio. 90}. 5.num_de_elementos). 2.9 ± Revisitando as Matrizes Como Funções No item anterior. 4. 100. o programa passa para a função tanto a matriz como o número de elementos que a matriz contém. 90. pode-se especificar somente o abre e fecha colchetes. No caso da função exibe_valores. foi visto que ao declarar o parâmetro formal para uma matriz. Em vez disso. for (i = 0. } void main(void) { int notas[5] = {70. i ++) printf("%d \n".h> void exibe_matriz(int valores[]. 90}. 8. Módulo 7 ± Ponteiros . int num_de_elementos) { int i. valores[i]). precisa informar o compilador. 6.6. int num_de_elementos) { int i. 10}. i < num_de_elementos.h> void exibe_matriz(int valores[]. Como pode-se ver. 3. o compilador não se preocupa com o tamanho da matriz que o programa passa para a função. printf("Prestes a exibir %d valores \n". Sabendo que o parâmetro é uma matriz. 6. } void main(void) { int notas[5] = {70. i < num_de_elementos. o seguinte programa usa a função exibe_matriz para exibir os valores em uma matriz. 80.

Quando os programas trabalham com matrizes (e strings). } 7. o compilador C passa um ponteiro. printf("O endereço de conta à %x \n". Da mesma forma. Um ponteiro é uma variável ou um valor que contem um endereço. printf("O endereço da matriz salarios à %x \n". &conta). o compilador passa o endereço inicial da matriz. O programa a seguir exibe o endereço inicial de várias matrizes diferentes: #include <stdio.h> void main(void) { int conta[10]. &salario). distancia).4 ± Aplicando o Operador de Endereço (&) a uma Matriz . salarios). float salario = 40000. o programa a seguir usa o operador de endereço para exibir o endereço de várias variáveis diferentes: #include <stdio. printf("O endereço de distancia à %x \n".7. quando um programa passa uma matriz para uma função. float salarios[5].1 ± Ponteiros como Endereços Como já foi visto. 7.0. o programa deve passar para a função um ponteiro para o endereço de memória da variável. Quando se passa matrizes ou string para as funções. conta). printf("O endereço da matriz conta à %x \n". long distancia[10].h> void main(void) { int conta = 1. printf("O endereço da matriz distancia à %x \n". Quando os programas precisarem determinar o endereço de uma variável. A Linguagem C utiliza muito os ponteiros. Os programas referenciam cada posição na memória usando um endereço exclusivo. long distancia = 1234567L.3 ± Como a Linguagem C trata Matrizes como Ponteiros Já foi visto anteriormente que um compilador C trata as matrizes como ponteiros. } 7.2 ± Determinando o Endereço de uma Variável Um ponteiro é um endereço de uma posição na memória. deverão usar o operador de endereço da Linguagem C ³&´. printf("O endereço de salario à %x \n". Por exemplo. Por exemplo. quando uma função precisa alterar o valor de um parâmetro. uma variável é o nome de uma posição na memória que pode armazenar um valor de um determinado tipo. o programa trabalha com um ponteiro para o primeiro elemento da matriz. &distancia).

} 7. os programas precisam declarar variáveis ponteiros. &conta). realmente atribui um endereço.6 ± Desreferenciando um Ponteiro . Assumindo que anteriormente tenha-se declarado int conta.h> void main(void) { int *iptr. juntamente com o endereço de conta: #include <stdio. Para armazenar ponteiros.h> void main(void) { int conta[10]. Quando atribui-se um valor a um ponteiro. &conta). o comando a seguir atribui o endereço da variável conta ao ponteiro iptr: iptr = &conta. precisa-se atribuir um valor a uma variável ponteiro antes de poder usar o ponteiro dentro do programa. Para declarar um ponteiro. salarios. /* Atribui o endereço de conta a iptr */ O programa a seguir declara a variável ponteiro iptr e atribui ao ponteiro o endereço da variável conta. seguido pelo ponteiro que o operador de endereço retorna: #include <stdio. printf("O endereço da matriz conta à %x &conta à %x \n". float. /* Declara variavel ponteiro */ iptr = &conta. printf("O endereço da matriz distancias à %x &distancias à %x\n". O programa então exibe o valor da variável ponteiro. } 7. aplicar o operador de endereço a uma matriz é redundante. a Linguagem C retornará o endereço inicial da matriz. &distancias). conta. conta. ponteiros são usados com muita freqüência. o comando a seguir declara um ponteiro para um valor do tipo int: int *iptr. char. O programa a seguir exibe o endereço inicial de uma matriz.Se o operador de endereço for aplicado a uma matriz.) e um asterisco (*) antes do nome da variável. printf("Valor de iptr %x Valor de conta %d Endereço de conta %x\n". Como qualquer variável. etc. &salarios). Portanto. printf("O endereço da matriz salarios à %x &conta à %x \n". precisa-se especificar o tipo do valor ao qual o ponteiro aponta (tal como int. long distancias[10]. Por exemplo.5 ± Declarando Variáveis Ponteiros À medida que os programas tornarem-se mais complexos. iptr. distancias. float salarios[5]. int conta = 1.

contador). O programa a seguir usa os ponteiros para dois parâmetros do tipo int para permutar os valores das variáveis. como mostrado aqui: #include <stdio.Desreferenciar um ponteiro é o processo de acessar o valor de uma posição de memória específica. 7. Por exemplo. Finalmente.h> void troca_valores(int *a. /* Armazena temporariamente o valor */ /* apontado por a */ *a = *b. iptr. deverá passar para a função um ponteiro para um parâmetro. *iptr). O programa depois exibe o valor do ponteiro e o valor armazenado na posição apontada pelo ponteiro (o valor contador). /* Atribui o valor de a a b */ . } /* Altera o valor na memória */ printf("Valor de contador %d \n". o comando a seguir atribui o valor apontado pela variável iptr para a variável conta: conta = *iptr. *iptr = 25. usa-se o operador asterisco de indireção (*).h> void main(void) { int contador = 10. o comando a seguir atribui o valor 7 à posição de memória apontada por iptr: *iptr = 7.7 ± Usando Valores de Ponteiro O programa a seguir atribui ao ponteiro int iptr o endereço da variável conta. como mostrado a seguir: #include <stdio. 7. Quando for necessário alterar o valor de um parâmetro. O programa então modifica o valor apontado pelo ponteiro. int *iptr. /* Atribui o endereço */ printf("Endereço em iptr %x Valor em *iptr %d \n". Da mesma forma. int *b) { int temp. *iptr).8 ± Ponteiros com Parâmetros de Função O Módulo de Funções examina em detalhes o processo de passar parâmetros para as funções. temp = *a. o comando printf a seguir exibe o valor apontado pelo ponteiro inteiro iptr: printf(³O valor apontado po iptr é %d \n´. /* Atribui o valor de b a a */ *b = temp. Para desreferenciar o valor de um ponteiro. /* Declara valor do ponteiro */ iptr = &contador.

int *iptr. o endereço resultante será 1001. 4. Se somar-se o valor 1 a um ponteiro.h> void main(void) { int valores[5] = {1. contador++) { printf("%d \n". o ponteiro apontará para a posição de memória de cinco posições adiante do endereço atual. } Como pode ser visto. um. dois) . &dois). int contador. iptr = valores. poderia se esperar que o resultado fosse 1001. dentro da função.Percorrendo uma String usando um Ponteiro . dois = 2.10 ± Incrementando e Decrementando um Ponteiro Uma das operações mais comuns com ponteiros é o incremento e o decremento do valor de um ponteiro para apontar para a próxima posição ou para a posição anterior na memória. O programa depois incrementa o valor do ponteiro para exibir os cinco elementos que a matriz contém: #include <stdio. Se fosse somado 1 ao ponteiro. 2. Por exemplo.11 . Se fosse somado 1 a um ponteiro do tipo int (que requer dois bytes na memória). um ponteiro é um valor que aponta para uma posição de memória específica. Se somar-se 5 ao valor de um ponteiro. os programas poderão subtrair valores ou somar e subtrair dois ponteiros. o endereço resultante será 1002. O programa passa o endereço de cada variável para a função usando o operador de endereço (&). contador < 5. troca_valores(&um. os comandos desreferenciam os ponteiros usando o operador de indireção (*). Nos termos mais simples possíveis. assuma que um ponteiro contenha o endereço 1000. printf("um contém %d dois contém %d \n". Além de somar valores aos ponteiros. Por exemplo. a aritmética de ponteiro não é tão simples quanto parece.} void main(void) { int um = 1. 7. iptr++. o ponteiro apontará para a próxima posição de memória. se fosse somado 1 a um ponteiro do tipo char (que contém 1000).9 ± A Aritmética de Ponteiros Um ponteiro é um endereço que aponta para um valor de um determinado tipo na memória. } } 7. for (contador = 0. No entanto. 3. o endereço resultante depende do tipo de ponteiro. O programa a seguir atribui o endereço inicial de uma matriz de valores inteiros ao ponteiro iptr. 5}. No entanto. 7. *iptr). Quando for efetuada a aritmética de ponteiro é necessário ter em mente o tipo de ponteiro.

h> #include <ctype. 7.h> char *string_maiusc(char *string) { char *ender_inicial.12 . Em seguida. como mostrado aqui: FILE *fopen(const char *nomecaminho.13 ± Criando uma Função que retorna um Ponteiro O programa a seguir cria uma função chamada string_maiusc que converte todos os caracteres de uma string para maiúsculas e depois retorna um ponteiro para uma string: #include <stdio.Funções que retornam Ponteiros O valor que uma função retorna é sempre do tipo declarado no protótipo ou cabeçalho da função. as funções podem declarar ponteiros para os valores. printf("%s \n".Uma Matriz de Ponteiros . a função simplesmente percorre os caracteres da string até encontrar o caractere NULL. char *string. } void main(void) { exibe_string("Unesp Ilha Solteira"). Usando o ponteiro. printf("%s \n". *temp.h> void exibe_string(char *string) { while (*string) putchar(*string++). string_maiusc("Matrizes e Ponteiros")). while (*string) *(temp++) = toupper(*string++). return(ender_inicial). ender_inicial = temp = string. Por exemplo. O programa a seguir usa a função exibe_string para exibir uma string de caracteres usando um ponteiro: #include <stdio. que a maioria das funções da Linguagem C usam para abrir um canal de arquivo. } void main(void) { char *titulo = "UNESP Ilha Solteira".14 . Além de retornar esses tipos básicos. 7.Uma string é uma matriz de caracteres terminada pó NULL. retorna um ponteiro para uma estrutura do tipo FILE. string). } 7. string = string_m aiusc(titulo). } Como pode ser visto. const char *modo). Para exibir o caractere. a função incrementa o ponteiro para apontar para o próximo caractere na string. a função fopen. a função exibe_string primeiro desreferencia o endereço do ponteiro (obtendo o caractere). a função exibe_string declara a variável string como um ponteiro.

³Quarta´.h> void main(void) { char *diasuteis[] = {"Segunda". ³Segunda´. "Quarta". *dia_util++). Como exemplo. ³Quinta´. ³Sexta´. "Sexta". "Sexta". a declaração a seguir cria uma matriz chamada dias que contém ponteiros para string de caracteres: char *dias[7]= {³Domingo´.Percorrendo em um Laço uma Matriz de Strings de Caracteres Ao criar uma matriz de string de caracteres. "Terça". O programa a seguir percorre em um laço a matriz dias. } . Mais comumente serão usadas matrizes para conter strings de caracteres. "Quinta". também pode-se criar matrizes de ponteiros. 7.16 ± Usando um Ponteiro para um Ponteiro para String de Caracteres A declaração a seguir cria um ponteiro para uma string de caracteres: char **dia_útil_ptr. "S bado"}. "TerÁa". ³Sábado´}. ³Terça´. Se for examinado o tipo da matriz da direita para a esquerda. a Linguagem C armazena os ponteiros para cada string dentro dos elementos da matriz. i. i < 7. dia_util = diasuteis.Assim como pode-se criar funções que retornam ponteiros. i++) printf("dias[%d] contÃm %s \n". "" }. Se combinar o nome do tipo char que precede o nome da variável. que contém ponteiros para strings que contém os nomes dos dias da semana. será visto que a matriz contém sete elementos. a declaração se tornará uma matriz de ponteiros para strings de caractere. int i.15 . "Segunda". como mostrado aqui: #include <stdio. O asterisco antes do nome da variável especifica um ponteiro. } 7. for (i = 0. "Quarta". O programa a seguir usa um ponteiro para um ponteiro para string de caracteres para exibir o conteúdo da matriz diasuteis: #include <stdio. while (*dia_util) printf("%s \n". "Quinta".h> void main(void) { char *dias[7] = {"Domingo". dias[i]). char **dia_util.

em vez de uma matriz. Nesses casos. como mostrado a seguir: char *titulo = ³Unesp Ilha Solteira´. como mostrado aqui: void *ponteiro_memoria. As seguintes declarações criam ponteiros para funções: int (*min)(). Observe o uso dos parênteses entre os nomes das variáveis. atribuindo à variável titulo um ponteiro para o primeiro caractere. as declarações serviriam como protótipos de função para as funções que retornam ponteiros para um tipo específico. os programas poderão criar um ponteiro para o tipo void. Como o compilador C automaticamente aloca a memória necessária e depois trabalha com um ponteiro para a memória. O uso mais comum dos ponteiros para funções é permitir que os programas passem uma função como um parâmetro para outra função. os programas podem usar um ponteiro de string de caracteres. Quando se declara uma matriz com colchetes vazios.Quando o programa inicia. 7. 7. Além disso. int *max(). e. deve-se começar com a declaração mais interna que aparece dentro dos parênteses.18 ± O Ponteiro do tipo Void Ao declarar uma variável ponteiro. int (*max)(). como mostrado aqui: int *min(). no entanto. Em vez disso. Quanto se faz isso. Se os parênteses fossem removidos. os programas não manipularão o valor de um ponteiro de qualquer maneira. Em alguns casos.19 ± Ponteiros para as Funções A Linguagem C permite criar ponteiros para todos os tipos de dados. float (*media)(). O programa repete então um laço até encontrar o ponteiro para a string NULL (a condição final). ele atribui ao ponteiro dia_útil o endereço inicial da matriz diasuteis (o endereço da string Segunda). mais tarde. ela permite que os programas criem e usem ponteiros para as funções. os programas somente irão obter um ponteiro para uma posição de memória com a qual o programa determinará o uso do ponteiro. é preciso especificar o tipo do valor para o qual o ponteiro aponta. o compilador pode. efetuar aritmética de ponteiros corretamente e adicionar os valores de deslocamentos corretos quando incrementar ou decrementar o ponteiro.17 ± Declarando uma Constante String usando um Ponteiro Muitas vezes strings de caracteres são inicializadas como segue: char titulo[] = ³Unesp Ilha Solteira´. depois. trabalha-se da direita para a esquerda: . 7. Ao ler uma declaração de variável. float *media(). o compilador C aloca memória suficiente para armazenar os caracteres especificados (e o terminador NULL).

} int min(int a. result = pega_resu lt(1. para a maioria dos programadores.h> int pega_result(int a. não há limite no número de indireções (ponteiros para ponteiros) que os programas podem usar. } 7. valor = 1001. int (*compare)()) { return(compare(a.20 ± Ponteiro para uma Função O uso mais comum de um ponteiro para uma função é passar essa função como um parâmetro para outra função. 2. b)). Separe um tempo para experimentar este programa e desenhe os níveis de indireção em um pedaço de papel até compreender o processamento que ele executa: #include <stdio. Por exemplo.h> int qual_e_o_valor(int ***ptr) { return(***ptr). } void main(void) { int *nivel_1. printf("O valor à %d \n". nivel_1 = &valor. int b) { printf("Em max \n"). Dependendo da função que o programa passa. No entanto.21 ± Usando um Ponteiro para um Ponteiro para um Ponteiro A Linguagem C permite criar variáveis que são ponteiros para outros ponteiros. } . Em geral. nivel_2 = &nivel_1. usar mais do que um ponteiro para um ponteiro resultará em confusão considerável. qual_e_o_valor(nivel_3)). printf("O maximo entre 1 e 2 à %d \n". o programa a seguir usa três níveis de ponteiros para um valor do tipo int. &min).int (*min)(). // Chama a função passada } int max(int a. O programa a seguir passa a função min ou max para a função pega_result. **nivel_2. result). e tornará seus programas muito difíceis de compreender. 2. nivel_3 = &nivel_2. printf("O minimo de 1 e 2 à %d \n". result = pega_result(1. return((a > b) ? a: b). result). int b) { printf("Em min \n"). return((a < b) ? a: b). } void main(void) { int result. o valor que pega_result retorna será diferente: #include <stdio. ***nivel_3. &max). 7. int b.

y y 7.8 ± Ponteiros com Parâmetros de Função: foi visto que quando for necessário alterar o valor de um parâmetro.12 ± Funções que retornam Ponteiros: foi explicado que o valor que uma função retorna é sempre do tipo declarado no protótipo ou cabeçalho da . deverá passar para a função um ponteiro para um parâmetro. usa-se o operador asterisco de indireção (*). y y 7.9 ± A Aritmética de Ponteiros: foi explicada de manira clara a aritmética de ponteiros. Foi apresentado um programa que usa os ponteiros para dois parâmetros do tipo int para permutar os valores das variáveis. y y 7.2 ± Determinando o Endereço de uma Variável: foi visto como obter um endereço de uma variável e quando os programas precisarem determinar o endereço de uma variável. uma síntese do que foi tratado em cada item deste módulo. caso você já tenha conhecimentos na Linguagem C. y y 7.6 ± Desreferenciando um Ponteiro: foi explicado que desreferenciar um ponteiro é o processo de acessar o valor de uma posição de memória específica.7. que servem para apontar para a próxima posição ou para a posição anterior na memória. y y 7.7 ± Usando Valores de Ponteiro: foi apresentado o código de um programa em que o valor de um ponteiro é usado para receber o endereço de uma variável de depois o ponteiro é usado para indicar o valor armazenado na posição de memória que ele indica. y y 7. char.4 ± Aplicando o Operador de Endereço (&) a uma Matriz: foi visto que se o operador de endereço for aplicado a uma matriz. float.5 ± Declarando Variáveis Ponteiros: foi visto que para declarar um ponteiro.3 ± Como a Linguagem C trata Matrizes como Ponteiros: é mostrado o código de um programa que exibe o endereço inicial de várias matrizes diferentes. y y 7. a Linguagem C retornará o endereço inicial da matriz. deverão usar o operador de endereço da Linguagem C ³&´.) e um asterisco (*) antes do nome da variável.10 ± Incrementando e Decrementando um Ponteiro: foram vistas as operações de incremento e o decremento do valor de um ponteiro. y y 7. Para desreferenciar o valor de um ponteiro. y y 7.11 ± Percorrendo uma String usando um Ponteiro: foi visto um programa que usa uma função para exibir uma string de caracteres usando um ponteiro.1 ± Ponteiros como Endereços: é visto que um ponteiro é uma variável ou um valor que contem um endereço. precisa-se especificar o tipo do valor ao qual o ponteiro aponta (tal como int. Com esta síntese você poderá relembrar conceitos vistos durante nosso estudo ou mesmo direcionar seu estudo. y y 7.22 ± Síntese do Módulo É apresentado à seguir. y y 7. etc. que trata os ponteiros como valores que podem ser somados ou subtraídos. y y 7.

Mais comumente serão usadas matrizes para conter strings de caracteres. y y 7. Uma vez que um arquivo esteja aberto. as funções podem declarar ponteiros para os valores. y y 7.15 ± Percorrendo em um Laço uma Matriz de Strings de Caracteres: foi visto um programa que percorre em um laço uma matriz . então uma abertura de um arquivo também inicializa um indicador de posição do arquivo no começo do arquivo.21 ± Usando um Ponteiro para um Ponteiro para um Ponteiro: foi visto que a Linguagem C permite criar variáveis que são ponteiros para outros ponteiros.1 ± Introdução Na Linguagem C. y y 7. Além de retornar esses tipos básicos. Um fluxo é associado a um arquivo específico pela realização de uma operação de abertura.Sistema de Arquivos 8. y y 7. y y 7. um arquivo é um conceito lógico que pode ser aplicado a tudo.16 ± Usando um Ponteiro para um Ponteiro para String de Caracteres: foi visto um programa que usa um ponteiro para um ponteiro para string de caracteres para exibir o conteúdo de uma matriz. Em geral. Se pode suportar acesso randômico. y y 7.13 ± Criando uma Função que retorna um Ponteiro: foi visto um programa que cria uma função que converte todos os caracteres de uma string para maiúsculas e depois retorna um ponteiro para uma string.20 ± Ponteiro para uma Função: foi visto que o uso mais comum de um ponteiro para uma função é passar essa função como um parâmetro para outra função. Por exemplo. também pode-se criar matrizes de ponteiros. mas nem todos os arquivos os são. y y 7.18 ± O Ponteiro do tipo Void: foi dada uma explicação geral sobre o ponteiro do tipo void.19 ± Ponteiros para as Funções: foi visto que a Linguagem C permite que os programas criem e usem ponteiros para as funções.17 ± Declarando uma Constante String usando um Ponteiro: foi visto como declarar uma constante string usando um ponteiro. desde arquivos em disco até terminais. não há limite no número de indireções (ponteiros para ponteiros) que os programas podem usar. um arquivo em disco pode suportar acesso randômico enquanto um acionador de fita não pode. y y 7. que contém ponteiros para strings que contém os nomes dos dias da semana. Nem todos os arquivos têm as mesmas capacidades.função.14 ± Uma Matriz de Ponteiros: foi explicado que assim como pode-se criar funções que retornam ponteiros. informações podem ser intercambiadas entre o arquivo e o seu programa. À medida que . y y 7. Módulo 8 . Isso ilustra um ponto importante sobre o sistema de E/S da linguagem C: todos os fluxos são os mesmos.

gravar ou anexar. da área intermediária (buffer) seja descarregado para o dispositivo externo.3 ± Abrindo um Arquivo Usando FOPEN Muitos programas em Linguagem C armazenam e lêem informações de um arquivo.cada caractere é lido ou escrito para o arquivo. O parâmetro modo especifica como quer-se usar o arquivo . A função fopen permite que seus programas abram um arquivo. O formato de fopen é como segue: #include <stdio. será preciso abrir o arquivo. se houver. o programa deve declarar uma (ou mais de uma se formos trabalhar com mais de um arquivo simultaneamente) variável ponteiro de arquivo.h> FILE *fopen(const char *nomearq. Este buffer intermediário entre arquivo e programa é chamado ³fluxo´. tais como o nome do arquivo. o indicador de posição é incrementado. Antes que os programas possam ler ou gravar informações em um arquivo. O parâmetro nomearq é uma string de caracteres que contém o nome do arquivo desejado. 8. a progressão através do arquivo. Para obter uma variável ponteiro de arquivo. Todos os arquivos são fechados automaticamente quando o programa termina normalmente. estado e posição corrente. A tabela abaixo descreve os valores de modo que fopen suporta: Modo "r" "w" "a" "rb" "wb" Significado Abre um arquivo para leitura Cria um arquivo para escrita Acrescenta dados para um arquivo existente Abre um arquivo binário para leitura Cria um arquivo binário para escrita . O buffer apontado pelo ponteiro de arquivo é a área intermediária entre o arquivo no disco e o programa. Um arquivo é desassociado de um fluxo específico por meio de uma operação de fechamento. Adotaremos esta nomenclatura aqui. assim. uma porta serial. onde fp é o nome que escolhemos para a variável (podia ser qualquer outro). e no jargão dos programadores é comum falar em funções que operam fluxos em vez de arquivos. Um ponteiro de arquivo é um ponteiro para uma área na memória (buffer) onde estão contidos vários dados sobre o arquivo a ler ou escrever. Isto se deve ao fato de que um fluxo é uma entidade lógica genérica. Um ponteiro de arquivo é uma variável ponteiro do tipo FILE que é definida em stdio. tal como "c:\arqdados. etc. um disco. assegurando.dat". 8. que pode estar associada a uma unidade de fita magnética. o fechamento do fluxo faz com que o conteúdo. const char *modo).h. Em fluxos abertos para saída. Para ler ou escrever em um arquivo de disco. Esse processo é geralmente referenciado como uma limpeza/descarga de apontador e garante que nenhuma informação será acidentalmente esquecida na área intermediária do disco.para ler.2 ± O Ponteiro de Arquivo A linha comum que une o sistema de E/S de disco aos programas escritos em C é o ponteiro de arquivo. usa-se uma declaração semelhante a esta: FILE *fp.

Se você examinar o arquivo de cabeçalho stdio. elas normalmente declaram ponteiros de arquivos usando a estrutura FILE. /*Nivel do buffer cheio/vazio*/ /* Sinalizadores de status*/ /* Descritor de arquivo*/ /*Caracter ungetc se não existir um . *saida. Se a função fopen não puder abrir o arquivo especificado. Esta definição foi tomada do Turbo C++ Lite: typedef struct { short level. unsigned char hold. quando os programas efetuam operações de entrada e saída. "r")) != NULL) { /*Arquivo aberto com sucesso*/ } else { /*Erro ao abrir o arquivo*/ } Dentro do programa."ab" "r+" "w+" "a+" "r+b" "w+b" "a+b" "rt" "wt" "at" "r+t" "w+t" "a+t" Acrescenta dados a um arquivo binário existente Abre um arquivo para leitura/escrita Cria um arquivo para leitura/escrita Acrescenta dados ou cria um arquivo para leitura/escrita Abre um arquivo binário para leitura/escrita Cria um arquivo binário para leitura/escrita Acrescenta ou cria um arquivo binário para leitura/escrita Abre um arquivo texto para leitura Cria um arquivo texto para escrita Acrescenta dados a um arquivo texto Abre um arquivo-texto para leitura/escrita Cria um arquivo texto para leitura/escrita Acrescenta dados ou cria um arquivo texto para leitura/escrita A função fopen retorna um ponteiro (chamado ponteiro de arquivo) para uma estrutura do tipo FILE que o arquivo de cabeçalho stdio.h define. unsigned flags. Seus programas sempre devem testar o valor de retorno de fopen para garantir que abriu o arquivo com sucesso. como mostrado aqui: if ((pa = fopen("NOMEARQ.4 ± A Estrutura FILE Como você aprendeu.h.3. como visto no final do item 3. Em tais casos. 8. é preciso declarar a variável ponteiro de arquivo como segue: void main() { FILE *pa /*Ponteiro para uma est rutura do tipo FILE*/ Muitos programas abrem um arquivo para entrada e outro para saída. você poderia declarar dois ponteiros de arquivo. como mostrado aqui: FILE *entrada. encontrará a definição da estrutura FILE. Seus programas usarão o ponteiro de arquivo para suas operações de entrada e saída.EXT". ela retornará o valor NULL. char fd.

será visto que a maioria deles não testa o valor de retorno de fopen. Se fclose for bem sucedida. unsigned char *buffer. como mostrado aqui: if (fclose(pa) == EOF) printf ("Erro ao fechar o arquivo de dados \n").5 ± Fechando um Arquivo Aberto Fechar um arquivo instrui o sistema operacional a esvaziar todos os buffers de disco associados com o arquivo e a liberar os recursos do sistema que o arquivo consumiu. a maioria dos compiladores definirá uma matriz de tamanho fixo (normalmente 20) dos ponteiros de arquivo que contém as informações para cada arquivo que seu programa abrirá. o tamanho do buffer do arquivo e a localização. os programas podem usar as funções fgetc e fputc.h> . um sinalizador que indica se o arquivo é um arquivo temporário. Se ocorrer um erro. como mostrado aqui: #include <stdio.h> int fclose (FILE *pont_arquivo). o programa poderá fazer muito pouco para corrigir a situação. Se o programa precisa abrir mais de 20 arquivos. se estiver trabalhando com arquivos de dados críticos. short token. cujos formatos são mostrados aqui: #include <stdio. e outras variáveis sinalizadoras.buffer*/ short bsize. o buffer de caracteres que unget usa. como mostrado aqui: fclose(pa). 8. Se estiver trabalhando no ambiente do DOS. fclose retornará a constante EOF. À medida que for examinando programas em Linguagem C. Para as operações de entrada e saída de caractere. consulte a documentação do compilador para conhecer os passos que precisará seguir para modificar o tamanho da matriz de ponteiros de arquivo. a estrutura FILE armazena o ponteiro de arquivo que controla sua localização atual dentro do arquivo. Além disso. unsigned char *curp. unsigned stemp. A função fclose fecha o arquivo associado com o ponteiro de arquivo especificado. C fechará os arquivos abertos quando o programa terminar. tais como os dados de ponteiros de arquivo. Na maioria das vezes. podem ler e gravar dados um caracter de cada vez ou uma linha de cada vez. No entanto. } FILE /*Tamanho do buffer*/ /*Buffer de transferência*/ /*Ponteiro ativo atual*/ /*Indicador de arquivo temporário*/ /*Usado para verificação de validade*/ /*Esse é o objeto FILE */ A estrutura FILE contém o descritor de arquivo de baixo nível que o sistema operacional usa para acessar o arquivo. deverá exibir uma mensagem de erro para o usuário para que ele possa examinar o conteúdo do arquivo.6 ± Lendo e Gravando Informações no Arquivo um Caracter de Cada Vez Quando os programas efetuam operações de entrada e saída em arquivos. se uma operação fechar arquivo apresentar erro. Se não chamar a função fclose. retornará o valor 0. 8.

int fputc (int caractere.TST \n"). /* Fecha o arquivo saida */ } } 8.8 ± Determinando a Posição Atual no Arquivo No item anterior foi visto como a Linguagem C controla a posição atual em arquivos abertos para as operações de entrada e saída.h> void main(void) { FILE *entrada. o ponteiro da posição avançará para o início da próxima linha. else { /* Lê e grava cada caractere no arquivo*/ while ((letra = fgetc(entrada)) != EOF) fputc(letra. fclose(entrada).sys para um arquivo chamado config. Usando o ponteiro da posição. a funções de entrada e saída de arquivo sempre podem controlar a localização atual dentro do arquivo. como segue: .TST". Dependendo do programa. A função fgetc lê o caracter atual do arquivo de entrada especificado. fputc retornará a constante EOF. gravação e anexação.SYS \n").tst: #include <stdio. usa fgetc e fputc para copiar o conteúdo do arquivo do diretório raiz config. O programa a seguir. Em tais casos usa-se a função ftell. Se o ponteiro de arquivo tiver chegado ao final do arquivo. *saida. um dos campos da estrutura armazena um ponteiro da posição para localização atual dentro do arquivo. "w"))==NULL) printf("Erro ao abrir \CONFIG. Se ler uma linha de texto do arquivo.SYS".4 apresentou a estrutura FILE. o sistema operacional define o ponteiro da posição no final do arquivo. "r"))==NULL) printf("Erro ao abrir \CONFIG. o ponteiro da posição avançará um caractere. Quando abre-se um arquivo no modo de anexação. algumas vezes será necessário determinar o valor do ponteiro de posição.7 ± O Ponteiro de Posição do Ponteiro de Arquivo O item 8. saida). Quando abre-se um arquivo para operações de leitura ou gravação. if ((entrada = fopen(" \CONFIG. fgetc retornará a constante EOF. else if ((saida = fopen(" \CONFIG. A função fputc gravará um caractere na posição do ponteiro de arquivo atual dentro do arquivo de saída especificado. /* Fecha o arquivo entrada */ fclose(saida). Como foi visto. o sistema operacional define o ponteiro da posição no início do arquivo. FILE *pont_saida). Modo de Abertura Posição do Ponteiro do Arquivo a r w Imediatamente após o último caractere do arquivo No início do arquivo No final do arquivo 8. int letra. A tabela a seguir especifica a localização na qual fopen coloca o ponteiro da posição quando abre-se o arquivo nos modos de leitura. Toda vez que ler ou gravar um caractere.int fgetc (FILE *pont_entrada). Se um erro ocorrer.

chamados de elementos de imagem. ou pixel. É importante notar que o sistema de numeração inicia no canto superior esquerdo da tela no ponto (x. O programa começa abrindo o arquivo do diretório raiz config. O programa a seguir usa ftell para exibir informações do ponteiro de posição. o programa lê e exibe o conteúdo do arquivo. A função ftell retorna um valor inteiro longo que especifica o byte de deslocamento à partir da posição atual no arquivo especificado.sys no modo de leitura.#include <stdio.SYS".SYS \n").1 A Tela Gráfica No modo gráfico. como está mostrado na Figura (a). a tela do monitor de vídeo é dividida numa fina malha de pontos individuais. Uma tela VGA (Adaptador Gráfico Colorido) tem 640 linhas por 480 colunas. O programa então usa ftell para exibir a posição atual. fclose(entrada). /* Fecha o arquivo entrada */ } } <p class=MsoNormal styl Módulo 9 Funções Gráficas na Linguagem C 9. A pós encontrar o final do arquivo. /* Lê e grava cada caractere no arquivo*/ while ((letra = fgetc(entrada)) != EOF) fputc(letra. stdout). "r")) == NULL) printf("Erro ao abrir \CONFIG. A resolução da tela é descrita em termos do número de pixeis por linha ou por coluna. o programa novamente usará ftell para exibir a posição atual. Qualquer pixel pode ser apagado ou iluminado.0). como segue: #include <stdio. printf("\nA posição atual é o byte %d \n". if ((entrada = fopen(" \CONFIG. .h> long int ftell (FILE *pont_arquivo).y) = (0. ftell(entrada)). Em seguida. o que vem a ser o princípio básico para a criação de imagens gráficas. ftell(entrada)). int letra.h> void main(void) { FILE *entrada. else { printf("A posição atual é o byte %d \n\n".

-319) (c)Eixos cartesianos no monitor CGA 9. Por isto.320) yc (0. total de linhas do vídeo Então a tela do vídeo terá o sistema de eixos conforme dado na figura abaixo: (0.0) c .479) (a) ( ) (479.yc onde: yv = eixo y da tela de vídeo yc = eixo y do plano cartesiano ymax = n. para mostrar na tela do PC no gráfico como se fosse no plano cartesiano deve-se fazer a seguinte equivalência: yv = ymax/2 .0) IX Y (639. vemos que o eixo y na tela do PC está invertido em relação ao eixo yc do plano cartesiano.(0.2 ± Detectando o Adaptador Gráfico ¥ ¤ £ ¢ IX X (0.0) (a) Eixos de coordenadas no modo VGA (b) Eixos de coordenada no modo carteziano Segundo as figuras (a) e (b) acima.0) (0.479 ) ¡   (639.

EGA-MONO 6 .h> main() { . EGA.16 colors 720x350 . VGA.2 colors 640x200 .ATT400 HERCMONOHI ATT400C0 ATT400C1 ATT400C2 ATT400C3 ATT400MED ATT400HI VGALO VGAMED VGAHI 0 012345 9 .MCGA 012345 3 . Os valores que os parâmetros gdriver e gmode poderão assumir são: Gdriver 1 .) está conectado e informa o modo de resolução mais alto do driver daquele adaptador.IBM8514 EGAMONOHI IBM8514HI IBM8514LO 3 01 7 . Para isso usamos a função detectgraph.2 color 640x200 . A sintaxe da função é: detectgraph(&gdriver.VGA 012 10 .2 color 320x200 320x200 320x200 320x200 640x200 .EGA 01 4 .PC3270 PC3270HI 0 A seguir temos um exemplo de um programa que detecta o adaptador imformando o mesmo: #include <stdio.EGA64 EGA64LO EGA64HI 01 5 . Hercules etc.16 colors 640x200 .HERCULES 8 .4 colors 640x350 .2 colors 640x400 .16 colors 640x480 .2 colors 2 .Provavelmente em seu programa seja necessário detectar qual o adaptar gráfico está em uso.2 color 640x480 .2 color 320x200 320x200 320x200 320x200 640x200 .16 colors 640x350 . Esta função detecta qual adaptador (CGA.h> #include <graphics.2 colors 640x480 .&gmode).16 colors 640x350 .16 colors 640x350 .CGA Placa Gráfica CGAC0 CGAC1 CGAC2 CGAC3 CGAHI MCGAC0 MCGAC1 MCGAC2 MCGAC3 MCGAMED MCGAHI EGALO EGAHI Gmode 01234 Nº LinhasxColunas 320x200 320x200 320x200 320x200 640x200 .256 colors 1024x768 256 colors 720X348 .

&modo_grafico).3 ± Inicializando a Parte Gráfica Quando os programas que você escrever usarem os recursos gráficos da Linguagem C. closegraph().modo_grafico). } No programa anterior. A função initgraph() inicializa o sistema para a placa e o modo gráfico detectados pela função detectgraph(). printf("\n O adaptador detectado é %d ". tirando a tela do modo texto e colocando-a no modo gráfico.adaptador_grafico). printf("\n O modo de alta resolucao %d".h> #include <graphics. clrscr().&modo_grafico. por exemplo. initgraph(&adaptador_grafico. detectgraph(&adaptador_grafico. int modo_grafico. você terá de preparar o sistema para isto.int adaptador_grafico. se o monitor de vídeo for CGA aparecerá: O adaptador detectado é 9 O modo de alta resolucao é 2 Indicando que o adaptador é 9 (VGA) e as dimensões da tela são as do modo 2 (640 linhas x 480 colunas). getch(). 9.i. } ."c: \tc"). getch().h> main() { int adaptador_grafico.j. A seguir um exemplo que ilustra a sintaxe e o uso destas duas funções initgraph() e closegraph(): #include <stdio.&modo_grafico). A função closegraph() cancela o modo gráfico estabelecido por initgraph() liberando a memória utilizada para gráficos. detectgraph(&adaptador_grafico. int modo_grafico.

As funções getmaxx() e getmaxy() retornam com valores inteiros os valores máximos das coordenadas x e y da tela. etc. A seguir. xmax. seus programas precisarão conhecer as dimensões da tela gráfica.100. ymax).h> main() { int adapt. Se a tela em questão for VGA o resultado será: O eixo x da tela vai de 0 a 639 O eixo y da tela vai de 0 a 479 . outtextxy(100. VGA. printf("\n O eixo x da tela vai de 0 a %d". visto que sem estas informações as manipulações gráficas incorrerão em erros.4 ± Obtendo as Dimensões da Tela Trabalhando com funções gráficas. printf("\n O eixo y da tela va i de 0 a %d". getch(). o programa ilustra o uso destas duas funções gráficas: #include <stdio. getch().&mod). com isto. mod. EGA. o programa está habilitado a utilizar toda tela sendo ela CGA.h> #include <graphics. } no modo gráfico! Aperte uma Este programa informa quais são as dimensões máximas x e y da tela gráfica. xmax)."c:\tc"). ymax. 9. detectgraph(&adapt.´Estamos tecla. ymax=getmaxy(). initgraph(&adapt. Com estas funções determinam-se as dimensões máximas da tela. xmax=getmaxx(). inicia a tela no modo gráfico e depois sai do modo gráfico.O programa anterior detecta a resolução gráfica da tela. closegraph().´).& mod.

5 ± Desenhando uma Reta na Tela Muitas são as aplicações gráficas em que é necessário desenhar-se uma reta na tela. getch().&mod). initgraph(&adapt.yi ao ponto xf. yinf). A seguir. detectgraph(&adapt.h> main() { int adapt. ilustramos o uso da função rectangle().h> main() { int adapt.yi. } 9. para separar textos ou para outras funções específicas."c: \tc"). Para este propósito. o uso da função line(). Para este propósito. closegraph(). yinf).9. mod . mod . Os parâmetros entre parênteses indica para o seu programa que ele desenhe uma linha ligando o ponto xi. detectgraph(&adapt.yf). .& mod)."c: \tc").&mod. com um programa exemplo: #include <graphics. xinf. 0.yf. a Linguagem C tem a função line() que tem a seguinte sintaxe: line(xi. a Linguagem C tem a função rectangle() que tem a seguinte sintaxe: rectangle(xsup. ysup. getmaxy()). com um programa exemplo: #include <graphics.6 ± Desenhando um Retângulo na Tela Muitas são as aplicações gráficas em que é necessário desenhar-se um retângulo na tela. Os parâmetros entre parênteses indica para o seu programa que ele desenhe um retângulo na tela com o canto superior esquerdo no ponto (xsup. line(0. A seguir. getmaxx().xf. ysup) e o canto inferior direito no ponto (xinf. initgraph(&adapt.&mod.

100). Para este propósito. com um programa exemplo: #include <graphics. cor). ela acende um único pixel na tela."c: \tc"). ilustramos o uso da função circle (). a Linguagem C tem a função putpixel() que tem a seguinte sintaxe: putpixel(x.15). outtextxy(55. initgraph(&adapt. putpixel(300. 300.100. raio). getch(). outtextxy(303. ycentro. getch().110. } 9. com um programa exemplo: .100. detectgraph(&adapt.8 ± Desenhando um Círculo na Tela Muitas são as aplicações gráficas em que é necessário desenhar-se um círculo na tela. closegraph(). 102. ilustramos o uso da função putpixel(). y). closegraph().15). ycentro).usando a cor especificada por cor. putpixel(50. ou seja.7 Desenhando um Ponto na Tela Muitas são as aplicações gráficas em que é necessário desenhar-se um ponto na tela. } 9. Os parâmetros entre parênteses indicam para o seu programa que ele desenhe um círculo à partir das coordenadas (xcentro. A seguir." aqui 1" ). Para este propósito.de raio raio.h> main() { int adapt. y. mod .&mod.rectangle(5. a Linguagem C tem a função circle() que tem a seguinte sintaxe: circle(xcentro. Os parâmetros entre parênteses indicam para o seu programa que ele imprima um pixel (ponto) no ponto (x." aqui 2").&mod). 10. A seguir.

getch(). um círculo e dois pontos: #include <graphics. circle(300. 100). 100. line(5."c: \tc").h> main() { int adapt. putpixel(200. } 9. mod . 10. detectgraph(&adapt. a Linguagem C tem a função arc() que tem a seguinte sintaxe: . getch(). circle(300. Para este propósito. 50.50). closegraph(). 100). rectangle(5. 1).&mod). 1). 300. 10. putpixel(100.h> main() { int adapt. 50). initgraph(&adapt. closegraph(). initgraph(&adapt.100.&mod.&mod). detectgraph(&adapt.9 ± Desenhando um Arco Circular na Tela Muitas são as aplicações gráficas em que é necessário desenhar-se um arco círcular na tela. } O exemplo a seguir é um programa que desenha uma reta. 50.&mod."c: \tc").#include <graphics. 300. mod . um retângulo.

} 9. com um programa exemplo: #include <graphics. mod .&mod. arc(300.i++) { line(i+5.&mod). detectgraph(&adapt.i+100). ycentro) e o raio por raio. putpixel(200. 100.&mod.i+10.h> main() { int adapt. Os parâmetros angulo_inicial e angulo_final especificam os ângulos inicial e final em graus. que tem uma sintaxe bastante simples.i+300.i . O centro é dado pelas coordenadas (xcentro. ycentro. a Linguagem C tem a função cleardevice(). 50. mod. 0. Para este propósito."c: \tc").i+ 100)."c: \tc"). initgraph(&adapt. initgraph(&adapt. angulo_inicial. detectgraph(&adapt. que será ilustrada através do programa exemplo abaixo: #include <graphics. A seguir. raio).h> main() { int adapt. angulo_final. seus programas irão desenhar várias formas geométricas e logo em seguida será necessário apagá-las. i<200. ilustramos o uso da função arc (). 15). putpixel(100.arc(xcentro.i+300. rectangle(i+5. 90.&mod). 50. i+10. getch(). closegraph(). onde o 0 está na posição horizontal apontando para a direita e 90 na posição vertical apontando para cima. . 15).10 ± Limpando a Tela Gráfica Em muitas ocasiões. 100). for (i=0.

Para este propósito. borda). y. Para este propósito. floodfill(x. a Linguagem C tem a função setfillstyle() e floodfill() que tem a seguinte sintaxe: setfillstyle(padrao.cor). Os valores que se pode atribuir ao parâmetro cor para a tela VGA são dados a seguir: VALOR COR AZUL CIANO MAGENTA CINZA CLARO AZUL CLARO CIANO CLARO MAGENTA CLARO BRANCO 1 3 5 7 9 11 13 15 VALOR COR PRETO VERDE VERMELHO MARROM CINZA ESCURO VERDE CLARO VERMELHO CLARO AMARELO 0 2 4 6 8 10 12 14 9. closegraph(). delay(1000). 50+i). } 9. a Linguagem C tem a função setcolor() que tem a seguinte sintaxe: setcolor(cor). 100+i. .11 ± Mudando as Cores do um Desenho Em muitos casos será necessário alterar a cor das linhas que delimitam os desenhos que são feitos pelos seus programas. cleardevice(). } getch().circle(300+i.12 ± Mudando a Cor de Fundo e o Preenchimento do um Desenho Em muitos casos será necessário alterar a cor de fundo e o padrão de preenchimento dos desenhos que são feitos pelos seus programas.

ym = getmaxy()/2. floodfill(xm.1). circle(xm. ilustramos o uso das funções setfillstyle() e floodfill() com um programa exemplo: #include < graphics.ym. setfillstyle(2.h> main() { int adapt.100).&mod). setados pela instrução setfillstyle().&mod. circle(xm. circle(xm. y.ym. detectgraph(&adapt. até encontrar a cor especificada por borda.A função floodfill(x. mod. y) com a cor e o padrão atuais de preenchimento.250).ym. sendo que o parâmetro padrao assume um dos valores abaixo: Número 0 2 4 6 8 10 Cor de fundo Linhas horizontais Linhas inclinadas grossas /// linhas inclinadas grossas \\ cruzes grossas agrupadas pontos esparsos Padrão 1 3 5 7 9 11 Número Cor sólida Linhas inclinadas finas /// Linhas inclinadas finas \\ cruzes finas agrupadas linhas intercaladas pontos densos Padrão A seguir.ym .ym+10. borda) preenche uma área na tela gráfica ao redor do ponto dado por (x. xm = getmaxx()/2. .1). xm."c: \tc"). setfillstyle(7.150). setcolor(LIGHTGREEN).10). A função setfillstyle() ajusta o padrão e a cor de preenchimento gráfico atuais. initgraph(&adapt.

1 A Tela Gráfica: é dada uma explicação detalhada de como funciona a tela gráfica na Linguagem C. y y 9. } 9. caso você já tenha conhecimentos na Linguagem C. y y 9. y y 9. floodfill(xm. y y 9. y y 9.3 Inicializando a Parte Gráfica: explica em detalhes que a função initgraph() inicializa o sistema para a placa e o modo gráfico detectados pela função detectgraph().6 Desenhando um Retângulo na Tela: fala sobre a função rectangle() que desenha um retângulo na tela.10 Limpando a Tela Gráfica: fala sobre a função cleardevice() que limpa a tela.11 Mudando as Cores do um Desenho: fala sobre a função setcolor() que muda as cores do desenho. y y 9. y y 9. conhecendo-se as dimensões da tela.10). y y 9. y y 9. floodfill(xm*2. y y 9. setfillstyle(3.7 Desenhando um Ponto na Tela: fala sobre a função putpixel() que desenha um ponto na tela.2 Detectando o Adaptador Gráfico: explicita o uso da função detectgraph que identifica o adaptador gráfico em uso.10).1).9 Desenhando um Arco Circular na Tela: fala sobre a função arc() que desenha um arco circular na tela. .ym*2.8 Desenhando um Círculo na Tela: fala sobre a função circle() que desenha um ponto na tela. Com esta síntese você poderá relembrar conceitos vistos durante nosso estudo ou mesmo direcionar seu estudo.13 Síntese do Módulo É apresentado à seguir. setfillstyle(7.ym+260. y y 9.5 Desenhando uma Reta na Tela: fala sobre a função line() que desenha uma reta na tela.floodfill(xm. getch().10). closegraph(). uma síntese do que foi tratado em cada item deste módulo.4 Obtendo as Dimensões da Tela: explica que com as funções getmaxx() e getmaxy() determinam-se as dimensões máximas da tela. tirando a tela do modo texto e colocando-a no modo gráfico.ym+160.1).

Quando declara-se uma estrutura. a união. Uma declaração de estrutura forma uma fonte que pode ser usada para criar variáveis de estruturas. char cidade[20]. todos os campos na estrutura estarão logicamente relacionados uns aos outros. Pode-se também declarar uma ou mais variáveis enquanto declara uma estrutura. Temos ainda que. o tipo enumerado e o typedef. nenhuma variável foi declarada. Observa-se que a declaração termina com um ponto-e-vírgula.y y 9. Por exemplo. Esta expressão declarará uma variável estrutura do tipo endereço chamada info_adr.12 Mudando a Cor de Fundo e o Preenchimento do um Desenho: fala sobre as funções setfillstyle() e floodfill() que muda as cores de fundo e o preenchimento de um desenho. unsigned long int cep. a informação sobre o nome e o endereço em uma lista de endereços deve ser normalmente representada em uma estrutura. char rua[40]. Até que se declare uma variável desse tipo. O typedef cria um novo nome para um tipo existente. 10. char estado[3]. As variáveis que compreendem a estrutura são chamadas de campos. a etiqueta endereço. define-se um tipo de variável complexa composto por campos. Em geral. O tipo enumerado é uma lista de símbolos. O seguinte fragmento de código declara uma estrutura-fonte que define os campos nome e endereço de tal estrutura. char rua[40]. uma estrutura é uma coleção de variáveis referenciadas sobre um nome. que algumas vezes é chamado de conglomerado ou agregado de tipos de dados. A palavra reservada struct diz ao compilador que uma estrutura está sendo definida: struct endereço{ char nome[30]. A união habilita um mesmo pedaço de memória a ser definido como dois ou mais tipos de dados diferentes.1 ± Estruturas Na Linguagem C. identifica essa estrutura de dados particular e é o seu especificador de tipo. deve-se escrever: struct endereço info_adr. provendo um meio conveniente de manter informações relacionadas juntas. Módulo 10 ± Tipos de Dados A Linguagem C permite criar diversos tipos diferentes de dados particulares. Veja a seguir um exemplo: struct endereço{ char nome[30]. A estrutura é um agrupamento de variáveis sobre um nome. char cidade[20]. Neste ponto do código. Somente a forma dos dados foi definida. Para declarar uma variável com essa estrutura. ela não existe. }. Podemos citar a estrutura. . É por isso que uma estrutura é uma declaração.

o seguinte código atribuirá o cep 12345777 ao campo cep da variável estrutura info_adr declarada anteriormente: info_adr. Para acessar uma estrutura específica. A forma geral é: nome_da_variável_estrutura. pode-se imprimir o conteúdo da info_adr. pode-se escrever: printf (³%lu´. como mostrada aqui: gets (info_adr.1 ± Referenciando os Campos da Estrutura Campos da estrutura são referenciados pelo uso do operador de seleção de campo: o ponto.nome. Todos os campos da estrutura são acessados da mesma maneira. binfo e cinfo como desse tipo. Isso definirá um tipo de estrutura chamada endereço e declarará as variáveis info_adr. para imprimir o cep na tela. então. ++t) putchar (info_adr. info_adr.1. Por exemplo. um caractere por vez. usando este código: int t. unsigned long int cep. 10. a matriz de caracteres info_adr.1. Isso imprimirá o cep contido no campo cep da variável estrutura info_adr. for (t = 0. O nome da variável estrutura seguido por um ponto e o nome do campo referenciarão um campo individual da estrutura. para declarar uma matriz de 100 elementos de estrutura do tipo endereço (definida anteriormente). info_adr. Isso cria 100 conjuntos de variáveis que são organizados como definido na estrutura endereço. Da mesma maneira.2 ± Matrizes de Estruturas O uso de matrizes de estruturas é o mais comum das estruturas. Por exemplo. cinfo. deve-se primeiro definir uma estrutura e. info_adr[2].cep).cep = 12345777. deve-se escrever: printf (³%lu´. declarar uma variável matriz daquele tipo.nome pode ser usada em uma chamada à função gets( ). } info_adr.cep).nome.nome[t]). Por exemplo. Se fosse necessário acessar os elementos individuais de info_adr.char estado[3].nome). . deve-se escrever: struct endereço info_adr[100]. Para declarar uma matriz de estruturas. Isso passará um ponteiro para caractere para o começo do campo nome.nome_do_campo Portanto. 10. poderia indexar nome. Por exemplo. binfo. para imprimir o código cep na estrutura 3. o nome da estrutura é indexado.nome[t].

os endereços e modo de programação dos dispositivos de I/O a serem manipulados tem que conhecidos adequadamente para evitar algum travamento do sistema por uso inadequado dessas funções.d = 98. Nesse caso.1. dois.6. deixam livre os endereços 220H a 22FH e 300H a 30FH. os sinais analógicos a serem convertidos só devem ser conectados com o computador ligado.4 ± Passando Estruturas para Funções Até aqui. O mapa de endereços de I/O do PC padrão. } um. todos os elementos da estrutura no lado esquerdo da atribuição receberão os valores dos elementos correspondentes da estrutura do lado direito.h> void main() { struct exemplo { int i. Também estes sinais devem ser desconetados antes de se desligar o computador. /*atribui uma estrutura a outra*/ printf (³%d %lf´.d).1 Introdução As funções de entrada/saída (I/O input/output) da linguagem C são as equivalentes das instruções in e out da linguagem Assembly. Elas permitem acesso direto ao hardware do microcomputador e.6.Como todas as variáveis matrizes. Por exemplo.i.i = 10. apresentado na tabela a seguir. A placa a ser inserida no slot ou barramento de expansão deve ser previamente configurada num desses endereços e conectada com o computador desligado. No caso de placas de aquisição de sinais. todo tipo de placa que não tenham grande demanda de endereços. um. Portanto. double d. 10. todas as estruturas e matrizes de estruturas dos exemplos são assumidas c Módulo 11 Funções de Entrada/Saída (I/O) e Programa Analisador Espectral 11. portanto. um. dois = um.1. . } 10. dois. pode-se atribuir uma a outra. as matrizes de estruturas começam sua indexação em zero. #include <stdio. como placas de protótipo ou de aquisição de sinais podem ser alocadas nesses endereços sem risco de causar conflito com outros dispositivos de I/O.3 ± Atribuindo Estruturas Se duas variáveis são do mesmo tipo. este programa atribui o valor da estrutura um para a estrutura dois e exibe o resultado 10 98. dois.

3 Placas de Aquisição de Sinais Analógicos A placa de aquisição de sinais CIO-DAS-AO-08H é uma placa de baixo custo para barramento ISA. 11.Tabela 11.h. Le um valor inteiro de 16 bits do endereço port_id especificado. para o endereço port_id especificado. int value) Envia o conteúdo da variável value. em 8 ou 16 bits. de 16 bits. 12 bits de resolução do tipo . void outportb(int port_id. unsigned char value) Envia o conteúdo da variável value. de 8 bits para o endereço port_id especificado.2 As Funções inportb e outport As funções inport() e outrport() permitem acesso direto a endereços de dispositivos de I/O. int inportb( int port_id). com as seguintes características: Entradas analógicas: 8 canais diferenciais multiplexados. void outport(int port_id. O arquivo header dessas funções é dos.1 Mapa de Endereços de I/O do PC 11. Le um valor inteiro de 8 bits do endereço port_id especificado. Seus formatos são apresentados a seguir: int inport( int port_id).

Conversor A/D A conversão A/D é iniciada com uma escrita no endereço BASE para operação em 8 bits ou escrita no endereço (BASE +1) para operação em 12 bits. tempo de conversão de 25 microssegundos. Saída analógica: dois canais de 12 bits.1 . que é zerado quando a conversão termina. em hexadecimal.Leitura 7 EOC 6 IP3 5 IP2 4 IP1 3 IRQ 2 MUX2 1 MUX1 0 MUX0 O resultado final da conversão pode então ser lido nos endereços BASE e BASE+1 com a seguinte configuração: Endereço BASE .2 Tabela de Endereçamento da Placa CIO-DAS08-AOH A placa tem um endereço-base setado por meio de chave de configuração. A tabela de endereçamento dessa placa é mostrada a seguir: Tabela 11. 11. O final de conversão é sinalizado através da leitura do bit mais significativo do endereço (BASE+2).aproximações sucessivas.Leitura . Os valores normalmente utilizados são 220H ou 300H.3. conforme esquema: Endereço BASE+2 . com faixa de tensão de saída selecionável por programação.

BS=(inportb(BASE)&0xF0)>>4. Para ordenação nos 12 bits. while(a==0x80) a=inportb(BASE+2)&0x80. realizar a leitura nos respectivos endereços.Escrita 7 X 6 X 5 X 4 X 3 DA11 (MSb) 2 <p class=MsoNormal 1 0 . deve. Bi=inportb(BASE+1). /*espera por EOC = 0. No endereço (BASE+1) estão os 8 bits mais significativos. O seguinte trecho de programa em linguagem C realiza a conversão de um valor analógico em digital. portanto.Escrita 7 DA7 6 DA6 5 DA5 4 DA4 3 DA3 2 DA2 1 DA1 0 DA0 (LSb) Endereço BASE+9 .Conversor D/A A conversão é realizada diretamente. em 12 bits. outportb(BASE+1.2 .Leitura 7 AD1 (MSB) 6 AD2 5 AD3 4 AD4 3 AD5 2 AD6 1 AD7 0 AD8 Observa-se acima que o LSB é é lido no endereço (BASE). rotacionar o byte menos significativo 4 casas a direita e somar com o byte superior rotacionado 4 casas a esquerda. 12 bits */ /* rearranjo valor digital em 12 bits 11. com apenas 4 bits menos significativos.7 AD9 6 AD10 5 AD11 4 AD12 (LSB) 3 0 2 0 1 0 0 0 Endereço BASE+1 .3. já provendo a ordenação dos bits. fim conversão */ /* leitura Byte inferior e correção */ /* leitura byte superior */ */ /* Partida no c onversor A/D. a=0x80.0). enviando o valor digital de 12 bits para os respectivos endereços no seguinte formato (Canal D/A 0): Endereço BASE+8 . vec = 16 * BS + Bi .

align .