Você está na página 1de 48

Universidade Federal de Campina Grande - UFCG

Centro de Engenharia Elétrica e Informática - CEEI


Departamento de Engenharia Elétrica - DEE
Programa de Educação Tutorial - PET

Minicurso

Introdução à Linguagem C

Responsáveis: João Victor Rodrigues Ramalho (PET-Elétrica-UFCG)


Matheus Cavalcante Rique (PET-Elétrica-UFCG)
Pedro Henrique de Araújo Felipe (PET-Elétrica-UFCG)

Tutor: Wamberto José Lira de Queiroz


Autores: Dinart Duart Braga (PET-Elétrica-UFCG)
Nustenil Segundo de M.L. Marinus (PET-Elétrica-UFCG)

Coautores: Ana Paula Tavares de Melo


Arthur Silva Vasconcelos
Bruna Larissa Lima Crisóstomo
Daniel Abrantes Formiga
Danilo Pequeno
Emilly Rennale Freitas de Melo
Filippe José Gadelha Tertuliano
Humberto de Brito Rangel Neto
João Victor Rodrigues Ramalho
Lucas Candeia Medeiros Maia
Matheus Cavalcante Rique
Natalia Silva Medeiros
Pedro Henrique de Araújo Felipe
Saul Borges Nobre
William Pinheiro Silva
SUMÁRIO SUMÁRIO

Sumário
1 Introdução à Linguagem C 3
1.1 Lógica Computacional . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.1 Algoritmo . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.2 Programa . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Falcon C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Tipos de Variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4 Incluindo Bibliotecas . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.5 Funções de Entrada-Saı́da padrões . . . . . . . . . . . . . . . . . 7
1.5.1 Printf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.5.2 Scanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6 Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.6.1 Aritméticos e de Atribuição . . . . . . . . . . . . . . . . . 9
1.6.2 Relacionais e Lógicos . . . . . . . . . . . . . . . . . . . . . 10
1.7 Biblioteca matemática . . . . . . . . . . . . . . . . . . . . . . . . 11
1.8 Exercı́cios de Revisão . . . . . . . . . . . . . . . . . . . . . . . . 12

2 Estruturas de seleção 13
2.1 if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.2 if/else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.3 switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.4 O operador ternário . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.5 Exercı́cios de Revisão . . . . . . . . . . . . . . . . . . . . . . . . 17

3 Estruturas de Repetição 18
3.1 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2 do/while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.3 for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.4 Exercı́cios de Revisão . . . . . . . . . . . . . . . . . . . . . . . . 21

4 Estruturas de Dados 21
4.1 Vetores/Arrays Unidimensionais . . . . . . . . . . . . . . . . . . 21
4.2 Strings na Linguagem C . . . . . . . . . . . . . . . . . . . . . . . 23
4.3 Matrizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.4 Exercı́cios de Revisão . . . . . . . . . . . . . . . . . . . . . . . . 26

5 Números Pseudoaleatórios 26
5.1 Visão Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.2 Exercı́cios de Revisão . . . . . . . . . . . . . . . . . . . . . . . . 27

6 Funções 27
6.1 Visão Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
6.2 Protótipo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
6.3 Função Sem Retorno e/ou Sem Entradas . . . . . . . . . . . . . . 32
6.4 Vetores como parâmetros de funções . . . . . . . . . . . . . . . . 33

1
SUMÁRIO SUMÁRIO

6.5 Exercı́cios de Revisão . . . . . . . . . . . . . . . . . . . . . . . . 35


6.6 Recursividade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
6.7 Escopo de variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . 37
6.7.1 Variáveis Locais . . . . . . . . . . . . . . . . . . . . . . . 37
6.7.2 Variáveis Globais . . . . . . . . . . . . . . . . . . . . . . . 37

7 Introdução a Apontadores 38
7.1 Visão Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
7.2 Declaração de apontadores . . . . . . . . . . . . . . . . . . . . . . 39
7.3 Inicialização de apontadores . . . . . . . . . . . . . . . . . . . . . 39
7.4 Aritmética de apontadores . . . . . . . . . . . . . . . . . . . . . . 41
7.4.1 Incremento e Decremento . . . . . . . . . . . . . . . . . . 41
7.5 Mais operações com apontadores . . . . . . . . . . . . . . . . . . 42
7.6 Exercı́cios de Revisão . . . . . . . . . . . . . . . . . . . . . . . . 43

8 Exercı́cios Complementares 44

2
1 INTRODUÇÃO À LINGUAGEM C

1 Introdução à Linguagem C
O objetivo desse curso é introduzir conceitos básicos da linguagem de pro-
gramação C, que une versatilidade e robustez, pois alia caracterı́sticas de lin-
guagens de baixo nı́vel com caracterı́sticas de alto nı́vel.

Criada por Denis Ritchie, em 1972, foi baseada na linguagem B e teve sua
primeira aplicação importante na reescrita do sistema operacional UNIX, que
até então era escrito na linguagem Assembly.

O C é uma linguagem de propósito geral, tendo como paradigma a pro-


gramação estruturada. É utilizada no desenvolvimento de navegadores, editores
de texto, banco de dados, sistemas operacionais, programas de comunicação e
automação.

Estudaremos nesse curso a linguagem de programação C padronizada pela


organização ANSI.

Sugerimos que o aluno compile todos os programas exemplificados nessa


apostila e dados em sala de aula, altere-os, veja se ocorrem erros e, caso sim,
tente corrigi-los. Enfim, manipule o programa para que se possa extrair o
máximo de experiência possı́vel de cada exemplo.

1.1 Lógica Computacional


1.1.1 Algoritmo
Conjunto de técnicas bem definidas e ordenadas que objetivem a resolução
de um determinado problema em um número finito de etapas. Por exemplo,
você tem um amigo chegando ao aeroporto e ele precisa ir de lá até sua casa.
As possı́veis formas dele ir são:
1. Táxi: ele vai ao ponto de táxi, entra no carro e dá o endereço para o
motorista;

2. Telefonema: quando chegar, ele liga para você para ir pegá-lo e depois,
vai até o terminal te esperar;
3. Ônibus: ele pega o ônibus para a integração na frente do aeroporto, desce
nela, pega outro ônibus, desce na rua do PET e caminha por duas quadras
em direção ao norte até chegar na casa número 51.

O exemplo apresenta um problema e três possı́veis algoritmos de soluções


para o mesmo. Note que as soluções não são únicas e cada uma possui carac-
terı́sticas especı́ficas, como gasto de dinheiro e tempo, apesar de todas conduzi-
rem à solução final.

3
1.1 Lógica Computacional 1 INTRODUÇÃO À LINGUAGEM C

1.1.2 Programa
Sequência completa de instruções que serão executadas por um computador,
de acordo com o algoritmo estabelecido. Pode-se dizer que o programa é na
verdade o algoritmo traduzido para linguagem de máquina.
A atividade de programação começa no ato do desenvolvimento do algo-
ritmo. Isto é, deve-se primeiramente dividir o problema em partes elementares
e planejar operações que conduzirão o programador até a resposta final por
meio das soluções particionadas. Desta forma, fazem-se usos de comandos da
linguagem de programação utilizada para realizar as operações pertinentes.

• Receber os números;

• Comparar (3 possibilidades: maior, menor ou igual);


• Exibir resposta.

A maior dificuldade talvez esteja em fazer a comparação. Note que se os


números não obedecerem duas das possibilidades, obrigatoriamente satisfarão a
terceira condição.
Para construir o código do programa, deve-se analisar o problema e pensar
em uma forma para resolvê-lo. Para isso, pode-se fazer o seguinte questiona-
mento:

• O que eu desejo fazer?


Antes de começar a programar, deve-se ter nı́tido em sua mente onde
você quer chegar, o que você deseja fazer. Às vezes, é muito útil fazer
um esquema no seu caderno ou em uma folha de papel, isso lhe ajuda a
esclarecer as etapas do programa.
• Quantas variáveis eu preciso?
Perceba que em todo e qualquer programa precisamos de variáveis, mas
não devemos exagerar na criação das mesmas. Imagine que você deseja
guardar informações, como os gastos do mês. Você pode ou guardar cada
nota fiscal de gasto (utilizando uma variável para cada gasto) ou você pode
ir anotando tudo em uma folha (incrementando uma variável, adicionando
valor a um valor de gasto que possuı́a anteriormente).

