PCS045-120-1 Driver LED
Transcription
PCS045-120-1 Driver LED
UNIFEI
Disciplina
Professor
UNIVERSIDADE FEDERAL DE ITAJUBÁ
Instituto de Engenharia de Sistemas e Tecnologias da Informação-IESTI
ECO002 – Técnicas de Programação
Dr.Enzo Seraphim, Dra.Thatyana de Faria Piola Seraphim
Notas de Aula de Linguagem C
Sumário
1Linguagem C ................................................................................................................................................... 3
1.1Organização dos Programas em C ....................................................................................................................... 3
1.2Include .................................................................................................................................................................... 5
1.3Variáveis ................................................................................................................................................................. 5
1.3.1Identificadores ou nomes de Variáveis ............................................................................................................................. 5
1.3.2Tipos de Dados e Tamanhos .............................................................................................................................................. 6
1.3.3Declaração de variável ...................................................................................................................................................... 6
1.3.4Inicialização variáveis ....................................................................................................................................................... 7
1.3.5Atribuição de variáveis ...................................................................................................................................................... 7
1.3.6Constante ........................................................................................................................................................................... 9
1.4Operadores ............................................................................................................................................................. 9
1.4.1Operadores Aritméticos ..................................................................................................................................................... 9
1.4.2Operadores Aritméticos de Atribuição .............................................................................................................................. 9
1.4.3Operadores de incremento e decremento ......................................................................................................................... 10
1.4.4Operadores Relacionais ................................................................................................................................................... 10
1.4.5Operadores Lógicos ......................................................................................................................................................... 10
1.5Comentários ......................................................................................................................................................... 11
1.6Funções para Entrada e Saída de dados ............................................................................................................ 11
1.6.1Função de saída printf <stdio.h> ......................................................................................................................................11
1.6.2Função de saída putchar <stdio.h> .................................................................................................................................. 13
1.6.3Função de entrada scanf() <stdio.h>................................................................................................................................ 13
1.6.4Funções de entrada getchar() <stdio.h> ........................................................................................................................... 14
1.7Tomada de Decisões ............................................................................................................................................. 14
1.7.1Comando de seleção if – else .......................................................................................................................................... 14
1.7.2Comando de seleção switch............................................................................................................................................. 14
1.8Laços ou Malhas de Repetição............................................................................................................................ 15
1.8.1Comando de laço while ................................................................................................................................................... 15
1.8.2Comando de laço do – while ........................................................................................................................................... 15
1.8.3Comando de laços for ...................................................................................................................................................... 16
1.8.4Comandos de desvio break e continue............................................................................................................................. 16
1.9Tipos de dados estruturados ............................................................................................................................... 16
1.9.1Estruturas Homogêneas – arrays .................................................................................................................................... 16
1.9.2Definições de tipos .......................................................................................................................................................... 17
1.9.3Estruturas Heterogêneas – struct .................................................................................................................................... 17
1.9.4Tipos enumerados ............................................................................................................................................................ 17
1.10Criando Funções ................................................................................................................................................ 18
1.10.1 Passando dados para a função ...................................................................................................................................... 19
1.10.2 Funções que retornam um valor ................................................................................................................................... 19
1.11 Funções da biblioteca <stdlib.h> ..................................................................................................................... 20
1.12Funções da biblioteca <time.h> ........................................................................................................................ 20
1.13Funções da biblioteca <math.h> ....................................................................................................................... 21
1.14Funções de Strings ............................................................................................................................................. 21
2Recursividade ................................................................................................................................................ 22
3Anexo: Biblioteca Conio.h............................................................................................................................ 25
3.1Instalação no DevCpp (windows ou linux) ........................................................................................................ 25
3.2Instação e Configuração no Linux ..................................................................................................................... 26
3.3Funções da Conio ................................................................................................................................................. 26
3.3.1void clrscr (void); ............................................................................................................................................................ 27
3.3.2void gotoxy (int x, int y); ................................................................................................................................................. 27
3.3.3int getch (void); / int getche (void); / int putch (int) ........................................................................................................ 27
3.3.4void delline (void); .......................................................................................................................................................... 28
3.3.5void textcolor (int cor); / void textbackground (int cor); ................................................................................................. 28
Linguagem C
A linguagem de programação C foi projetada para permitir grande economia de expressão nos
programas, isto é, produzir programas fonte mais compactos. Foi primeiramente usada para escrever cerca
de 90% do código do sistema operacional UNIX, e com a popularização deste sistema operacional em
equipamentos de médio porte, e até micros, a linguagem C também ganhou popularidade entre os
programadores profissionais.
Em 1969, os laboratórios Bell procuravam uma alternativa para o sistema operacional Multics para o
computador PDP-7. Uma versão básica do sistema operacional UNIX foi então escrita em Assembly. Neste
mesmo período, uma linguagem experimental estava sendo desenvolvida por Keneth Thompson. Esta
linguagem se chamava B, e a partir dela foi projetada a linguagem C, em 1972.
Logo depois, em 1973, o sistema operacional UNIX foi melhorado e cerca de 90% de seu código foi
escrito em C. Por causa desta libertação do Assembly, UNIX (e consequentemente C) adquiriu grande
portabilidade, foi rapidamente adaptado a uma série de computadores e seu uso não parou de crescer. No
final da década de 70 e inicio da década de 80, a proliferação de UNIX e C foi muito grande e chegou até os
micros. Além do que, C ficou independente do sistema operacional UNIX e uma série de compiladores C
surgiram para muitos equipamentos.
Hoje, C é a linguagem preferida dos programadores profissionais por várias razões, e chega a
substituir Assembly em boa parte do software recentemente desenvolvido.
Basta dar uma olhada nas revistas e livros que trazem algoritmos e dicas para programadores, vê-se
que as implementações que, há alguns anos, vinham em Assembly, estão hoje quase totalmente escritas em
C.
Com o advento da Programação Orientada para Objetos (OOP - Object Oriented Programming), a
linguagem que se tornou mais usada para esta técnica de programação é uma extensão da linguagem C,
chamada C++.
A maneira de se comunicar com um computador chama-se programa e a única linguagem que o
computador entende chama-se linguagem de máquina.
1.1 Organização dos Programas em C
Um programa C é na verdade uma coleção de funções, criadas pelo programador ou funções de
biblioteca.
A maioria dos compiladores que vem da linguagem C, vem com uma grande quantidade de funções
já criadas e compiladas em bibliotecas que são usadas dependendo da necessidade do programador.
Os componentes de um programa em C são:
•
Comentários: podem e devem estar em qualquer ponto do programa. É aconselhável colocar
um resumo logo no inicio do programa com algumas informações como: nome do programa, nome do
programador, período de elaboração, para que serve, se é parte de algum sistema maior, restrições de acesso
por motivo de segurança, etc. Os comentários são escritos entre os delimitadores /* e */, e desta forma não
são considerados pelo compilador. Outra forma de inserir comentários é utilizar duas barras //. Qualquer
coisa que esteja escrita após as duas barras até o fim da linha será interpretado como comentário.
•
Diretivas de compilação: não são instruções próprias da linguagem C. As diretivas são
mensagens que o programador envia ao compilador para que este execute alguma tarefa no momento da
compilação. Deve haver uma linha inteira para cada diretiva, que são iniciadas pelo caractere #. As diretivas
mais comuns são #include e #define, respectivamente usadas para, especificar bibliotecas de funções a
serem incorporadas na compilação, e macro substituições, como veremos mais adiante.
Definições globais normalmente são especificações de constantes, tipos e variáveis que serão
válidas em todas as funções que formam o programa. Embora sejam de relativa utilidade, não é uma boa
prática de programação definir muitas variáveis globais. Como elas podem ser acessadas em qualquer parte
do programa, mesmo um breve descuido na alteração dos seus valores, pode provocar problemas em muitos
outros locais.
•
Protótipos de funções não são obrigatórios. Os protótipos são usados pelo compilador para
fazer verificações durante a compilação: ver se as partes do programa que acionam as funções o fazem de
modo correto, com o nome certo, com o número e tipo de parâmetros adequados, etc. Esta é uma boa pratica
para se programar em C.
•
Definições de funções são os blocos do programa onde são definidos os comandos a serem
executados em cada função. A função pode, ou não, receber valores que serão manipulados em seu interior.
Após o processamento, as funções podem, se necessário retornar um valor. É obrigatório a presença de pelo
menos uma função com o nome "main", e esta será a função por onde começa a execução do programa. Não
há ordem obrigatória para codificar as funções. No entanto, procuraremos sempre começar pela função
main, para facilitar a tarefa de manutenção do programa. Todas as outras funções serão codificadas em
seguida. É necessário que seja respeitada uma ordem na codificação das funções. O programador pode
“desrespeitar” esta necessidade SE declarar corretamente todos os protótipos de funções.
Abaixo é apresentado um modelo de programa
•
/*
/*
/*
Programa 1
Função: descrição
Autor: nome
*/
*/
*/
//Diretivas de compilação
#include <biblioteca.h>
#define macros
#define labels
//Seção de variáveis globais
char variavelGlobal;
//Seção de protótipos de funções
void funcao1(char var);
int funcao2(void);
//seção de definições de funções
int main(int argc, char* argv[])
{
...
return 0;
}
void funcao1(char var)
{
...
}
int funcao2(void)
{
...
return x;
}
Abaixo é exemplificado o conjunto mínimo de instruções usado para começar a programar na
linguagem C, embora que não seja obrigatório, mas aconselhável, coloque apenas uma instrução por linha.
#include <stdio.h>
int main(int argc, char* argv[])
{
return 0;
}
1.2 Include
Esta diretiva de compilação serve para especificar ao compilador que queremos utilizar novas
funções, tipos e macros que estão disponíveis em outros arquivos. Como a linguagem C tem uma grande
variedade destas funções e definições, é comum que elas estejam agrupadas em arquivos diferentes, de
acordo com a natureza das tarefas que executam. As formas gerais para esta diretiva são as seguintes:
#include <nome do arquivo>
#include "nome do arquivo"
A diferença entre estas duas formas está no local onde o compilador vai procurar o arquivo no
momento da compilação. No primeiro formato, o arquivo é procurado no diretório definido pelo compilador
C, como sendo aquele que contem os "header files". Header files são os arquivos com extensão .h que
contém definições de tipos, dados e diversas funções já prontas. O segundo formato é usado quando
queremos que o compilador busque o arquivo especificado no mesmo diretório do arquivo que estamos
criando. Esta forma é usada normalmente quando queremos incorporar arquivos criados e salvos por nós
mesmos no diretório atual. Segue uma lista com alguns arquivos (bibliotecas) padronizados em todos
compiladores, compativeis com a norma ANSI-C:
•
assert.h rotina de diagnóstico par código fonte.
•
ctype.h rotinas de verificação de tipo de dados
•
errno.h define macro para erros em C
•
float.h define macros que especificam características do ponto flutuante
•
limits.h define macros que definem os limites dos tipos de dados
•
math.h funções matemáticas
•
stdio.h rotinas padrão de entrada e saída definidas pelos criadores da linguagem C.
•
stddef.h vários tipos de dados e macro substituições
•
stdlib.h várias rotinas muito úteis, conversão, sort, etc..
•
string.h rotinas para manipular strings e memória
•
time.h rotinas para manipular tempo.
Existem outros arquivos com outras funcionalidades. Estes devem ser usados com cuidado pois
podem prender o programador a um determinado compilador e/ou arquitetura.
1.3 Variáveis
As variáveis são um dos aspectos fundamentais de qualquer linguagem de computador. Uma variável
em linguagem C é um espaço de memória reservado para armazenar certo tipo de dado e tendo um nome
para referenciar o seu conteúdo. Ou seja, uma variável é um espaço de memória contém um valor que pode
ser alterado ao longo do tempo.
1.3.1 Identificadores ou nomes de Variáveis
A escolha de nomes significativos para suas variáveis pode ajudar a entender o que o programa faz e
evita erros. Pode-se utilizar quantos caracteres se queira para um nome de variável, mas sempre o primeiro
caracter sendo obrigatoriamente uma letra ou sublinhado. Os demais podem ser letras, números ou outros
caracteres.
A linguagem C faz distinção entre maiúsculas e minúsculas, ou seja, a variável com nome matrix é
diferente da variável como nome MaTrIx. A prática tradicional na linguagem C é usar minúsculas para
variáveis e maiúsculas para constantes.
Uma variável não pode ter o mesmo nome de uma palavra chave em linguagem C.
1.3.2 Tipos de Dados e Tamanhos
O tipo de uma variável, informa a quantidade de memória, em bytes, que esta irá ocupar e como esta
deve ser interpretada: com ou sem fração (vírgula). Os tipos básicos de dados na linguagem C são:
Tipo
bits
bytes
variação
char
8
1
-127 à 127
int
16
2
-32.768 à 32.767
float
32
4
3,4 x 10 -38 à 3,4 x 10 38
double
64
8
3,4 x 10 -308 à 3,4 x 10 308
Podemos notar que as variáveis que possuem maior tamanho podem armazenar valores maiores.
Notamos também que apenas os tipos float e double possuem casas decimais.
Além desses, existe o tipo void que é usado quando uma função não retorna ou quando aponta para
um valor indefinido.
Modificadores
Um modificador de tipo altera o significado dos tipos base e produz um novo tipo. Existem quatro
tipos de modificadores, dois para o tamanho (long e short) e dois para sinal (unsigned e signed). Um tipo
declarado com o modificador long pode ter tamanho MAIOR ou IGUAL ao tipo original. Um tipo declarado
como short deve ter tamanho MENOR ou IGUAL ao tipo original. Os tipos declarados como signed
possuem um bit reservado para o sinal. Os tipos declarados como unsigned não podem assumir valores
negativos, em compensação podem atingir o dobro do valor de um tipo unsigned.
Exceto void, os demais tipos podem ser alterados pelos modificadores.
Tipo
unsigned char
unsigned int
signed int
unsigned long int
short int
long int
long double
bytes
1
2
4
2
4
10
variação
0 à 255
0 à 65.535
-32.768 à 32.767
0 à 4.294.967.295
-32.768 à 32.767
-2.147.483.648 à 2.147.483.647
3,4 x 10 -4932 à 1,1 x 10 4932
Na linguagem C, por padrão os tipos são sinalizados, ou seja, possuem parte positiva e negativa. Por
isso é raro encontrar o modificador signed.
1.3.3 Declaração de variável
Uma declaração de variáveis é uma instrução que resulta uma quantidade de memória para
armazenar o tipo especificado.
Uma declaração de variável consiste no nome de um tipo, seguindo de nome da variável. Na
linguagem C todas as variáveis devem ser declaradas antes de iniciar a codificação. Variáveis do mesmo tipo
podem ser declaradas separadas por vírgula.
Exemplo:
int idade;
char sexo;
float peso, salario;
1.3.4 Inicialização variáveis
É possível combinar uma declaração de variável com o operador de atribuição, para que a variável
tenha um valor ao mesmo tempo de sua declaração. A linguagem C não inicializa variáveis com valores
padrão, deste modo uma variável não inicializada pode conter “lixo”. Como boa prática devemos sempre
inicializar as variáveis no momento da declaração para evitar problemas.
Na linguagem C escrevemos os caracteres entre aspas simples, por exemplo: 'a'; cadeias de caracteres
entre aspas duplas, por exemplo: "primeiro programa"; e numeros sem aspas, por exemplo: 97.6. Notar que
o indicador de fração é o ponto e não a virgula.
Exemplo:
#include <stdio.h>
int main(int argc, char* argv[])
{
char sexo = 'H';
int idade = 31;
float peso = 72.5, salario = 300;
printf( "Eu sou %c, tenho %d anos, peso %f kg e ganho %f reais",
nome, sexo, idade, peso, salario);
return 0;
}
Resultado na tela: Eu sou H, tenho 31 anos e peso 72.5 kg e ganho 300 reais
Inicialização de conjunto de caracteres
Quando uma variável é declarada na linguagem C, essa não contêm valor e por isso uma boa prática
é inicializá-la na declaração. Para inicializar uma variável com um conjunto de caracteres, devemos declarála como se fosse um vetor de caracteres. Conjuntos de caracteres serão explicados mais adiante.
#include <stdio.h>
int main(int argc, char* argv[])
{
char nome[10] = "Jose";
printf( "Eu me chamo %s", nome);
return 0;
}
Resultado na tela: Eu me chamo Jose
Obs: a variável deve ter um tamanho maior que a quantidade de caracteres do texto a ser atribuido.
1.3.5 Atribuição de variáveis
A atribuição de novos valores para a variável pode ser feita em qualquer parte do programa.
Exemplo:
#include <stdio.h>
int main(int argc, char* argv[])
{
float preco = 150;
printf( "preco sem nota = %f ", preco);
preco = preco * 0.20;
printf( " preco com nota = %f", preco);
return 0;
}
Resultado na tela: preco sem nota = 150.0 preco com nota = 180.0
Utilização de Parênteses para Atribuição
Pode-se também fazer a atribuição entre parênteses obtendo-se o mesmo valor que está sendo
atribuído.
Exemplo:
#include <stdio.h>
int main(int argc, char* argv[])
{
int salario;
float inss = (salario = 300) * 0.1;
printf( "salario = %d e inss %d", salario, inss);
return 0;
}
Resultado na tela: salario = 300 e inss = 30.0
Vírgula
Você pode usar a vírgula para separar várias expressões dentro de um conjunto de parênteses. As
expressões são avaliadas da esquerda para a direita, e toda a expressão assume o valor da última expressão
avaliada.
Exemplo:
#include <stdio.h>
int main(int argc, char* argv[])
{
float salario, inss;
float irrf = (salario = 300, inss = salario * 0.1) * 0.1;
printf( "salario = %f, inss = %f, irrf = %f", salario, inss, irrf);
return 0;
}
Resultado na tela: salario = 300, inss = 30.0, irrf = 3.0
Conversão de tipos
A linguagem C nos permite converter um valor de um certo tipo para um valor correspondente de
outro tipo. Isto se chama typecast.
Para converter um valor de um tipo para outro, basta escrever entre parênteses o nome do novo tipo
antes do valor original. No exemplo abaixo, convertemos um número real em um número inteiro.
Exemplo:
#include <stdio.h>
int main(int argc, char* argv[])
{
int preco = 30;
int imposto = (int) preco * 0.05;
printf( " preco = %d, imposto = %d", preco, imposto);
return 0;
}
Resultado na tela: preco = 30, imposto = 1
Como o tipo inteiro não permite virgula o valor de imposto acaba sendo truncado, ou seja, ele tem
sua parte fracionária eliminada.
1.3.6 Constante
Uma constante tem valor fixo e inalterável. Usamos a diretiva de compilação #define que define uma
macro para associar um valor constante. Para nomear uma constante é comum usar apenas letras maiúsculas,
pois facilita sua identificação no programa.
Exemplo:
#include <stdio.h>
#define DISTANCIA 400
int main(int argc, char* argv[])
{
printf ("São Paulo está %d Km de Rio Preto",
return 0;
DISTANCIA);
}
Resultado na tela: São Paulo está 400 Km de Rio Preto
1.4 Operadores
A linguagem C tem uma grande quantidade de operadores. Veremos alguns operadores da linguagem
C divididos em grupos: aritméticos, aritméticos de atribuição, incremento/decremento, relacionais e lógicos.
1.4.1 Operadores Aritméticos
operador
descrição
=
atribuição
+
soma
subtração
*
multiplicação
/
divisão
%
resto da divisão
Os operadores aritméticos: soma e subtração tem a mesma prioridade, a qual é menor que a
prioridade da multiplicação, divisão e resto da divisão. O operador resto da divisão aceita somente
operandos inteiros. Ele retorna o resto da divisão do inteiro à sua esquerda pelo inteiro à sua direita.
Exemplo:
int a = 1, b = 3, c = 5;
int l, m, n, o, p;
//código
l = 17 % c
m = 15 + b
n = 23 - a
o = 18 / b
p = 4 * c
//interpretação
l = 17 % 5
m = 15 + 3
n = 23 – 1
o = 18 / 3
p = 4 * 5
//resultado
l = 2
m = 18
n = 22
o = 6
p = 20
1.4.2 Operadores Aritméticos de Atribuição
Pode-se combinar os operadores aritméticos (+, -, *, /, %) com o operador de atribuição da seguinte
forma:
//contraído
l *= 4
m /= 2
n += 5
o -= 8
p %= 5
//expandido
l = l * 4
m = m / 2
n = n + 5
o = o - 8
p = p % 5
Este tipo de contração é muito utilizado na linguagem C pois facilita a escrita.
1.4.3 Operadores de incremento e decremento
Uma operação muito comum nos programas em C é realizar o incremento, ou decremento, de uma
variável. Por isso foram criados dois operadores específicos para esse fim: ++ incrementa de 1 seu operando;
-- decrementa de 1 seu operando. Geralmente são utilizados para realizarmos contagens progressivas ou
regressivas.
Os operandos de incremento e decremento trabalham de dois modos: pré ou pós-fixado. No préfixado, o operador aparece antes do nome da variável. Exempo: ++n; onde n é incrementado antes de seu
valor ser usado.
No pós-fixado, o operador aparece após o nome da variável. Exemplo: n++, onde n é incrementado
depois de seu valor ser usado.
Exemplo:
int a = 4;
//comando
a++
a-l = 2 * a++
m = 2 * ++a
//interpreação
a = a + 1
a = a - 1
l = 2 * 4
m = 2 * 5
//resultado
a = 5
a = 3
l = 8
m = 10
1.4.4 Operadores Relacionais
Estes operadores são usados para fazer comparações
operador
descrição
operador
descrição
>
maior
<
menor
>=
maior ou igual
<=
menor ou igual
==
igualdade
!=
diferente
Como sabemos, o resultado de uma comparação deve ser "verdadeiro" ou "falso". A linguagem C não
define um tipo lógico. O que ocorre é o seguinte: se o resultado de uma comparação for falso, o resultado da
operação será 0 (zero); e se a comparação for verdadeira, o resultado da operação será 1 (um).
Usualmente programadores de linguagem C definem seu próprio tipo lógico chamado bool como um
enumerado. O conceito de enumerado será visto posteriormente.
Exemplo:
#include <stdio.h>
typedef enum{false, true} bool;
int main(int argc, char* argv[])
{
int idade = 18;
bool logMaiorIdade = (idade > 18);
int intVelho = (idade > 50);
printf("maior idade = %d e velho = %d ",
logMaiorIdade, intMaiorIdade);
return 0;
}
Resultado na tela: maior idade = 1 e velho = 0
1.4.5 Operadores Lógicos
Os operadores lógicos são: && (lógico E), || (lógico OU) e ! (lógico Negação)
Se exp1 e exp2 são duas expressões simples:
exp1 && exp2 - é verdadeira se as duas expressões forem verdadeiras.
exp1 || exp2 - é verdadeira se uma ou as duas expressões forem verdadeiras.
! exp1 - é verdadeira se exp1 for falsa e vice-versa
Expressões
Um dos pontos mais característicos da linguagem C é a grande liberdade que ela dá aos
programadores no momento de escrever as expressões. Isto é responsável pela compactação do código
escrito em C, mas também faz com que as expressões escritas por programadores mais experientes sejam
mais complicadas à primeira vista.
Para facilitar a interpretação das expressões é comum utilizarmos parênteses para evitar a
ambiguidade.
Exemplo:
(2+2)/2 = 2
2+2 /2 = 3
1.5 Comentários
Comentários são textos que introduzimos no meio do programa fonte com a intenção de torná-lo
mais claro. É uma boa prática em programação inserir comentários no meio dos nossos programas. Pode-se
comentar apenas uma linha usando o símbolo ‘//’. Para comentar mais de uma linha usa-se o símbolo ‘/*’
antes do comentário e ‘*/’ para indicar o final do comentário.
Exemplo:
#include <stdio.h>
#define DIST 400 // distancia entre SP e RP
int main(int argc, char* argv[])
{
/* esse programa serve para
mostar como se usa comentários
em um programa */
printf ("São Paulo está %d Km de Rio Preto",
return 0;
DIST);
}
Resultado na tela: São Paulo está 400 Km de Rio Preto
1.6 Funções para Entrada e Saída de dados
1.6.1 Função de saída printf <stdio.h>
O printf é uma das funções de entrada e saída (E/S). No interior dos parênteses da função printf estão
as informações passadas na tela do computador.
Sintaxe: printf ( "expressão controle" , lista de argumentos )
A função printf é responsável tanto por imprimir as informações na tela do computador quanto por
formatá-las. Deste modo podemos indicar se queremos exibir um numero com ou sem parte fracionária.
Existem também códigos especiais para mudança de linha entre outros como podemos ver na tabela a seguir:
Códigos
Significado
Código
Formato
especiais
Printf
\n
nova linha
%c
caracter simples
\t
tabulação
%d
inteiro
\b
retrocesso
%e
notação científica
\"
aspas
%f
ponto flutuante
\\
barra
%o
inteiro octal
\f
salta página formulário
%s
cadeia de caracteres
%u
decimal sem sinal
%x
hexadecimal
Exemplo 1:
#include <stdio.h>
int main(int argc, char* argv[])
{
printf ("Este é o número dois: %d", 2);
return 0;
}
Resultado na tela: Este é o número dois: 2
Exemplo 2:
#include <stdio.h>
int main(int argc, char* argv[])
{
printf ("%s está a %d milhões de milhas do Sol", "Vênus", 67 );
return 0;
}
Resultado na tela: Vênus está a 67 milhões de milhas do Sol
Exemplo:
prinf ("Os alunos são %d \n"; 350);
prinf ("Os alunos são %4d \n"; 350);
prinf ("Os alunos são %6d \n"; 350);
Resultado na tela:
Os alunos são 350
Os alunos são 350
Os alunos são
350
Os comandos de formato podem ter modificadores que especificam a largura do campo e o número
de casas decimais é um ponteiro de justificação pela esquerda. Um inteiro colocado entre o sinal % e o
comando de formato age como um especificador de largura mínima do campo. Isto preenche a saída com
brancos ou zeros para garantir que tenha pelo menos um comprimento mínimo determinado. Caso a string
ou o número seja maior que o mínimo, será totalmente impressa, mesmo que ultrapasse o mínimo.
Exemplo de preenchimento padrão é feito com espaços em brancos.
printf ("%5d", 350); //tela:
350
Exemplo para preencher com zeros basta colocar o zero entre o sinal % e o número.
printf ("%05d", 350); //tela:00350
Exemplo usando casas decimais
printf
printf
printf
printf
("%4.2f \n", 3456.78);
("%3.2f \n", 3456.78);
("%3.1f \n", 3456.78);
("%10.3f \n", 3456.78);
//tela:3456.78
//tela:3456.78
//tela:3456.8
//tela: 3456.780
Exemplo para linhar usando casas decimais basta usar ponto flutuante
printf ("%10.2f %10.2f %10.2f \n", 834.0, 1500.55, 480.21);
printf ("%10.2f %10.2f %10.2f \n", 23, 4567.64, 9.12);
Resultado na tela:
834.00
23.00
1500.55
4567.64
480.21
9.12
O sinal de menos (-) precedendo a especificação do tamanho do campo após sinal (%) justifica os
campos à esquerda:
printf ("%-10.2f %-10.2f %-10.2f \n", 834.0, 1500.55, 480.21);
printf ("%-10.2f %-10.2f %-10.2f \n", 23, 4567.64, 9.12);
Resultado na tela:
834.00
23.00
1500.55
4567.64
480.21
9.12
1.6.2 Função de saída putchar <stdio.h>
Esta função exibe um único caracter na tela. Ao contrário de strings, escritas entre aspas, constantes
tipo caracter são escritas entre apóstrofos em C.
Sintaxe: putchar( caracter );
Exemplo:
putchar('a');
1.6.3 Função de entrada scanf() <stdio.h>
A função scanf() é outra função da biblioteca stdio.h e é o complemento de printf(). Ela nos permite
ler dados formatados da entrada padrão do teclado.
Sua sintaxe é similar à do printf(), isto é, uma expressão de controle seguida por uma lista de
argumentos separados por vírgula.
Sintaxe: scanf("expressao de controle", lista de argumentos);
A expressão de controle são os códigos de formatação, precedidos por um sinal % e a lista de
argumentos deve consistir nos endereços das variáveis. A linguagem C oferece um operador para tipos
básicos chamado operador de endereço e referenciado ao símbolo & que retorna o endereço.
Exemplo:
#include <stdio.h>
int main(int argc, char* argv[])
{
int n = 2;
printf( "Valor %d, endereço =
return 0;
%u", n, &n);
}
Resultado na tela: Valor 2, endereço = 65524
65524 é o endereço que esta variável ocupa na memória.
Código scanf
%c
%d
%e
%f
%o
%s
%u
%x
%l
Formato
leia um caracter simples
leia um inteiro
leia um nº notação científica
leia um nº ponto flutuante
leia um inteiro octal
leia uma cadeia de caracteres
leia um decimal sem sinal
leia um hexadecima
leia um inteiro longo
Exemplo:
#include <stdio.h>
int main(int argc, char* argv[])
{
int anos;
printf( "Digite sua idade: ");
scanf("%d", &anos);
return 0;
}
Resultado na tela: Digite sua idade: 22
1.6.4 Funções de entrada getchar() <stdio.h>
A função getchar() guarda o último caracter digitado.
getchar() - lê o caracter do teclado e permite que seja impresso na tela.
Exemplo:
Resultado na tela
#include <stdio.h>
Digite algum caracter: a
A tecla pressionada foi: a
Digite outro caracter: b
A tecla pressionada foi: b
int main(int argc, char* argv[])
{
char ch;
printf( "Digite algum caracter: ");
ch = getchar();
printf("\n A tecla pressionada foi: %c",
ch);
printf( "\n Digite outro caracter: ");
ch = getchar();
printf("\n A tecla pressionada foi: %c",
ch);
return 0;
}
1.7 Tomada de Decisões
1.7.1 Comando de seleção if – else
O comando if compara uma expressão. Se o resultado for verdadeiro serão executados os comandos
abaixo do if, se o resultado for falso serão executados os comandos abaixo do else
Sintaxe:
Exemplo:
Resultado na tela
if ( expressão )
{
comandos1
}
else
{
comandos2
}
#include <stdio.h>
Digite sua nota: 7.5
Aprovado
int main(int argc, char* argv[])
{
float nota;
printf( "Digite sua nota: ");
scanf("%f", ¬a);
if ( nota >= 7 )
{
printf ("\n Aprovado");
}
else
{
printf ("\n Reprovado");
}
return 0;
}
1.7.2 Comando de seleção switch
O comando switch compara um inteiro ou um caracter se existe algum case corresponde a ele, se
nenhum case corresponder, pode-se usar a opção default, que é opcional e colocada por último.
Sintaxe:
Exemplo:
Resultado na tela
switch ( variável)
{
case constante1:
comandos1;
break;
case constante2:
comandos2;
break;
default:
comando1;
break;
}
#include <stdio.h>
Digite sua nota: 4
Bom
int main(int argc, char* argv[])
{
int nota;
printf( "Digite sua nota (1 à 4): ");
scanf("%d", ¬a);
switch(nota){
case 4:
{
printf ("\n Bom");
break;
}
case 3:
{
printf ("\n Regular");
break;
}
case 2:
{
printf ("\n Ruim");
break;
}
case 1:
{
printf ("\n Péssimo");
break;
}
default:
{
printf ("\n Inválida");
break;
}
}
return 0;
}
1.8 Laços ou Malhas de Repetição
1.8.1 Comando de laço while
O enquanto a expressão for verdadeira, será executado o laço.
Sintaxe:
Exemplo:
Resultado na tela
while (expressão)
{
comandos1
}
#include <stdio.h>
int main(int argc, char* argv[])
{
int contador = 1;
int soma=0;
while ( contador <= 10 )
{
soma = soma + contador;
contador++
}
printf( "Soma de 1 à 10 é %d",soma);
return 0;
}
A soma dos números de 1 à
10 é 55
1.8.2 Comando de laço do – while
Ao contrário do comando de laço while e for, que testam a condição no início, o laço do-while
verifica a expressão no final do laço.
Sintaxe:
Exemplo:
Resultado na tela
do
{
#include <stdio.h>
Contador positivo
int main(int argc, char* argv[])
{
int contador = -1;
int soma=0;
do
{
printf("Contador positivo")
}while (contado>0)
return 0;
comandos1
} while (expressão)
}
Notar que a mensagem é exibida na tela mesmo o contador sendo negativo.
1.8.3 Comando de laços for
O laço FOR engloba 3 expressões numa única linha. É útil principalmente quando queremos repetir
algo numa quantidade de vezes fixo.
Sintaxe:
Exemplo:
Resultado na tela
for (inic; teste; inc )
{
comandos
}
#include <stdio.h>
int main(int argc, char* argv[])
{
int contador;
for(contador=1;contador<=10; contador++)
{
printf("Contador=%d\n", contador);
}
return 0;
}
Contador = 1
Contador = 2
Contador = 3
Contador = 4
Contador = 5
Contador = 6
Contador = 7
Contador = 8
Contador = 9
Contador = 10
1.8.4 Comandos de desvio break e continue
Existem dois comandos que podem modificar o andamento dos loops. Eles podem ser utilizados
dentro do bloco de comandos de qualquer tipo de laço. Suas funcionalidades são:
break – provoca a saída do laço em que se encontra no momento;
continue – termina a execução da lista de comandos e reinicia o loop. Se as condições continuarem
validas uma nova iteração é realizada
O comando break já foi visto funcionando em conjunto com o comando switch.
1.9 Tipos de dados estruturados
1.9.1 Estruturas Homogêneas – arrays
Em C, é possível também criar arrays, isto é, conjuntos de dados de um mesmo tipo, com um mesmo
nome, mas identificados através de um índice.
Sintaxe:
Exemplo:
tipo nome_do_array[número de elementos];
int vetor[3];
Os elementos de um array são identificados através de um índice inteiro que começa sempre em 0.
Portanto, no exemplo acima temos vetor[0], vetor[1] e vetor[2].
Outro ponto a destacar é que um array pode ser inicializado no momento de sua definição, como já
vimos para outros dados. Neste caso, a sintaxe é um pouco diferente, mas o exemplo a seguir ilustra o
processo. Os valores iniciais para cada elemento do array são escritos entre chaves e separados por vírgula.
Lembrar que o ponto é o divisor decimal para números fracionários.
Exemplo:
float vet[5] = { 1.001, 2.123, 4.555, -2.345, 123.3 };
Arrays multidimensionais, equivalentes às matrizes, podem ser definidos de modo análogo aos
arrays unidimensionais, exceto pelo fato de que são especificados mais de uma dimensão. O exemplo a
seguir mostra a definição e inicialização de uma matriz 3x2 de elementos tipo float.
Exemplo:
float mat[3][2] = { {1,2}, {3,4}, {5,6} };
1.9.2 Definições de tipos
Veremos agora como definir nossos próprios tipos em um programa na linguagem C. Isto é muito útil
quando começarmos a tratar de estruturas mais complexas.
Sintaxe:
Exemplo:
typedef tipo nome;
typedef unsigned char byte;
typedef enum {true, false} bool;
1.9.3 Estruturas Heterogêneas – struct
A palavra struct define uma variável que pode receber mais de um valor e esses valores podem ser de
tipos diferentes.
Sintaxe:
Exemplo:
typedef struct
{
tipo campo1;
tipo campo2;
...
} nome do tipo;
typedef struct
{
char nome[20], endereço[40];
float salario;
} registro;
registro reg;
1.9.4 Tipos enumerados
Em muitas situações é necessário utilizar informações sequenciais. Para facilitar a programação
podemos criar listas de elementos com nomes que nos lembrem seu significado. Estas listas são chamadas
de tipos enumerados.
Sintaxe:
Exemplo:
enum nome_enumerado{valor1, valor2, valor3, ...}
enum dia_util {segunda, terca, quarta, quinta,
sexta};
int dia;
for (dia = segunda; dia <= sexta; dia++)
{
....
}
Na verdade, o que ocorre quando definimos um tipo enumerado é o relacionamento automático do
primeiro item da sequência ao número 0, do segundo item ao número 1, e assim por diante.
Tipos enumerados são conjuntos de identificadores criados pelo programador associados aos inteiros
a partir de 0 (primeiro item), 1(segundo item), 2, 3, etc.
O nome do tipo é dispensável e somente deve ser colocado se for intenção do programador definir
variáveis deste tipo. Neste caso, a palavra enum deverá preceder o nome do tipo na definição de variáveis.
Exemplo:
enum vogal { a, e, i, o, u }; /* tipo enumerado vogal */
enum vogal v; /* variável v */
Há ainda a possibilidade de usar a diretiva typedef, como no exemplo a seguir:
typedef enum { masculino, feminino, indefinido} sexo;
1.10 Criando Funções
A maneira moderna de programar em C usa protótipos de funções para que o compilador faça
verificações nos pontos em que as funções são acionadas e nas próprias definições das funções. O protótipo
de uma função tem o mesmo formato que o cabeçalho da função.
Sintaxe:
Exemplo:
tipo nome_da_função ( parâmetros ) ;
int sum(int a, int b);
float raiz(float);
void tela(void);
O ponto e vírgula no final é obrigatório, o tipo é referente ao valor que a função retorna, o nome da
função é um identificador definido pelo programador, e os parâmetros são especificados um a um com tipo e
nome, ou somente tipo.
O um tipo chamado "void" serve para indicar que a função não retorna nenhum valor. Protótipos em
que especificamos o tipo void entre parênteses indicam que a função não tem parâmetros.
Após a criação dos protótipos devemos realizar a implementação das funções. Para isso existe um
cabeçalho para cada função. O cabeçalho tem a mesma forma dos protótipos. A diferença é que não possue o
ponto e virgula final. Após o cabeçalho temos o corpo da função que vem escrito entre chaves. O cabeçalho
tem os parâmetros definidos completamente, isto é, com tipo e nome de cada um. Caso a função não possua
parâmetros ela é declarada com os parênteses vazios.
No corpo da função são feitas as definições locais e, usando os comandos da linguagem C, é
implementado o algoritmo da tarefa que a função executa. Se o programa vai usar alguma função que foi
desenvolvida pelo usuário, deve-se lembrar de declarar o protótipo antes da função main().
Todas as variáveis declaradas dentro de uma função são chamadas variáveis locais. Elas possuem
este nome pois, podem apenas ser lidas ou escritas dentro da função na qual elas foram definidas.
Exemplo:
Resultado na Tela
#include <stdio.h>
void desenho (void);
**********
int main(int argc, char* argv[])
{
desenho();
return 0;
}
void desenho (void)
{
int aux; //variável local
for (aux = 1; aux <= 10; aux++)
{
printf("*");
}
}
1.10.1 Passando dados para a função
Muitas funções têm uma lista de parâmetros ou argumentos. Os parâmetros fornecem os meios para
fazer a comunicação entre funções. Variáveis declaradas dentro da função são diferentes de variáveis com o
mesmo nome declaradas dentro de uma outra função.
Exemplo:
#include <stdio.h>
void desenho (int num);
int main(int argc, char* argv[])
Resultado na Tela
Digite o número de asteriscos: 8
********
{
int ast;
printf("Número de asteriscos:");
scanf("%d", &ast);
printf("\n");
desenho ( ast );
return 0;
}
void desenho (int num)
{
int aux;
for (aux = 1; aux <= num; aux++)
{
printf("*");
}
}
1.10.2 Funções que retornam um valor
Para especificar o valor de retorno de uma função usa-se o comando return seguido do valor de
retorno. Tal valor pode ser uma constante, conteúdo de uma variável ou resultado de uma expressão.
Exemplo 1:
Resultado na Tela
#include <stdio.h>
int quadrado (int num);
int main(int argc, char* argv[])
Digite um número: 8
O quadrado de 8 é 64
{
int quad;
printf("Digite um número:");
scanf("%d", &quad);
printf("\n O quadrado de %d é %d",
quad, quadrado(quad) );
return 0;
}
int quadrado (int num)
{
int aux;
aux = num * num;
return( aux );
}
Exemplo 2:
Resultado na Tela
/* Programa para calcular a soma de dois
inteiros digitados.*/
#include <stdio.h>
int sum(int a, int b);
Digite dois inteiros: 8 10
A soma é: 18
int main(int argc, char* argv[])
{
int a, b, c;
printf("Digite dois inteiros: ");
scanf("%d %d", &a, &b);
c = sum(a,b);
printf("A soma é: %d \n", c);
return 0;
}
int sum(int a, int b)
{
return a+b ;
}
1.11 Funções da biblioteca <stdlib.h>
Função
Descrição
double atof (const char *string)
Função que converte uma string em um double.
int atoi(const char *str)
Função que converte uma string em um integer.
long atol(const char *str)
Função que converte uma string em um long integer.
int rand ( void )
Função que gera um numero randômico.
void srand ( unsigned int seed )
Função que inicializa a semente geradora dos números
randômicos.
int abs ( int n )
long abs ( long n )
Função que retorna o valor absoluto do número
div_t div (int numerator, int denominator)
Função que retorna a divisão inteira
void * calloc ( size_t num, size_t size )
Função que aloca memória
void free ( void * ptr )
Função que desaloca memória
void * malloc ( size_t size )
Função que aloca memória
int system ( const char * command )
Função que executa um comando do sistema
1.12 Funções da biblioteca <time.h>
Função
Descrição
clock_t clock(void)
Função que retorna o número de ciclos estimados desde
que o programa iniciou. Essa função possui uma alta
precisão mas, somente pode medir um pequeno intervalo
do tempo.
double difftime(time_t timer2, time_t timer1)
Função que retorna o clock da máquina, possui uma alta
precisão mas somente pode medir um intervalo pequeno do
tempo.
time_t time(time_t* timer)
Retorna o número de segundos desde 01/01/1970. Apesar
da baixa precisão pode medir um grande intervalo de
tempo. O parâmetro “timer” pode ser omitido.
CLOCKS_PER_SEC
Macro que contém o número de clock em um segundo.
1.13 Funções da biblioteca <math.h>
Para nossos interesses acadêmicos, certamente é importante sabermos usar as funções matemáticas
disponíveis no compilador C. Há uma série delas, cujos protótipos estão distribuídos na biblioteca math.h.
Algumas funções matemáticas:
Função
Descrição
double abs( double arg)
retorna o valor absoluto de arg
double cos( double arg)
retorna o coseno de arg (arg deve estar em radianos)
double log( double num )
retorna o logaritmo natural de num
double pow( double base, double exp)
retorna a base elevada à potência exp (baseexp)
double sin( double arg)
retorna o seno de arg (arg deve estar em radianos)
double sqrt( double num)
retorna a raiz quadrada de num
double tan( double arg)
retorna o tangente de arg (arg deve estar em radianos)
1.14 Funções de Strings
Pointers e arrays são muito usados em C e estão de certo modo relacionados às strings. Uma string é
na verdade um array de caracteres. No entanto, como o nome de um array é na verdade um pointer, há outra
maneira de definir uma variável string, ela pode ser um pointer para o tipo char.
Exemplo:
char nome[20];
char *profissao;
No primeiro exemplo, a variável nome guarda o endereço do primeiro byte de um local na memória
que pode armazenar strings de até 19 caracteres. O último caracter de uma string é sempre null (código zero
ASCII). Na verdade, null não pertence de fato à string, serve apenas para indicar seu final. Uma importante
diferença entre definir uma variável string como array de char e como pointer para char está na memória.
Quando a definimos como array, a memória é automaticamente reservada, como para qualquer array, mas
quando o fazemos como pointer, não há memória reservada previamente. Outro aspecto importante está em
como atribuir valores a estas variáveis. Quando escrevemos uma string entre aspas, o compilador C cria tal
string seguida por null em algum lugar no meio do programa objeto. O endereço de tal lugar é que está
disponível para ser então usado no programa. Desta forma, atribuição direta como no exemplo a seguir é
perfeitamente válida.
Exemplo:
char *nome = "Geraldo Ribeiro";
Esta forma se aplica bem à variáveis string definidas como pointers para char, mas para arrays e
outras operações mais complicadas, há uma série de funções de bliblioteca prontas à disposição dos
programadores em todos os compiladores.
Existe um série de funções definidas para manipulação de string no arquivo string.h:
Função
Descrição
char *strcpy(char *dest, const char *src)
copia uma string
char *strncpy(char *dest, const char *src,
size_t n)
copia uma quantidade de caracteres de uma
string
concatena duas string
char *strcat(char *dest, const char *src)
char *strncat(char *dest, const char *src,
size_t n)
concatena uma quantidade de caracteres entre
duas strings
char *strchr(const char *s, int c)
copia um char
int strcmp(const char *s1, const char *s2)
compara duas strings
int strncmp(const char *s1, const char *s2,
size_t n)
compara uma quantidade de caracteres entre
duas strings
size_t strlen(const char *s)
retorna tamanho de uma string
char *strstr(const char *haystack, const char
*needle)
compara se uma string esta contida dentro de
outra
Uma outra função muito útil para manipulação de string está na biblioteca stdio.h:
Função
sprintf(char *str, const char *format, ...)
Descrição
funcionamento igual a função printf, no
entanto o valor não é visualizado na tela, mas copiado
para a variável str
função para fazer leitura do teclado para uma
char *gets(char *s)
string
Recursividade
Qualquer função em linguagem C/C++ pode ser chamada de um modo recursivo, isto é, uma função
pode chamar-se a si própria. O número de vezes que uma função pode ser chamada recursivamente é
limitado ao tamanho da pilha (stack), se este valor for alcançado, o programa termina com "error: Stack
Fault" ou "Stack Overflow".
Função Recursiva é uma função que invoca a si própria, ou invoca outra função, e na seqüência das
diversas sub-funções, uma das sub-funções invoca a primeira função. Cada vez que uma função é chamada
de forma recursiva, é armazenada uma cópia dos seus parâmetros por forma a não perder os valores dos
parâmetros das chamadas anteriores. Em cada instância da função, só são diretamente acessíveis os
parâmetros criados para esta instância, não sendo diretamente acessíveis os parâmetros de outras instâncias.
A informação guardada na invocação de uma função é designada por Estrutura de Invocação e
consiste basicamente na seguinte informação:
•
Endereço de retorno (quando a função terminar o programa deve continuar a sua execução na
linha seguinte à invocação da função)
•
Estado dos registros e flags da CPU
•
Variáveis passadas como argumentos para a função (por valor, referência)
•
Variável de retorno (por valor, referência)
A invocação de uma função recursiva é igual à invocação de uma função não recursiva, na qual é
necessário guardar uma estrutura de invocação, sendo esta estrutura libertada depois do fim da execução da
função e atualização do valor de retorno.
As funções recursivas contêm duas partes fundamentais:
•
Ponto de Paragem: o ponto de paragem da recursividade é resolvido sem utilização de
recursividade, sendo este ponto geralmente um limite superior ou inferior da regra geral.
•
Regra Geral: o método geral da recursividade reduz a resolução do problema através da
invocação recursiva de casos menores, sendo estes casos menores resolvidos através da resolução de casos
ainda menores, e sucessivamente, até atingir o ponto de paragem que finaliza o método.
As variáveis declaradas como estáticas, não requerem novo armazenamento em cada invocação da
função recursiva. Estas variáveis existem durante todo o programa, não sendo criado cópias destas variáveis
na invocação de uma função de modo recursivo.
Desenho de algoritmos recursivos:
•
Obter uma solução de como o problema pode ser dividido em passos menores
•
Definir um ponto de paragem
•
Definir uma regra geral
•
Verificar se o algoritmo termina
•
Desenhar uma árvore de execução do programa, mostrando o desenvolvimento do processo.
Exemplo 1: Função para o cálculo do fatorial de um número.
A função fatorial retorna o mesmo valor em ambas as implementações, contudo, a forma sem
recursividade é ligeiramente mais rápida.
#include <stdio.h>
long int fact1( int num )
{
if (num < 0) // Se o número < 0 retorna erro.
//Função Factl - Método Recursivo
long int fact1( int num );
retun -1;
if ( (num == 0) || (num == 1) )
//Função Fact2 - Método Iterativo
// Se numero = 0 ou 1, então factorial é 1
long int fact2( int num );
return 1;
else
int main(int argc, char* argv[])
// Caso contrário, chamada recursiva
return( num * fact1( num - 1 ) );
{
int numero=0;
}
long int fact=0;
long int fact2( int num ){
long int resultado = 1;
scanf("%d", %numero);
if (num < 0) // Se o número < 0 retorna erro.
fact = fact1(numero);
retun(-1);
printf("\nfatorial %d = %d", &numero, %fact);
for(int i = 2; i <= num; i++){
fact = fact2(numero);
printf("\nfatorial %d = %d", &numero, %fact);
resultado *= i;
return 0;
}
return(resultado);
}
}
Todo algoritmo recursivo gera uma pilha de execuções a ser resolvida. Nessa implementação só
existe uma única chamada recursiva e por isso essa pilha tem o formato de uma lista. Abaixo segue um
exemplo da lista de recursão para fact(5).
1
fact(5)=5*fact(4)
2*fact(1)
2*fact(1)
2*1
3*fact(2)
3*fact(2)
3*fact(2)
3*fact(2)
3*2
4*fact(3)
4*fact(3)
4*fact(3)
4*fact(3)
4*fact(3)
4*fact(3)
4*6
5*fact(4)
5*fact(4)
5*fact(4)
5*fact(4)
5*fact(4)
5*fact(4)
5*fact(4)
5*24=120
Exemplo 2: Função para o cálculo da seqüência de Fibonacci.
#include<stdio.h>
long int f1( int num )
{
if (num < 0) // Se o número < 0 retorna erro.
//Função Fl - Método Recursivo
long int f1( int num );
retun(-1);
if (n == 1 || n == 2)
//Função F2 - Método Iterativo
// Se numero = 1 ou 2, então fibonacci é 1
long int f2( int num );
return 1;
else
int main(int argc, char* argv[])
// Caso contrário, chamada recursiva
return f1(n-1) + f1(n-2);
{
int numero=0;
}
long int fibo=0;
long int f2( int num )
scanf("%d", %numero);
{
int i, n1=0, n2=1, total=0;
if(num > 0)
fibo = f1(numero);
printf("\nfatorial %d = %d", &numero, %fibo);
{
total=1;
for (i = 2; i <= num; i++ )
fibo = f2(numero);
printf("\nfatorial %d = %d", &numero, %fibo);
{
total = ( n1 + n2 );
return 0;
n1 = n2;
}
n2 = total;
}
}
return total;
}
Nessa implementação existe duas chamadas recursivas e por isso essa pilha tem o formato de uma
árvore onde cada ramo se divide em dois.
1
f(4)=
1
f(2)+f(1)
f(2)+f(1)
1+f(1)
1+f(1)
1+1
f(3)+f(2)
f(3)+f(2)
f(3)+f(2)
f(3)+f(2)
f(3)+f(2)
1
2+f(2)
2+f(2)
2+1=3
Todo o algoritmo que contém mais de uma chamada recursiva gera uma pilha recursiva no formato
de árvore e o que varia é a quantidade de ramos da árvore. Se houver três chamadas recursivas cada ramo se
divide em três, se houver quatro chamadas cada ramo se divide em quatro e assim por diante.
Exemplo 3: Inversão de uma string
// Método inverter string
void inv1(char * str)
{
inv(str, 0, strlen(str)-1);
}
// Método recursivo inverter string
void inv(char * s, int i, int j)
{
char aux
if ( j - i > 2)
{
// Inverter a sub-string.
inv (s, i + 1, j – 1);
}
// Trocar os caracteres extreinos.
aux = s[j];
s[j] = s[i];
s[i] = aux;
}
// Método Iterativo
void inv2(char * str)
{
int i=0;
int j=strlen(str);
char aux
for( int i = O ; i < j ; ++i, --j )
{
// Trocar os caracteres extremos.
aux = s[j];
s[j] = s[i];
s[i] = aux;
}
}
Abaixo segue um exemplo da lista de recursão para inv("recurso", 0, 5).
inv("recurso",2,4)
inv1("recurso")
inv("recurso",0,6)
inv("recurso
recurso",1,5)
inv("recurso",1,5)
inv("rerucso",1,5)
inv("recurso
recurso",0,6)
inv("recurso",0,6)
inv("recurso",0,6)
inv("rsruceo
rsruceo",0,6)
inv1("osrucer")
Anexo: Biblioteca Conio.h
1.15 Instalação no DevCpp (windows ou linux)
1) Menu Tools e Check Updates/Packages
2) Select devpak server:: devpak.org Community
Devpaks.
Clique no botão Check for updates.
updates
4) Clique no botão Ok.
3) Localizar na lista Available update list:
list CONIO.
Clique no botão Download Selected..
5)Clique no botão Install
7) Menu Tools e Compiler Options
6) Clique no botão Finish
8) Clique Add these commands to te linker
command line.
Escreva na caixa de texto abaixo: -lconio
1.16 Instação e Configuração no Linux
Para instalar a biblioteca conio no linux baixe-a do site: http://sourceforge.net/projects/libconio/.
Para descompactar o arquivo libconio-1.0.0.tar.gz digite no terminal:
# tar xvf libconio-1.0.0.tar.gz
Entre no diretório que foi criado, compile e instale a biblioteca. Para isso basta digitar os comandos a
seguir:
# cd libconio-1.0.0
# ./configure
# make
# make install
1.17 Funções da Conio
O conio.h é um cabeçalho de funções usado no antigo arquivo do MS-DOS compiladores para criar
interfaces em texto. Ela não faz parte da linguagem de programação C, nem da biblioteca padrão C, nem da
ISO C e nem é exigido pela POSIX.
Este cabeçalho declara biblioteca várias funções úteis para a realização de entrada e saída em
"terminal/prompt MSDOS". A biblioteca funções declaradas pelo conio.h variam significativamente de
compilador para compilador. A biblioteca que se tornou a mais portável entre os compiladores foi do Turbo
C da Borland pois, não utilizava a API do DOS, mas interrupções da BIOS.
1.17.1 void clrscr (void);
A função clrscr limpa a tela e move o cursor para a posição (1,1). Caso não tenha definido a cor do
fundo com a função textbackground() o fundo permanecerá da cor atual. Caso contrário, ele ficará da cor
definida.
#include <conio.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
clrscr();
printf("pressione uma tecla para apagar a tela...");
getchar();
clrscr();
return 0;
}
1.17.2 void gotoxy (int x, int y);
A função gotoxy posiciona o cursor na tela nas coordenadas x (coluna) e y (linha). Se as coordenadas
são invalidas, a função é ignorada.
#include <conio.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
gotoxy(1,2);
printf("Primeira frase fica embaixo da Segunda.");
gotoxy(1,1);
printf("Segunda frase fica em cima da Primeira.");
gotoxy(1,4);
return 0;
}
1.17.3 int getch (void); / int getche (void); / int putch (int)
Essas funções possuem uma função bastante parecida: ambas esperam um caractere ser pressionado
no teclado, retornando a tecla pressionada. A diferença entre elas é que a função getch() não imprime o
caractere pressionado, o que ocorre com a getche(). A letra "e" final de getche significa echo, que significa
retornar a entrada.
Ambas as funções lidam com os caracteres especiais (setas, home, Fn, etc) usando dois (ou mais)
códigos. No windows, o primeiro caracter nesses casos é 0, enquanto no Linux é 27. Geralmente, no Linux
há três códigos para uma tecla especial, sendo o terceiro o especifico à tecla pressionada.
A função getch(), por não dar retorno, pode ser utilizado em situações na qual não é interessante que
seja impresso a tecla pressionada, como num menu onde se escolhe a opção com as setas ou numa rotina
para digitar uma senha.
A função getche() pode ser utilizada para receber uma tecla do teclado de cada vez, em contraste com
o scanf() que, mesmo para pegar um caracter, espera um pressionamento da tecla <ENTER>, gerando um
buffer.
A função putch exibe o caracter no monitor.
Elas respeitam as configurações feitas pelas funções da conio como window e mudança de cor.
#include <conio.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
char senha[7], char login[7];
int i;
printf("digite uma login com 6 digitos:")
for(i=0;i<6;i++)
{
login[i] = getche();
}
login[i]="\0";
printf("\n");
printf("digite uma senha com 6 digitos:")
for(i=0;i<6;i++)
{
senha[i] = getch();
putch('*');
}
senha[i]="\0";
printf("login: %s / senha: %s\n", login, senha);
return 0;
}
1.17.4 void delline (void);
A função delline apaga a linha que contem o cursor e move todas as linhas abaixo dela uma linha
para cima.
#include <conio.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
clrscr();
printf("Primeira frase.");
printf("Segunda frase.");
printf("Terceira frase.");
gotoxy(1,2);
delline();
gotoxy(1,4);
return 0;
}
1.17.5 void textcolor (int cor); / void textbackground (int cor);
A função textbackground troca a cor do texto de uma determinada frase, sendo que a cor é
determinada por um número.
A função textbackground troca a cor do fundo de uma determinada frase, sendo que a cor também é
determinada por um número. Para mudar a cor-do-fundo da tela inteira, é necessário, após usar a
textbackground(), usar também a clrscr(). Assim, todo o fundo será alterado. Estas funções não afetam
nenhum caracter que já esteja na tela.
Cor
Valor Permitido Permitido
Cor
Cor Fundo Cor Letra
BLACK
0
Sim
Sim LIGHTBLUE
BLUE
1
Sim
Sim LIGHTGREEN
GREEN
2
Sim
Sim LIGHTCYAN
CYAN
3
Sim
Sim LIGHTRED
RED
4
Sim
Sim LIGHTMAGENTA
MAGENTA
5
Sim
Sim YELLOW
BROWN
6
Sim
Sim WHITE
LIGHTGRAY
7
Sim
Sim BLINK
DARKGRAY
8
Não
Sim
Exemplo para mudança de cor:
#include <conio2.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
textbackground(BLUE);
textcolor(BROWN);
clrscr();
printf("Primeira frase.\n");
textcolor(WHITE+BLINK);
printf("Segunda frase.\n");
textbackground(RED);
textcolor(YELLOW);
printf("Terceira frase.\n");
return 0;
}
Valor
9
10
11
12
13
14
15
128
Permitido Permitido Cor
Letra
Cor Fundo
Não
Sim
Não
Sim
Não
Sim
Não
Sim
Não
Sim
Não
Sim
Não
Sim
Não
BLINK + cor