• Meu programa está ficando complicado demais?


Sempre ao programar devemos observar o esquema feito inicialmente e
tentar perceber se estamos tomando um caminho coerente ou se possi-
velmente estamos dando ”voltas”, tornando nosso caminho mais longo do
que o necessário.

4
1.2 Falcon C++ 1 INTRODUÇÃO À LINGUAGEM C

1.2 Falcon C++


Para criar um programa em linguagem C, primeiro produzimos um arquivo
fonte que contém a lógica e sequência de operações do problema que queremos
resolver. Esse arquivo é escrito em um editor de textos e depois de produzido
é transformado em um arquivo objeto pelo compilador. Em seguida, ocorre
a ligação desse código objeto com rotinas definidas nas bibliotecas utilizadas,
dando origem a um programa executável.

Durante o curso, usaremos o compilador IDE (Integrated Development En-


vironment) Falcon C++, que pode ser usado tanto para desenvolvimento de
programas em C como em C++. Listamos abaixo dois procedimentos básicos
desse programa:
Criando um novo código fonte:

• Clique em Arquivo > Novo > Arquivo Novo;


• Uma nova janela irá abrir-se, escreva o código do seu programa nessa
janela;

Compilando o código fonte:

• Clique em Executar > Compilar;


• Escolha um nome e local para salvar o arquivo;
• O arquivo executável (.exe) será salvo na mesma pasta do código fonte e
com o mesmo nome.

A maioria das dúvidas que porventura surgirem sobre algum procedimento mais
elaborado, pode ser sanada no arquivo de ajuda do programa, em Ajuda > Ajuda
sobre o Falcon C++.

1.3 Tipos de Variáveis


Variáveis são abstrações de um local de memória onde se guarda informação
e quase toda operação em C é realizada com o auxı́lio delas. Para utilizar uma
variável, precisa-se, antes de qualquer coisa, declará-la; um procedimento que é
realizado utilizando a seguinte sintaxe:

/*sintaxe da declaração de uma variável*/


tipo de variavel nome;

Os nomes de variáveis devem ter duas condições satisfeitas:

1. Começar com letras ou (sublinhado);

2. Os caracteres seguintes podem ser letras, números ou (sublinhado).

5
1.4 Incluindo Bibliotecas 1 INTRODUÇÃO À LINGUAGEM C

Obs: O C faz distinção entre letras maiúsculas e minúsculas (case sensi-


tive), de modo que duas variáveis declaradas a1 e A1 correspondem a variáveis
distintas.

Exemplo 1.1: Possı́veis declarações:

x, a, A, b3, Nome123, p3t e 1337;

Exemplo 1.2: Declarações inválidas:

3, 007, 1variavel, *oi, %pet e <eletrica> ;

Ao declarar uma variável, devemos especificar um tipo e este diz quais va-
lores podem ser armazenados na região da memória associada à variável, como
esses valores são representados e quais operações envolvendo essa variável serão
válidas.

Tipo de de variáveis Descrição Memória (bytes)


Char Caractere 1
Int Inteiro 2
Float Real 4
Double Dupla precisão 8

/*Exemplo de declaração de variáveis:*/


int num;
char l;
float a;

1.4 Incluindo Bibliotecas


Uma biblioteca é um arquivo onde várias funções, geralmente associadas a
um tipo de processamento em especı́fico, são guardadas.

A maioria das funções utilizadas em um programa em C está implemen-


tada em um arquivo separado, e, para que alguma função esteja acessı́vel no
programa, é necessário incluir esse arquivo da seguinte forma:

/*sintaxe da declaração de uma biblioteca*/


#include <nomedabiblioteca.h>

A sintaxe acima é válida para bibliotecas padrões do C. Além das biblio-


tecas padrões, existem bibliotecas não-padronizadas, nas quais outros tipos de

6
1.5 Funções de Entrada-Saı́da padrões1 INTRODUÇÃO À LINGUAGEM C

funções são armazenadas.

Através da diretiva de pré-processamento#include, o programador também


pode incluir em seu programa arquivos especı́ficos, desde que ele diga o local da
memória onde o arquivo se encontra.
A stdio.h e stdlib.h são as bibliotecas mais comumente usadas, nelas estão
as funções básicas de entrada e saı́da.

1.5 Funções de Entrada-Saı́da padrões


1.5.1 Printf
O printf é uma função de saı́da que permite escrever no dispositivo de saı́da
padrão, geralmente o monitor. Sua sintaxe é descrita abaixo:

/*sintaxe do printf*/
printf (”expressão de controle”, lista de argumentos);

A expressão de controle deve conter o texto que será exibido na tela, além
disso, devem ser incluı́das nesse texto as variáveis que serão exibidas. Para tal se
utiliza um código de controle, onde se deseja que apareça o valor da variável.
O código informa ao compilador como a variável deve ser apresentada. Abaixo,
na tabela 1, são apresentados os códigos de controle mais frequentemente utili-
zados por programadores:

Código Significado
%d Inteiro
%f Float
%c Caractere
%s String
%h Inteiro Hexadecimal com letras maiúsculas
%% Imprime um %

Outros exemplos de comandos bastante utilizados em expressões de controle


são o \n, que inicia uma nova linha, e o \t, que insere uma tabulação.

Exemplo 1.3: Uso da função printf :

#include<stdio.h>
#include<stdlib.h>

int main(){
printf("tudo bem? \n");
printf("%f \n", 3.1415);

7
1.5 Funções de Entrada-Saı́da padrões1 INTRODUÇÃO À LINGUAGEM C

printf("um inteiro %d e um caractere %c \n", 11, ’a’);


printf("%s composta \n", "Frase");
printf("%s%d %% \n", "Taxa de ", 5);

system("pause");
}

1.5.2 Scanf
Para se fazer leituras da entrada padrão, normalmente pelo teclado, usa-se
a função scanf, também definida na biblioteca stdio.h. Sua sintaxe lembra a do
printf :

/*sintaxe do scanf*/
scanf (”expressão de controle”, lista de argumentos);

A expressão de controle deve conter os códigos na ordem em que os da-


dos devem ser lidos. Já na lista de argumentos devem ser especificadas quais
variáveis vão receber os valores lidos.

Exemplo 1.4 Uso da função scanf :

scanf("%d", &int1);
scanf("%c", &char1);
scanf("%d%c", &int1, &char1);

Observação: É importante colocar o operador & antes do nome da variável


na lista de argumentos. O motivo para esse procedimento será entendido mais
adiante.

Agora que aprendemos a usar as funções printf e scanf, vejamos um exemplo


de programa que utiliza essas duas funções em conjunto:

Exemplo 1.5: Programa que implementa as funções printf e scanf :

#include<stdio.h>
#include<stdlib.h>
int main(){
int inteiro1, inteiro2;
printf("Entre com o primeiro numero inteiro\n");
scanf("%d", &inteiro1);
printf("Entre com o segundo numero inteiro\n");

8
1.6 Operadores 1 INTRODUÇÃO À LINGUAGEM C

scanf("%d", &inteiro2);
printf("A soma e %d\n", inteiro1 + inteiro2);
system("pause");
return 0;
}

1.6 Operadores
1.6.1 Aritméticos e de Atribuição
Os operadores aritméticos são sı́mbolos utilizados para realizar operações
matemáticas. Eles podem ser unários ou binários, que agem sob uma ou duas
variáveis, respectivamente.

Operador Ação Tipo


+ Soma variáveis Unário ou Binário
- Subtrai variáveis Unário ou Binário
* Multiplica variáveis Binário
/ Divide variáveis Binário
% Retorna o resto da divisão inteira Binário
++ Incrementa uma variável Unário
-- Decrementa uma variável Unário

Os cinco primeiros operadores da tabela acima retornam o resultado de suas


operações sem alterar o valor das variáveis sobre as quais eles agem. Já os dois
últimos operadores, de incremento e decremento, além de retornar o valor da
operação, também alteram o valor da variável para o valor retornado.

Os valores retornados por operações aritméticas podem ser guardados em


outra variável, desde que o tipo de dado retornado seja o mesmo do tipo de
variável na qual o dado será armazenado. Para realizar essa operação, a atri-
buição, usa-se o operador =, que guarda o valor da expressão da direita na
variável da esquerda, Vejamos sua sintaxe:

/*Sintaxe do operador de atribuição:*/


variável = expressão aritmética;

Exemplo 1.6: Uso dos operadores aritméticos:

9
1.6 Operadores 1 INTRODUÇÃO À LINGUAGEM C

a = 3;
b = (3 + 3.14)/5;
c = 1;
c++;
d = ((132324%3)*3)–;
e = -a;
f = a++;
g = ++a;
h = ((a++)+(–a))/2;

1.6.2 Relacionais e Lógicos


Os operadores relacionais realizam comparação entre variáveis. Abaixo, são
apresentados em formato de tabela:

Operador Significado
> Maior
>= Maior ou igual
< Menor
<= Menor ou igual
== Igual
!= Diferente
A expressão utilizando esses operadores retorna 1 caso a expressão seja ver-
dadeira e 0 caso ela seja falsa.

Exemplo 1.7: Uso dos operadores relacionais:

C = 3>2, (C=1)
D = (10 == 9) (D = 0)
E = ((1<3) == 1) (E =1 )
F = A>B
Já os operadores lógicos realizam três operações lógicas básicas, são elas:

Operador Significado
&& E (and)
|| OU (or)
! NÃO (not)

O operador && retorna 1 (verdadeiro) caso as expressões a sua direita e a


esquerda sejam ambas verdadeiras. O operador | | retorna 1 (verdadeiro) caso
uma das duas seja verdadeira e o operador ! inverte o valor lógico da variável.

10
1.7 Biblioteca matemática 1 INTRODUÇÃO À LINGUAGEM C

Vale lembrar que em C, qualquer valor diferente de 0 é interpretado logica-


mente como verdadeiro e o número 0 é interpretado como falso.

Exemplo 1.8: Uso dos operadores lógicos:

A = (5>3)&&(3<1) (A = 0)
B = (5>3)| |(3<1) (A = 1)
C = !!5 (C = 1)

1.7 Biblioteca matemática


A linguagem C dispõe de algumas funções especiais para operações ma-
temáticas, para trabalhar com estas funções deve-se usar em cada algoritmo
a biblioteca math.h.

#include < math.h >


Existem diversas funções disponı́veis, como de potência, de arredondamento,
trigonométricas e outras. Segue uma tabela com algumas.

Funções básicas da biblioteca matemática

11
1.8 Exercı́cios de Revisão 1 INTRODUÇÃO À LINGUAGEM C

Função Descrição Exemplo


sqrt( x ) Raiz quadrada de x sqrt(900.0) é 30.0
sqrt(9.0) é 3.0
exp( x ) Função exponencial ex exp(1.0) é 2.718282
exp(2.0) é 7.389056
log( x ) Logaritmo natural de x log(2.718282) é 1.0
log(7.389056) é 2.0
log10( x ) Logaritmo de x log10(1.0) é 0.0
log10(10.0) é 1.0
log10(100.0) é 2.0
fabs(x) Valor absoluto de x fabs(13.5) é 13.5
fabs(0.0) é 1.0
fabs(-13.5) é 13.5
ceil(x) Arredonda x ao menor inteiro não menor que x ceil(9.2) é 10.0
ceil(-9.8) é -9.0
floor(x) Arredonda x ao maior inteiro não maior que x floor (9.2) é 9.0
floor(-9.8) é -10.0
pow(x,y) x elevado à potência y pow(2,7) é 128.0
pow(9, 0.5) é 3.0
fmod(x,y) Módulo(resto) de x/y como um número em ponto flutuante fmod(13.657, 2.333) é 1.992
sin(x) Seno trigonométrico de x(x em radianos) sin(0.0) é 0.0
cos(x) Cosseno trigonométrico de x(x em radianos) cos(0.0) é 1.0
tan(x) Tangente trigonométrico de x(x em radianos) tan(0.0) é 0.0

1.8 Exercı́cios de Revisão


I - Escreva um programa que receba quatro números e calcule a média
aritmética, a soma e o produto de todos os números e exiba o resultado na
tela.

II - Escreva um programa que receba dois números a e b. Utilizando os


operadores lógicos, calcule a expressão (Não(a) E Não(b)) e exiba o resultado
na tela.

III -Faça um programa para receber um grupo de 3 valores reais, exibir


os valores lidos e determinar o menor e o maior valor existente, sem utilizar
estruturas de seleção.

12
2 ESTRUTURAS DE SELEÇÃO

2 Estruturas de seleção
2.1 if
A instrução if tem a seguinte forma geral:

/* Sintaxe da instrução de controle if*/


if (condição){
comandos;
}

Quando o argumento da instrução if (condição) for verdadeiro (valores dife-


rentes de zero), o comando ou blocos de comandos é executado e quando é falso
(valor zero) o comando é ”ignorado”.

Vale salientar que ao fim da instrução if não se usa ponto-e-vı́rgula (;).

Exemplo 2.1: Programa utilizando a estrutura if :

#include<stdio.h>
#include<stdlib.h>

int main(){
int num1, num2;
printf("Informe dois numeros inteiros para que seja ");
printf("determinado o relacionamento entre eles\n");
scanf("%d%d", &num1, &num2);
if(num1 == num2)
printf("%d e igual a %d", num1, num2);
if(num1 != num2)
printf("%d e diferente de %d", num1, num2);
if(num1 < num2)
printf("%d e menor que %d", num1, num2);
if(num1 > num2)
printf("%d e maior que %d", num1, num2);
system("pause");
return 0;
}

13
2.2 if/else 2 ESTRUTURAS DE SELEÇÃO

2.2 if/else
A instrução if-else tem a seguinte forma geral:

/*Sintaxe da instruç~
ao de controle if-else */

if(condiç~
ao){
Comandos1;
}
else{
Comandos2;
}

Quando o argumento da instrução if (condição) for verdadeiro (valores dife-


rentes de zero), o comando ou blocos de comandos dentro do bloco if (no caso da
sintaxe acima, comandos1) é executado; quando é falso (valor zero), o comando
dentro do if é “ignorado” (comandos1) e o comando ou blocos de comandos
dentro do else é executado (no caso da sintaxe em questão, comandos2).

if( variavel1 > variavel2){


printf("%d é maior que %d \n", variavel1, variavel2);
}else{
printf("%d é maior ou igual que %d\n", variavel2,variavel1);
}

if (condiç~
ao_1) comando_1;
else if (condiç~
ao_2) comando _2;
else if (condiç~
ao_3) comando _3;
[...]
else if (condiç~
ao_n) comando _n;
else ultimocomando;

Exemplo 2.2: Programa utilizando a estrutura if-else:

14
2.3 switch 2 ESTRUTURAS DE SELEÇÃO

#include<stdio.h>
#include<stdlib.h>

int main(){

int numero;

printf("Digite um numero :\n");


scanf("%d", &numero);
if(numero > 20){
printf("O numero eh maior que 20");
}else if(numero < 20){
printf("O numero eh menor que 20");
}else{
printf("O numero eh igual a 20");
}
system("pause");
return 0;
}

2.3 switch
Outra instrução de controle bastante usada é o switch. Sua forma geral é:

/* Sintaxe da instruç~
ao de controle switch*/

switch(variavel){
case constante1:
comandos;
break;
case constante2:
comandos;
break;
[...]

15
2.3 switch 2 ESTRUTURAS DE SELEÇÃO

case constanten:
comandos;
break;
default:
comandos;
break;
}

A instrução switch é bastante usada para substituir várias condições, evi-


tando assim o uso excessivo da instrução if ou de cadeias if-else-if. A principal
diferença do switch é que a sua estrutura não aceita expressões e sim, constan-
tes. O switch testa a variável e executa a declaração cujo case corresponda ao
valor atual da variável. A declaração default é opcional e será executada ape-
nas se a variável, que está sendo testada, não for igual a nenhuma das constantes.

O comando break interrompe a execução de um comando. No caso do switch,


o break faz com que ele seja interrompido assim que a declaração for executada.
Se não houver o break, o programa executará todos os casos seguintes, sem testá-
los, até encontrar um break ou o switch chegar ao seu fim. Ou seja, o uso do
break não é obrigatório, mas é bastante recomendado.

Exemplo 2.3: Uso do switch:

switch(numero){
case 1:
printf("O numero e igual a 1");
break;
case 2:
printf("O numero e igual a 2");
break;
case 80:
printf("O numero e igual a 80");
break;
default:
printf("O numero nao e nem 1, nem 2 e nem 80");
break;
}

16
2.4 O operador ternário 2 ESTRUTURAS DE SELEÇÃO

Observação: Tente executar o programa acima sem o break e veja o que


acontece.

2.4 O operador ternário


Este operador se torna útil para substituir instruções if-else, simplificando o
programa e tem a seguinte sintaxe:

*Sintaxe do operador ternário*/


condição ? expressão 1:expressão 2;

Esta forma pode ser substituı́da por:

if(condiç~
ao)
Express~
ao_1;
else
Express~
ao_2;

Assim, se a condição for verdadeira, o operador exibe apenas a expressão 1,


caso contrário, exibe a expressão 2.

Exemplo 2.4: Uso do operador ternário:

if( a < 0)
b = 2;
else
b = 3;
Que pode ser substituı́do por apenas uma linha:
b = a < 0 ? 2 : 3 ;

2.5 Exercı́cios de Revisão


I - Faça um programa que verifique se um número é divisı́vel por 2.

II - Faça um programa que informe o mês de acordo com o número infor-


mado pelo usuário. (Exemplo: Entrada: 4. Saı́da: Abril.)

17
3 ESTRUTURAS DE REPETIÇÃO

3 Estruturas de Repetição
3.1 while
O while é útil para realizar operações repetidas submetidas a uma condição
que muda com o tempo. Sua sintaxe é:

/*Sintaxe do While*/
ao) {
while (condiç~
comandos;
}

Enquanto a condição for verdadeira, os comandos serão executados. Cada


iteração é comumente chamada de laço.
Observação: a condição é testada antes do laço ser executado.

Uma analogia com a instrução if seria:

ao) {
if (condiç~
comandos;
"Volte para o comando if"
}

Exemplo 3.1: Programa que utiliza o while:

#include <stdio.h>
#include <stdlib.h>
int main(){
int inteiro = 1, n, somatorio = 0;
printf ("Calculo do Somatorio dos n primeiros inteiros");
printf(" positivos.\n");
scanf ("%d", &n);
while (inteiro <= n) {
somatorio += inteiro;
inteiro += 1;
}

18
3.2 do/while 3 ESTRUTURAS DE REPETIÇÃO

printf ("Somatorio: %d \n", somatorio);


system ("pause");
return 0;
}

O programa ficará preso ao laço até que n atinja o seu valor máximo.

3.2 do/while
O do/while tem ação bastante semelhante à do comando while, sua forma
geral é:

/* Sintaxe do Do/While */
do {
comandos;
} while (condiç~
ao);

A diferença entre este comando e o while é que, no do/while, a primeira


iteração é realizada antes de ser analisada a condição, enquanto que no while,
primeiro se analisa a condição para depois começar a iteração.

Exemplo 3.2: Programa que utiliza o do-while:

#include <stdio.h>
#include <stdlib.h>

int main(){
int contador = 1;
do {
printf ("%d \n" , contador);
contador++;
} while (contador <= 10);
system ("pause");
return 0;
}

19
3.3 for 3 ESTRUTURAS DE REPETIÇÃO

3.3 for
O comando for é a terceira estrutura para se trabalhar com loops de re-
petição. Sua forma geral é:

/* Sintaxe do For */
for (inicializaç~ ao; incremento/decremento) {
ao; condiç~
comandos;
}

Na estrutura do for, temos a inicialização da variável do contador, uma


condição de parada (geralmente relacionada ao contador), o incremento (ou
decremento) do contador e os comandos a serem realizados. A sua execução
começa com a inicialização, seguida pela verificação da condição de parada,
execução das instruções(se a condição for verdadeira) e, finalmente, a execução
do incremento (ou decremento). Uma analogia interessante com a instrução if
é:

inicializaç~
ao;
ao) {
if (condiç~
comandos;
incremento;
"Volte para o comando if"
}

Exemplo 3.3: Programa que utiliza o for :

/* Programa que imprime números de 1 a 100 */

#include <stdio.h>
#include <stdlib.h>
int main () {
int contador;

for (contador = 1; contador < = 100; contador++)


printf ("%d \n" , contador);
system ("pause");

20
3.4 Exercı́cios de Revisão 4 ESTRUTURAS DE DADOS

return 0;
}

3.4 Exercı́cios de Revisão


1. Multiplicar os 10 primeiros números naturais diferentes de 0.
1
2. Calcule a soma dos 100 primeiros termos da função harmônica. (an = n)

4 Estruturas de Dados
4.1 Vetores/Arrays Unidimensionais
Em C, um array é um grupo de locais de memória relacionados pelo fato
de que todos têm o mesmo nome e o mesmo tipo. Para fazer referência a um
determinado local ou elemento dele, especificamos o nome do array e a posição
em que o elemento se encontra. Os nomes dos arrays seguem as mesmas con-
venções para as declarações de outras variáveis. Esse tipo de estrutura de dados
tem uma aplicação bastante vasta. A declaração de um vetor pode ser feita da
seguinte forma:

/*Declaração de um vetor*/
tipo nome do vetor[número de elementos];

Ao ler essa declaração, o compilador reserva na memória espaço suficiente


para armazenar o número de elementos especificado nela. Por exemplo:

char nome[30];

O vetor nome possui 30 elementos do tipo char, sendo alocado na memória


do computador o espaço necessário para representá-lo totalmente, no caso 30
bits, pois o tipo de variável char agrega um valor de 1 byte.
Para nos referirmos a um elemento especı́fico do vetor, devemos usar o
nome deste vetor e um ı́ndice. Os ı́ndices válidos começam em 0 e vão ate
(número de elementos)-1. Além de se poder usar um número inteiro constante
no ı́ndice de um vetor, também é possı́vel usar variáveis inteiras, de forma que
essas estruturas têm uma importância essencial em processos iterativos como
for e while.

O vetor nome possui ı́ndices válidos de 0 a 29. O Dev-C++ não considera


um erro de sintaxe utilizar um ı́ndice fora dos limites. Então, caso seu código
fonte tenha a linha nome[50], por exemplo, o compilador, não irá apontar erro

21
4.1 Vetores/Arrays Unidimensionais 4 ESTRUTURAS DE DADOS

de sintaxe e o programa será compilado, embora possa ocorrer algum resultado


inesperado durante a sua execução.

Convém observar que os elementos de um array também podem ser iniciali-


zados na sua declaração com um sinal de igualdade e uma lista de inicializadores,
entre chaves e separados por vı́rgula. Caso haja menos inicializadores do que
o número de elementos do array, os elementos restantes são inicializados auto-
maticamente com o valor zero. Já se o tamanho do array for omitido de uma
declaração com uma lista de inicializadores, o número de elementos do array
será o número de elementos da lista.

Exemplo 4.1: Declaração de um array:

int array[10]= {0,1,2,3,4,5,6,7} ;


char palavra[]={‘p’, ‘r’, ‘i’, ‘m’, ‘e’, ‘i’, ‘r’, ‘o’, ‘\0’};

Exemplo 4.2: Usos corretos e incorretos de vetores:

int idades[100];
int i=5;

Corretos:

idades[10]=idades[50];
idades[0]=idades[3]-idades[8];
idades[i]=idades[i+5];

Incorretos:

idades[100]=idades[0];
idades[-1]=idades[3];
idades=idades+1;

Exemplo 4.3: Ilustração do uso de vetores em um processo iterativo:

/*Calcula a média dos números inteiros inseridos pelo usuário*/


#include <stdio.h>

22
4.2 Strings na Linguagem C 4 ESTRUTURAS DE DADOS

#include <stdlib.h>
int main (){
int numeros[50]={0};
int i,j;
int total=0;
float media;
printf("Insira numeros inteiros para calcular a");
printf(" media (para parar a insercao digite -1 \n):");
for (i=0;numeros[i-1] !=-1; i++)
scanf("%d", &numeros[i]);
i--;
for (j=0; j!=i; j++)
total = total+numeros[j];
media = (float)total/i;
printf("\n\nA media dos numeros eh %f\n", media);
system("pause");
return 0;
}

O programa do Exemplo 4.3 recebe números inteiros e armazena em um


vetor, a leitura continua até que o usuário insira o número -1, em seguida, a
média é calculada. Entenda esse programa, copie no seu IDE e tente alterá-lo
para que o programa imprima todos os números da série no seguinte formato:
números = [n1,n2,n3,(...),nmax].

4.2 Strings na Linguagem C


String é a denominação dada a uma cadeia de caracteres em sequência que
formam uma palavra. Na linguagem C, o uso de strings é bastante restrito pelo
fato do compilador tratar exclusivamente um string como um vetor de caracte-
res terminado pelo caractere especial ‘\0’.

Exemplo 4.4: Declaração de uma string :

char palavra[]={‘A’, ‘m’, ‘i’, ‘g’, ‘o’, ‘\0’};

Também é possı́vel criar uma string fazendo o vetor do tipo char receber a
palavra entre aspas. Observe o Exemplo 4.5.

23
4.2 Strings na Linguagem C 4 ESTRUTURAS DE DADOS

Exemplo 4.5: Declaração de uma string :

char palavra[]=“Amigo”;

Dessa forma o compilador cria um array com o tamanho mı́nimo necessário


para salvar a palavra desejada na memória, além de reservar automaticamente
a última posição do vetor para o caractere especial ’\0’. O uso dessa notação
se faz muito cômoda, pois o programador não precisa contar a quantidade de
letras que a palavra contém antes de declarar o array.
A dificuldade de trabalhar com strings na linguagem C pode ser sentida em
códigos que necessitem a comparação entre esses dois tipos de elementos. O
Exemplo 4.6 ilustra esse problema.

Exemplo 4.6:

#include <stdio.h>

int main(int, char **)

char ola[] = "ola";


char ola2[] = "ola";

if(ola == ola2)
printf("Iguais");
else
printf("Nao sao iguais");

return 0;

O programa do Exemplo 4.6 imprime como resultado ”Nao sao iguais”.


Isso ocorre pois o argumento do if está comparando dois endereços de memória
distintos. Uma solução para este problema é proposta como exercı́cio na seção
6.5.
Apesar da dificuldade, a biblioteca string.h diponibiliza uma vasta quanti-
dade de funções próprias para operações envolvendo strings.

24
4.3 Matrizes 4 ESTRUTURAS DE DADOS

4.3 Matrizes
Matrizes têm a maioria das caracterı́sticas semelhantes aos vetores. A dife-
rença primordial é o número de dimensões que as matrizes possuem. Enquanto
vetores possuem apenas uma dimensão, matrizes possuem n dimensões. Um
caso particular é o de matrizes bidimensionais (n=2). Vejamos a sintaxe para a
declaração desta matriz:

/* Declaração de uma matriz bidimensional */


tipo nome da matriz[número de linhas][número de colunas];

Para referenciar um elemento particular da matriz, devem-se utilizar dois


ı́ndices: o número da linha e o da coluna do elemento que se deseja acessar.
Assim como em vetores, o compilador não verifica se o ı́ndice está dentro dos
limites permitidos, ficando a cabo do programador essa tarefa.

Um array com vários subscritos, vetor de várias dimensões, pode ser inicia-
lizado em sua declaração da mesma forma que um array unidimensional.

Exemplo 4.4: Declaração de um array bidimensional:

int tabela[2][2] = {{1,2},{3,4}};

Exemplo 4.5 Utilização de matrizes bidimensionais:

#include <stdlib.h>
#include <stdio.h>
int main (){
int matriz[20][10];
int i,j,k;
k=1;
for (i=0; i <20; i++){
for (j=0;j<10;j++){
matriz[i][j]=k;
printf("%d\t", matriz[i][j]);
k++;
}
printf("\n");
}
system("pause");

25
4.4 Exercı́cios de Revisão 5 NÚMEROS PSEUDOALEATÓRIOS

return 0;
}

O programa do Exemplo 4.5 preenche uma matriz 20x10 com valores de 1 a


200.

Matrizes com dimensões maiores que dois têm propriedades análogas às das
matrizes bidimensionais. Para declarar uma matriz n-dimensional, usa-se a
seguinte sintaxe:

/* Sintaxe para declaração de matrizes n-dimensionais */


tipo nome da matriz[tamanho 1][tamanho 2][tamanho
3]...[tamanho n-2][tamanho n-1][tamanho n];

4.4 Exercı́cios de Revisão


I - Faça um vetor de tamanho 50 preenchido com o seguinte valor (i+(3*(i-
2)))%(i+1), sendo i a posição do elemento no vetor, em seguida exiba o vetor
na tela.

II - Faça um programa que preenche uma matriz quadrada 5x5 com 1’s na
diagonal principal(matriz identidade) e a exibe na tela.

III - Faça um programa que preencha uma matriz, em que cada elemento
possua o valor resultante do produto entre o seu ı́ndice da linha e o da coluna,
depois a exiba na tela.

IV - Faça um programa para receber uma matriz 4x4 de números inteiros


e determinar e mostrar as posições dos elementos que são maiores que a média
deles.

5 Números Pseudoaleatórios
5.1 Visão Geral
Muitas aplicações, principalmente jogos, exigem o uso de números aleatórios
para diversas funcionalidades. Um computador digital não é capaz de gerar um
número totalmente aleatório, pois é um sistema determinı́stico. No entanto,
é possı́vel, utilizando uma função da biblioteca stdlib.h, gerar números com
uma distribuição probabilı́stica aproximadamente uniforme: são os números
pseudoaleatórios.

26
5.2 Exercı́cios de Revisão 6 FUNÇÕES

Para gerar números pseudoaleatórios, usa-se a função rand(), que retorna


um número pseudoaleatório do conjunto dos inteiros.
Se o comando a seguir for executado:

for (i=0; i < 10; i++){


printf ("%d", rand()%6);
}

Será gerada uma sequência de dez números entre 0 e 5. Mas, se o comando


for executado novamente, os mesmos números serão gerados. Isto ocorre devido
às condições iniciais para a execução serem as mesmas. Para que isso não ocorra,
deve-se enviar uma “semente” (um valor arbitrário) como entrada ao sistema.

Para enviar uma semente à função rand(), devemos usar a função srand(num),
que é uma função que não retorna nenhum valor, portanto, não pode ser atribuı́da
à uma variável qualquer, e ainda, ”num”é um inteiro que serve como semente.
É interessante que a cada execução do programa uma semente diferente seja
enviada e uma forma de fazer isso é enviar um valor que mude frequentemente.

Uma das sementes mais usadas pelos programadores é o tempo do relógio


do computador, que muda constantemente, é quantidade de segundos passados
desde 1 de janeiro de 1970. Esse valor é retornado pela função time(NULL), da
biblioteca time.h. Para inseminar a função rand() com o valor do clock, digita-se
o seguinte comando:

srand(time(NULL));

Desta forma, a cada execução, os números pseudoaleatórios gerados serão


diferentes, dando mais confiabilidade ao sistema.

5.2 Exercı́cios de Revisão


1- Faça um programa que simule o lançamento de dois dados, d1 e d2, n
vezes. A saı́da do programa deverá ser o número de cada dado e a relação entre
eles (>,<,=) de cada lançamento.

6 Funções
6.1 Visão Geral
Quando se está programando e há a necessidade de fazer um programa
grande e complexo, é bom dividi-lo em blocos que realizam determinadas tarefas.

27
6.1 Visão Geral 6 FUNÇÕES

Para esses blocos dá-se o nome de funções.


Exemplo 6.1: Sintaxe de uma função:

tipo de retorno nome da funcao(par^


ametros){
comandos;
}

O tipo de retorno é o tipo do valor que a função retornará. Caso este tipo
não seja especificado, a função retornará um inteiro. Os parâmetros são uma
lista de valores, cada um com seu tipo, que a função recebe, ou seja, é a entrada
da função e pode ter a seguinte forma:

(parâmetros) = (tipo nome1, tipo nome2, ..., tipo nomeN);

Exemplo 6.2: Função para calcular o quadrado de um número:

#include<stdio.h>
#include<stdlib.h>

int quadrado (int a){


return(a*a);
}

int main(){

int numero;

printf ("\nEntre com um numero: ");


scanf ("% d", &numero);
numero = quadrado(numero);
printf("\n O quadrado vale: %d\n", numero);
system("pause");
return 0;

28
6.1 Visão Geral 6 FUNÇÕES

Toda função necessita ser chamada. Pode-se perceber que, no exemplo, a


chamada da função é:

numero = quadrado(numero);

No Exemplo 6.2, a entrada da função quadrado é numero, que é o seu argu-


mento. O parâmetro da função é int a, de forma que a recebe o valor da
entrada da função, ou seja, os parâmetros recebem os valores dos argumentos
da chamada da função. As linhas de comando da função devem ser processadas
e o dado final, retornado. Deve-se atentar ao tipo de retorno declarado durante
a criação da função, de modo que seja compatı́vel com o que realmente será
retornado. No exemplo, como a função quadrado recebe um número inteiro, o
retorno a*a também deverá ser do tipo inteiro.

Exemplo 6.3: Função para identificar se um número é ou não par:

#include<stdio.h>
#include<stdlib.h>

int EhPar ( int b){


if (b % 2)
return 0;
else
return 1;
}

int main(){

int numero;

printf ("Entre com um numero: ");


scanf ("%d", &numero);
if (EhPar(numero))
printf("\nO numero eh par\n");
else
printf("\n numero eh impar\n");
system("pause");
return 0;

29
6.2 Protótipo 6 FUNÇÕES

6.2 Protótipo
Nos exemplos mostrados anteriormente, as funções foram escritas antes da
função principal main. O objetivo desta prática é de informar ao compilador
com antecedência quais serão os parâmetros e os tipos de retorno das funções
que serão utilizadas, a fim de garantir uma execução correta do programa. Para
uma programação mais organizada, deve-se fazer o uso de protótipos, que reali-
zam a tarefa de informar ao compilador quais as funções que serão utilizadas, o
seu tipo de retorno e os tipos dos parâmetros, sendo colocados antes da função
main, enquanto que as declarações das funções correspondentes virão depois
dela.

Exemplo 6.4: Forma geral do protótipo de uma função:

tipo de retorno nome da função (parâmetros);

Os dados informados no protótipo (tipo de retorno, nome da função e parâmetros)


devem ser equivalentes aos usados na função. A seguir, encontram-se os exem-
plos usados na Subseção 6.1 modificados, com o uso de protótipos:

Exemplo 6.5: Usando protótipo para a função de calcular o quadrado de


um número:

#include<stdio.h>
#include<stdlib.h>

int quadrado (int a);


int main(){

int numero;

printf ("Entre com um numero: ");


scanf ("%d", &numero);
numero = quadrado(numero);
printf("\n O quadrado vale: %d\n", numero);

system("pause");

30
6.2 Protótipo 6 FUNÇÕES

return 0;
}

int quadrado (int a){


return(a*a);
}

Exemplo 6.6: Usando protótipo para a função de identificar se um número


é ou não par:

#include<stdio.h>
#include<stdlib.h>

int EhPar (int b);


int main(){

int numero;
printf ("Entre com um numero: ");
scanf ("%d", &numero);
if (EhPar(numero))
printf("\nO numero eh par\n");
else
printf("\nO numero eh impar\n");
system("pause");
return 0;
}

int EhPar ( int b){


if (b % 2)
return 0;
else
return 1;
}

31
6.3 Função Sem Retorno e/ou Sem Entradas 6 FUNÇÕES

6.3 Função Sem Retorno e/ou Sem Entradas


Há casos em que não é necessário que a função retorne algum valor. Quando
isto ocorre, a função é declarada com o tipo void.

Exemplo 6.7: Forma geral do protótipo de uma função sem retorno:

void nome da função (parâmetros);

Também há funções que não recebem entradas. Assim, o protótipo delas fica
da seguinte forma:

Exemplo 6.8: Forma geral do protótipo de uma função sem entradas:

tipo de retorno nome da função (void);

Nessa situação, pode-se usar apenas “()” em vez de “(void)”.


Há casos em que as funções não recebem entradas nem retornam nenhum
valor, como, por exemplo, funções que exibem mensagens para o usuário.

Exemplo 6.9: Forma geral do protótipo de uma função sem retorno e


entradas:

void nome da função (void);

Exemplo 6.10: função void-void (função sem parâmetros de entrada e sem


retorno):

#include<stdio.h>
#include<stdlib.h>

void mensagem (void);


int main(){

mensagem();
printf("\nRepita!\n");
mensagem();
system ("pause");
return 0;
}

void mensagem(void) {

32
6.4 Vetores como parâmetros de funções 6 FUNÇÕES

printf("\nPET Eletrica\n");
}

6.4 Vetores como parâmetros de funções


Assim como são passadas variáveis como parâmetros de funções, também é
possı́vel a passagem de vetores. No entanto, quando uma variável comum é pas-
sada, o que a função recebe é somente o valor da mesma, que é armazenado em
outra variável temporária. Quando os vetores são passados para as funções, é o
endereço do primeiro elemento do vetor que é passado, de forma que a função
pode acessar e modificar todos os elementos do mesmo.

Para passar, por exemplo, um vetor unidimensional, basta que no protótipo


da função seja especificado o nome do array seguido de []. Para vetores mul-
tidimensionais, basta que no protótipo seja especificado o tamanho de suas di-
mensões, podendo ser ocultado apenas o tamanho da dimensão mais à esquerda,
colocando-se apenas [ ] ou um *.

Exemplo 6.11: Protótipos de funções que recebem vetores como parâmetro:

void funcao1 (int matriz1[][50]); // matriz1 é bidimensional


void funcao2 (int matriz2[]); //matriz2 é unidimensional

Há programas em que o array estará completamente preenchido e seu ta-


manho previamente determinado. Deste modo, se a capacidade do vetor é de
10 elementos e o programador cria, por exemplo, uma função para imprimir
os elementos, ele usará o tamanho como condição de parada em um laço que
percorra o vetor. Porém, em alguns casos, pode não ser necessário o uso de to-
dos os elementos do array, por exemplo, quando ele não estiver completamente
preenchido. Nestes casos o número de elementos preenchidos deve ser passado
como um dos parâmetros da função e usado como condição de parada nos laços
que percorram o vetor.

Exemplo 6.12: Funções que recebem vetores como parâmetros:

#include<stdio.h>
#include<stdlib.h>

void exibe array biD(int[ ] [3]);


void exibe array uniD(int[ ], int);
void preenche array uniD(int[ ], int );

33
6.4 Vetores como parâmetros de funções 6 FUNÇÕES

int main(){

int array1[10];
int tam1;
int array2[2][3] = {1, 2, 3, 4, 5};
int array3[2][3] = {{1, 2}, {4}};

printf("\nEntre com o tamanho do array1 (maximo 10): ");


scanf ("%d", &tam1);
preenche array uniD(array1, tam1 );
printf("\nnValores do array1: ");
exibe array uniD(array1, tam1);
printf("\nValores do array2 por linha: ");
exibe array biD(array2);
printf("\nValores do array3 por linha: ");
exibe array biD(array3);

system("pause");
return 0;
}

void preenche array uniD(int a[ ], int tam) {


int i;
printf("\nEntre com os elementos do vetor: ");
for (i=0; i < tam; i++){
scanf("%d", &a[i]);
}
}

void exibe array uniD(int a[], int tam){


int i;
for (i=0; i<tam; i++){
printf("%d", a[i]);

34
6.5 Exercı́cios de Revisão 6 FUNÇÕES

}
}

void exibe array biD (int a[ ][3]){

int i, j;
for (i=0; i <= 1; i++) {
for (j=0; j <= 2; j++) {
printf("%d", a[i][j]);
}
printf("\n");
}
}

6.5 Exercı́cios de Revisão


I - a) Escreva uma função que recebe um número inteiro n > 0 e devolve o
número de dı́gitos de n e o primeiro dı́gito de n.

b)Escreva um programa que leia uma sequência de n inteiros positivos e exiba


o número de dı́gitos e o primeiro dı́gito de cada um deles.

II - Um número a é dito permutação de um número b se os dı́gitos de a formam


uma permutação dos dı́gitos de b.

Exemplo: 5412434 é uma permutação de 4321445, mas não é uma per-


mutação de 4312455.

Obs.: Considere que o dı́gito 0 (zero) não aparece nos números.


a)Faça uma função contadı́gitos que dados um inteiro n e um inteiro d,0 < d < 9,
devolve quantas vezes o dı́gito d aparece em n.

b) Usando a função do item anterior, faça um programa que lê dois inteiros
positivos a e b e responda se a é permutação de b.

III Faça uma função que receba dois vetores tipo char e compare se estes são
iguais. A função deve retornar 1 se os vetores forem iguais e 0 caso contrário.

35
6.6 Recursividade 6 FUNÇÕES

6.6 Recursividade
Uma poderosa caracterı́stica de muitas linguagens de programação, incluindo
C, é o fato de que uma função pode chamar a si mesma. Quando isto ocorre,
dizemos que a função é recursiva. Um exemplo clássico é para o cálculo do
fatorial de um número.

Exemplo 6.13: Função recursiva para calcular o fatorial de um número:

#include<stdio.h>
#include<stdlib.h>

int fatorial (int n);


int main() {
int n;
printf("Digite um valor para n: ");
scanf ("%d", &n);
printf("\nO fatorial de %d eh %d", n, fatorial(n));
system ("pause");
return 0;
}

int fatorial(int n) {
if (n)
return n*fatorial(n-1);
else
return 1;
}

Deve-se tomar bastante cuidado ao usar a recursividade, pois necessita-se


de uma escolha correta do critério de parada para evitar erros lógicos, como a
função ser executada infinitas vezes, que é um dos erros mais comuns. Outro
aspecto relevante é que a cada vez que uma função é chamada, é consumida
uma parcela de memória do computador. Desta forma, o uso incorreto da
recursividade pode esgotar rapidamente a memória da máquina.

36
6.7 Escopo de variáveis 6 FUNÇÕES

6.7 Escopo de variáveis


6.7.1 Variáveis Locais
Este tipo de variável só tem validade dentro do bloco no qual foi declarada.
O bloco, como foi dito anteriormente, é o conjunto de instruções que estão den-
tro de um par de chaves. Por exemplo, pode-se declarar variáveis dentro de um
for. A caracterı́stica que as tornam tão importantes é justamente a de serem
exclusivas a um bloco.

Exemplo 6.14: Programa usando variáveis locais:

#include<stdio.h>
#include<stdlib.h>

int main() {
int a, b=5, c=7;
for (a=0; a<10; a++) {
int b=0, c=1;
printf("\na = %d, b = %d, c = %d", a, b, c);
}
printf("\na = %d,b = %d, c= %d", a, b, c);
system ("pause");
return 0;
}

No exemplo anterior, na função main foram declaradas três variáveis: a, b e


c. No bloco relativo ao laço for, foram criadas b e c. Ao executar o programa,
pode-se observar que os valores de a estão mudando de 0 a 9 dentro do laço e os
de b e c permanecem 0 e 1, respectivamente. Apesar de existirem no bloco mais
externo outras variáveis b e c, o programa prioriza as variáveis locais, das quais
são impressos os valores. As variáveis locais são criadas sempre que um bloco
começa a ser executado e são destruı́das quando ele termina. Se no exemplo
6.14 fosse incrementada alguma das variáveis locais após o valor ser impresso,
quando o laço fosse executado novamente, o valor impresso seria igual ao da vez
anterior.

6.7.2 Variáveis Globais


Este tipo de variável é declarado fora de todas as funções do programa, de
modo que pode ser usada por todas as funções. Entretanto, uma função pode

37
7 INTRODUÇÃO A APONTADORES

ter uma variável local com o mesmo nome de uma variável global. Quando isto
ocorre, o programa dá prioridade à variável local.

Exemplo 6.15: Programa usando variáveis globais:

#include<stdio.h>
#include<stdlib.h>

int a=0, b=1, c=2;

void imprimeABC ( void ){


int b=3;
printf("\na = %d, b = %d, c = %d", a, b, c);
}

int main(){
printf( "\na = %d, b = %d, c = %d", a, b, c);
b++;
a = a+5;
printf("\nb = %d", b);
imprimeABC();
system ("pause");
return 0;
}

No exemplo 6.15, são criadas as variáveis globais a, b e c. É notável que elas


podem ser acessadas e modificadas tanto pela função main quanto pela função
imprimeABC. Foi criada uma variável local b de mesmo nome de uma global
para que a ordem de prioridade fosse visualizada, já que o valor impresso é o da
variável local.

7 Introdução a Apontadores
7.1 Visão Geral
A diferença entre os bons programadores em C e todos os outros está certa-
mente no domı́nio que têm da manipulação de apontadores.

38
7.2 Declaração de apontadores 7 INTRODUÇÃO A APONTADORES

Um apontador é simplesmente uma variável que armazena o endereço de


outra variável. Como, por exemplo: O que é o ponteiro de um relógio? É o que
aponta para as horas, minutos ou segundos. Um apontador aponta para algo.
Em programação, temos as variáveis armazenadas na memória, e um apontador
indica um endereço de memória.

Para clarear a mente, imagine as variáveis como documentos, a memória do


computador como pastas para guardar documentos e o apontador como atalhos
para as pastas.

7.2 Declaração de apontadores


Um conceito que não se pode perder de vista é que o apontador é uma
variável como outra qualquer, sendo assim, é necessário que ocorra a sua de-
claração.

A sintaxe de declaração de um apontador é a seguinte:

/*Declaração de um apontador*/
tipo *ptr;

Neste caso ptr é o nome da variável do tipo apontador, tipo é o tipo da variável
para qual apontará e o *(asterisco) indica que é uma variável do tipo apontador.

Exemplo 7.1: Declaração de apontador:

char a,b,*p,c,*q;
int idade, *p idade;

Observação: Quando o tipo declarado é um vetor, por exemplo “array”,


o nome da variável é um apontador que aponta para o endereço de memória
da primeira variável do vetor, isto é, o apontador, neste caso “array”, apenas
guarda o valor &array[0].

7.3 Inicialização de apontadores


Quando declaramos um apontador, ele é inicializado com um endereço não
válido, portanto antes de usá-lo é necessário atribuir um endereço, o que é feito
pelo operador (&).

Exemplo 7.2: Inicialização de apontadores:

39
7.3 Inicialização de apontadores 7 INTRODUÇÃO A APONTADORES

int x=5;
int *ptr;
ptr = &x;
Neste exemplo, primeiro declara-se a variável inteira x com valor 5 e de-
claramos o apontador inteiro ptr. Depois disso, inicializamos o apontador ptr
com o endereço da variável x. Ou seja, na terceira linha de código dizemos que
apontamos ptr para o endereço da variável x.

Exemplo 7.4: Inicialização de difentes tipos de variáveis:

int x = 5;
float pi = 3.14;
int *ptr x=&x;
float *pointer to pi = &pi;

Veja agora esse exemplo do uso de apontadores:

Exemplo 7.5: Programa para o uso de apontadores:

#include <stdio.h>
#include <stdlib.h>

int main () {
int x = 5;
int *ptr;
ptr = &x;

//exibe o valor de x
printf("%d\n\n", x);

//exibe o valor apontado por ptr


printf("%d\n\n", *ptr);

//exibe do endereço apontado por ptr


printf("%d\n\n", ptr);

//exibe o valor do endereço do apontador


printf("%d\n\n", &ptr);

40
7.4 Aritmética de apontadores 7 INTRODUÇÃO A APONTADORES

//exibe o endereço da variável x


printf("%d\n\n", &x);

system("pause");
}

A saı́da do programa é a seguinte:

5
5
2686788
26866784
2686788

Pressione qualquer tecla para continuar. . .

Deste exemplo podemos concluir que *ptr é igual a x, e ptr é igual a &x.
Com isso vemos melhor como funciona um apontador e como usá-lo.

7.4 Aritmética de apontadores


7.4.1 Incremento e Decremento
Um apontador pode ser incrementado como qualquer outra variável. No en-
tanto, o incremento de uma unidade não significa que o endereço anteriormente
armazenado no apontador seja incrementado ou decrementado em um byte.

Na realidade, se ptr é um apontador para um determinado tipo, quando ptr


é, por exemplo, incrementado de uma unidade, o endereço que passa a conter é
igual ao endereço anterior do apontador mais a quantidade de bytes referente ao
tipo do apontador, isto é, o apontador não avança um byte, mas sim a dimensão
do tipo do objeto para o qual aponta.

Exemplo 7.6: Aritmética de apontadores:

#include <stdio.h>
#include <stdlib.h>

41
7.5 Mais operações com apontadores7 INTRODUÇÃO A APONTADORES

int main (){


int x = 5;
int *ptr;
ptr = &x;

//valor do endereço inicial do apontador


printf("%d\n\n", ptr);

//valor do endereço após o incremento


printf("%d\n\n",++ptr);

system("pause");
}

Saı́da do programa:

2686788
2686792

Pressione qualquer tecla para continuar. . .

Com isso é perceptivel como ocorre o incremento e o decremento das variáveis


do tipo apontador.

7.5 Mais operações com apontadores


Suponhamos dois apontadores inicializados ptr1 e ptr2. Podemos realizar
dois tipos de atribuições entre eles:

ptr1=ptr2;

Esse primeiro exemplo faz com que ptr1 aponte para o mesmo lugar que
ptr2.

*ptr1=*ptr2;

42
7.6 Exercı́cios de Revisão 7 INTRODUÇÃO A APONTADORES

Nesse segundo caso, estamos igualando os valores indicados pelos dois apon-
tadores: alteramos o valor que era apontado por ptr1 pelo valor apontado por
ptr2.

(*ptr1)++;

Aqui, colocamos *ptr1 entre parênteses para especificar que queremos al-
terar o valor apontado por ptr1. Ou seja, iremos incrementar o conteúdo da
variável indicada pelo apontador ptr1.

*ptr1++;

Neste caso a precedência do operador ++ sobre o operador * faz com que a


expressão seja equivalente a *(ptr1++). O valor atual de ptr1 é retornado ao
operador *, e o valor de ptr1 é incrementado. Ou seja, obtemos o valor atual
do apontador e já o fazemos indicar para o próximo valor.

x=*(ptr1+15);

Esta linha atribui a uma variável x o conteúdo do décimo quinto inteiro


adiante daquele apontado por ptr1. Por exemplo, suponhamos que tivéssemos
um vetor i[16] e que ptr1 apontasse para i[0]. Nossa variável x receberia o valor
de i[15].

7.6 Exercı́cios de Revisão


I - Escrever um programa que exiba na tela todos os valores de um vetor,
usando um apontador;

II - Escreva um programa que receba um vetor de variáveis do tipo float e


calcule a média dos valores usando um apontador;

III - Escreva um programa que receba um vetor do tipo char e utilizando


um apontador alterar as vogais pelo caractere ’ ’;

IV - Escreva um programa que receba um vetor do tipo char e altere as


consoantes pelo caractere seguinte na tabela ASCII (DICA: ’A’ = 64, ’B’=65);

43
8 EXERCÍCIOS COMPLEMENTARES

8 Exercı́cios Complementares
I - Faça um programa em C que receba as notas de quatro estágios, a nota
de um exercı́cio extra (que vale 1 ponto) e diga se o aluno foi aprovado por
média, reprovado por média ou para final. Nesse último caso, informar qual a
nota mı́nima necessária para ser aprovado. (As regras de aprovação serão as da
UFCG).

II - Faça um programa que exiba as n primeiras linhas do triângulo de Pascal:

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
III - Calcule a soma dos 10 primeiros termos da série de Taylor para a função
exponencial, para x=1:

x x2 x3 x4 x5
ex = 1 + + + + + + ..., −∞ < x < ∞
1! 2! 3! 4! 5!
Determinando, dessa forma, um valor aproximado da constante de Euler.

IV - Faça um vetor de tamanho 100 que é preenchido com os 100 primeiros


naturais que não são múltiplos de 7 ou que terminam com 7.

V - Faça um programa que dada uma sequência de n números reais deter-


mina o número de vezes que cada um deles ocorre na mesma.

VI - Escreva uma função que calcula o produto dos elementos da coluna j


de uma matriz real Amxn .

VII - Faça um programa que lê da entrada padrão duas matrizes 3x3, calcula
o produto de ambas e exibe o resultado na tela.

VIII - Faça um programa que lê os coeficientes (a,b,c) de uma equação de


segundo grau da forma ax2 + bx + c = 0 e informa se as raı́zes são duplas,
distintas ou complexas. Caso sejam duplas ou distintas, exibir as raı́zes.

IX - Escreva uma função que recebe uma matriz real Amxn e determina a
sua transposta (se B é a matriz transposta de A então aij = bji) e depois exibe
na tela.

44
8 EXERCÍCIOS COMPLEMENTARES

X - Faça uma função que verifica se uma matriz Amxm é a matriz identidade.

XI - Faça um jogo que simula o jogo de par ou ı́mpar. Usuário contra a


máquina.

XII - Dados n e dois números inteiros positivos, i e j, diferentes de 0, exibir


em ordem crescente os n primeiros naturais que são múltiplos de i ou de j ou de
ambos. Exemplo: Para n=6, i=2 e j=2 a saı́da deverá ser: 0,2,3,4,6,8.

XIII - Faça um programa que gera um número aleatório de 1 a 1000. O


usuário deve tentar acertar qual número foi gerado, a cada tentativa o pro-
grama deverá informar se o chute é menor ou maior que o número gerado. O
programa acaba quando o usuário acerta o número gerado. O programa deve
informar em quantas tentativas o número foi descoberto.

XIV - Faça uma função recursiva que retorna o n-ésimo valor da serie de
Fibonacci, onde o n-ésimo termo é a soma dos termos anteriores. Os dois pri-
meiros termos são 1. Vejamos os 10 primeiros termos: 1 1 2 3 5 8 13 21 34 55 89 ...

XV - Implemente a mesma função da questão anterior de forma iterativa.

XVI - Implemente o jogo da velha, o programa deve informar quando o o


jogo acaba e qual jogador venceu.

45
REFERÊNCIAS REFERÊNCIAS

Referências
[1] Mesquita, R.C. Apostila: Curso de Linguagem C. UFMG, s/d;
[2] Projeto Mac Multimı́dia - Material Didático para disciplinas de Introdução
a Computação - http : //www.ime.usp.br/ macmulti/ - acessado no dia
29/09/2008

[3] Schildt, H. C - Completo e Total. São Paulo: McGraw-Hill, 1990.


[4] Gurjão, E.C. Notas de Aula: Introdução à Programação - UFCG, 2006.
[5] Damas, L. Linguagem C. 10a Edição. Rio de Janeiro: LTC, 2007.

[6] Deitel, P.J., Deitel, H.M. Como Programar em C. 6a Edição. São Paulo:
Prentice Hall, 2011. 848 p.

46

Você também pode gostar