0% acharam este documento útil (0 voto)
5 visualizações

Tutorial C 11

Tutorial de programação na linguagem C
Direitos autorais
© © All Rights Reserved
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
5 visualizações

Tutorial C 11

Tutorial de programação na linguagem C
Direitos autorais
© © All Rights Reserved
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 30

Figura 1: Eniac

Tutorial C

1. Um pouco de história
Programar é criar um conjunto de instruções para dizer ao computador como executar uma
determinada tarefa.
Um dos primeiros problemas da programação foi como passar instruções aos computadores vistos que
esses são máquinas eletrônicas que só entendem dois valores 0 (desligado) onde não passa
eletricidade 1 (ligado) onde a eletricidade passa.
2. Por isso antigamente programadores eram figuras míticas que viviam em cavernas com seus
computadores, é a programação era realizada através de ligações manuais de chaves e fios
como você pode ver na figura 1 onde temos o Eniac considerado o primeiro computador do
mundo.
3. Programar dessa forma era demorado e complicado então logo apareceu a necessidade de se
criar uma linguagem que servisse de intermediária entre homem e maquina, surge o Assembly
uma linguagem que descreve as ações que um computador pode fazer por meio de mnemônicos
como ADD (soma) MOV (mover) que são traduzido em linguagem de máquina por um
”montador” assembler. Abaixo um programa em Assembly que soma dois números e subtrai a
soma de um terceiro:
MAIN PROC
MOV AX, 000BH
MOV BX, 00A1H
ADD AX, BX
MOV BX, 0005H
SUB AX, BX
MOV AH, 4CH
INT 21H
MAIN END P
4. END MAIN
Apesar de Assembly ter melhorado a situação seus programas ainda eram difíceis de entender e
muitos longos, não seria mais fácil simplesmente escrever:
X+Y–Z
Surge então as linguagens de alto nível onde programas podem ser escritos em uma linguagem mais
próxima o possível da linguagem humana (no caso o mais próximo possível da língua inglesa) e depois
traduzidos para linguagem de máquina.
A forma como essa tradução é feita cria duas outros classificações de linguagem de programação as
linguagens compiladas e interpretadas, a diferença está no tempo em que a tradução parta linguagem
de máquina ocorre:
1) Linguagens compiladas: são aquelas que tem o seu código traduzido antes da execução por
um programa denominado compilador. O compilador pega o arquivo que contém o programa
em linguagem de alto nível, arquivo fonte, e gera um arquivo do programa em linguagem de
máquina, arquivo executável. Quando você deseja executar o programa basta chamar o
arquivo executável.
Ex: C, C++, Fortran, Pascal, ADA
2) Linguagens interpretadas: nesse caso nós não temos um arquivo executável, o próprio
programa escrito em linguagem de alto nível usa um programa denominado interpretador que
traduz o programa linha por linha conforme é executado.
5. Ex: Python, PHP, JavaSscript, Lisp.

6. Ambiente de desenvolvimento
C é uma linguagem de programação compilada, isso é, nós desenvolvemos nossos programas em
uma linguagem mais próxima o possível da linguagem humana (no caso o mais próximo possível da
língua inglesa), os arquivos fonte, que depois serão traduzidos para uma linguagem que o computador
(hardware) possa entender, os arquivos executáveis. Para realizar essa tradução precisamos da ajuda
de um programa projetado para isso denominado compilador, nos exemplos desse tutorial estarei
usando o GCC ou GNU Compiler Collection uma coleção de compiladores criados pelo projeto GNU
(General Public License).
Considero que ao longo desse tutorial estaremos usando um sistema operacional Linux, o que é bem
pratico uma vez que a maioria das distribuições Linux já vem com o GCC pré instalado e pronto para
compilar programas em C. Se você for usar o Windows como sistema operacional considere usar o
MinGW que é uma versão portável de um conjunto de ferramentas GNU incluindo o GCC
(o compilador C do GNU) para o Windows.
Para escrever os programas deste tutorial você pode usar qualquer editor de textos
simples como gedit. Atenção não use editores de texto do tipo office, pois estes embutem
no texto suas marcações próprias o que na hora de compilar o programa irá gerar erros.
7. A estrutura de um programa em C
C é uma linguagem feita por pequenos pedaços de códigos chamados de funções, abaixo
encontramos o exemplo da estrutura de uma função:
int myfuncao() {
// as instruções ficam aqui
}
Onde:

➔ int é o tipo de dado do valor retornado, nesse caso seria um valor inteiro.

➔ myfunction() é nome da função, sempre com abre e fecha parenteses depois. Dentro dos
parênteses normalmente vão valores (parâmetros) que queremos que sejam tratados pela
função, mas, mesmo no caso de não passarmos nenhum valor para a função devemos colocar
os parênteses depois do nome da função.
➔ as chaves { } abrem e fecham o corpo da função. E dentro das chaves que vamos colocar
nossas instruções.
Como todo o programa de computador precisa de um início em C temos uma função especial
denominada main que é onde todo o programa em C começa.

Dadas essas primeiras introduções vamos escrever nosso primeiro programa em C, para
isso abra o editor de texto e digite o código mostrado abaixo, aqui sugiro crie um diretório
(pasta) somente para guardar os arquivos criados nesse tutorial, agora salve-o como
olamundo.c (programas fonte são criados usando-se a extensão .c):
/*
Meu primeiro Programa em C
o famoso Olá Mundo
*/

#include <stdio.h>

// Inicio do programa
int main() {

printf("Olá Mundo \n");

return 0;
}
Quem já aprendeu outra linguagem de computador provavelmente já viu algo parecido, esse é o
famoso programa Olá Mundo ou Hello World com o qual a maioria dos autores começam a ensinar
uma linguagem de computador, ele simplesmente escreve no terminal Olá Mundo.

Feitas as devidas apresentações vamos dissecar a estrutura do programa linha por linha:

------------------------------------------------------------------------------------------------------------------------
Linha 1 -
/*
Inicia um espaço para comentários de múltiplas linhas, lembrando que um bom
programador sempre comenta seus códigos para que no futuro outros
programadores e mesmo você possa entender o que foi feito.
Linha 2 e 3 -
Meu primeiro Programa em C
o famoso Ola Mundo
Este é o nosso cometário de duas linhas.
Linha 4 -
*/
Fecha o espaço de cometários.
Linha 5 -
#include <stdio.h>
A instrução include precedida de cerquilha (#) solicita ao compilador para incluir o
arquivo de cabeçalho stdio.h no programa. O arquivo stdio.h faz parte das
bibliotecas padrões de C adotadas pela maioria dos compiladores, stdio.h contem
funções pré-definidas para cuidar de entradas e saídas dos programas em C.
Os arquivos com extensão .h sendo o h de header são conhecidos como arquivos
de cabeçalho sua prerrogativa é disponibilizar outras funções que alguém já se deu
ao trabalho de escrever facilitando nossa vida.
Linha 7 -
// Inicio do programa
Duas barras servem para inserir um comentário de uma única linha.
Linha 8 -
int main() {
É onde nosso programa começa. A função main é obrigatória em C pois a primeira
chamada de um programa em C é para a função main e é dentro dela que você
coloca o seu código e as chamadas as outras funções de um programa em C. Se
não existir uma função main no seu programa o C não saberá por onde começar
a executar o programa. O abre e fecha parênteses vazio depois da declaração de
main indicam que ela não recebe nenhum parâmetro (irei abordar parâmetros
melhor quando entrarmos em funções em C). O int na frente da função main
indica que ela deve retornar um valor do tipo inteiro, devendo retornar zero se
tudo ocorrer bem ou outro número caso o programa encerre de forma inesperada.
A chave de abertura ({) após main() indica o início do bloco de instruções da
função main que deve ser encerrado por uma chave de fechamento (}).
Linha 10 -
printf(“Ola Mundo \n”);
Antes de analisamos a instrução acima vale ressaltar a identação do código ou
tabulação. No código acima você deve ter reparado, se não for cego, o recuo dado
em relação a linha 8 dessa nossa nova instrução. É de boa praxe em programação
sempre recuar as linhas dentro de um bloco de instruções isso torna os seus
programas mais legíveis e organizados. Em C essa identação costuma ser de 4
colunas ou espaços em branco.
A função printf() faz parte da biblioteca stdio.h e serve para imprimir algo no
terminal nesse caso ela recebe como parâmetro uma cadeia de caracteres
formando a frase Olá Mundo seguido de um espaço e pelo caracteres de nova
linha representado por \n (essa representação faz com que o terminal vá para uma
nova linha). Repare que tudo está dentro de aspas duplas, está é a forma de se
representar uma cadeia de caracteres em C.
Ao final da função printf() temos um ponto e virgula, ele serve para encerrar uma
instrução, ele só não é usado depois de instruções precedidas de cerquilha (#)
como include. Então lembre-se Toda e qualquer instrução em C deve terminar
com um ponto e virgula.
Linha 12 -
return 0;
É a última instrução da função main() retornando um inteiro no caso o valor zero
que serve para indicar que nossa função main() terminou sem problemas. Caso
nosso programa fosse encerrado inesperadamente por algum erro em tempo de
execução um valor diferente de zero seria retornado e poderia ser capturado por
outro programa que estive-se aguardando o fim do nosso programa para que
pudesse lidar com o erro do nosso programa.
Linha 14 -
}
Indica o fim do nosso bloco de instruções.
------------------------------------------------------------------------------------------------------------------------
Bom escrito nosso código precisamos compilá-lo para gerar o arquivo executável, para isso abra o
terminal do Linux navegue até a pasta em que você salvou o arquivo olamundo.c e digite o comando
abaixo:

$ gcc olamundo.c -o olamundo

OBS:
Se ao tentar compilar o programa aparecer a mensagem:
stdio.h: Arquivo ou diretório não encontrado
É porque em algumas distribuições Linux o compilador gcc tem vindo sem algumas bibliotecas para
solucionar o problema instale o pacote build-essential.
Exemplo para instalação no Ubuntu e derivados::
$ sudo apt-get install build-essential
Agora dentro do seu diretório você terá os arquivos olamundo.c e o arquivo compilado olamundo:
Para

executar o programa basta digitar:


$ ./olamundo

Você pode estar se perguntando:


Por que não criamos o executável olamundo como o sufixo .exe?
É que por padrão no Linux nós não temos arquivos com o sufixo .exe, os arquivos executáveis
simplesmente não usam sufixo.
Por que eu preciso usar o ./ para executar o arquivo?
No Linux programas são executados apenas se indicarmos o diretório onde ele se encontra
como o ponto (.) indica o diretório atual colocamos ele seguido da barra, se fossemos executar nosso
arquivo de fora dos diretório atual teríamos que colocar algo como /home/meudir/tutorialC/olamundo.

8. Números Binários e Hexadecimais


4.1 Números Binários
Como já vimos no início desse tutorial computadores só conseguem trabalhar em cima de dois valores
0 (zero) e 1 (um), representando os estados ligado e desligado. Para formar qualquer outro valor ele
precisa combinar os valores 0 e 1 o que nós leva ao conceito de números binários.

Estamos acostumados a trabalhar com números na base 10 (dez símbolos os números de 0 a 9)


sem que nem nós atentemos para esse fato, por exemplo o número 104 pode ser representa da
seguinte maneira:
1 x 102 + 0 x 101 + 4 x 100 = 100 + 0 + 4 = 104
Números binários funcionam da mesma forma só que na base 2 (dois símbolos 0 e 1), onde 104 seria
expresso em binários da seguinte forma:
1 x 26 + 1 x 25 + 0 + x 24 + 1 x 23 + 0 x 22 + 0 x 21 + 0x 20 =
64 + 32 + 0 + 8 + 0 + 0 + 1= 105
A cada representação binaria (0 ou 1) é dado o nome de bit (bynari digit).
Computadores costumam agrupar binários em grupos de oito também conhecidos como bytes. A
nossa representação do número 104 em bytes seria então:
01101000
4.2 Números Hexadecimais
Os números hexadecimais como o próprio nome diz são compostos por dezesseis dígitos que são os
números de 0 a 1 mais as letras A, B, C, D, E e F representado os números 10, 11, 12, 13, 14 e 15
respectivamente

9. Memória do Computador
Memória de computadores pode ser um assunto complexo, mas, aqui vou simplificar isso o máximo
possível.
A memória pode ser classificadas como:
• Memória principal: a memória principal de um computador é chamada de RAM (Randomic
Acess Memory), sua caraterística é ter um tempo de acesso (o tempo que a CPU leva para
buscar um dado) extremamente rápido e por sua volatilidade, assim que você desliga o
computador tudo que estiver armazenado nela é perdido.
• Memória secundaria: caraterizada por ter um tempo de acesso maior que a memória principal é
por não ser volátil, mesmo após você desligar o computador tudo que esta armazenado nela
continua lá. São os discos rígidos, cd, dvd etc...
Nossos programas residem na memória secundaria e quando são chamados para executar são
carregados para a memória principal permanecendo lá até o fim de sua execução.
O que nós interessa é a memória RAM e como computador armazena seus dados nela. Já vimos que
o computador trabalha com bits sua menor unidade, para poder representar valores maiores que 0 e 1
o computador agrupa os bits normalmente em um grupo de 8 bits chamados bytes. A memória do
computador é dividida em bytes onde cada byte recebe um endereço para que a CPU possa encontrar
o dado desejado de acordo com seu endereço, veja tabela abaixo que representa nossa memória:

Endereço bytes
2000
2001
2002 01010001
2003
2004
Tabela 1
Na tabela acima temos o endereço de numero 2002 armazenando o número 81 ou o byte 01010001.
Quando o computador precisa armazenar um numero ou instrução maior do que o que cabe em um
byte (11111111 = 255) ele agrupa esse valor em mais de um byte em endereços consecutivos na
memória.

10. Tipos de dados


Programas de computadores consistem em receber uma serie de dados brutos é nós
devolver uma informação, como por exemplo receber as notas de um aluno é nós
informar se ele foi aprovado ou não.
Nós podemos dividir os tipos de dados entre os primitivos e compostos.
Os tipos de dados primitivos são:
• Números inteiros: não possuem partes decimais nem fracionarias, podem ser
negativos ou positivos (-50, 3, 47, 0, -9)
• Números reais: podem possuir partes decimais e fracionarias, podem ser negativos
ou positivos (3,1415; 9,8; -0,5)
• Caracteres: qualquer letra do alfabeto, dígitos e/ou símbolos especiais.
• Booleanos: só pode tem dois valores verdadeiro ou falso, normalmente
representados nas linguagens de programação por true ou TRUE e false ou FALSE
Tipos compostos de dados são aqueles que podem se obtidos da combinação dos tipos
primitivos, onde o melhor exemplo é:
• Strings: cadeias de caracteres (“123R”, “_saida”. “Lobo 123”)

10.1. Tipos de dados em C


A linguagem C apresenta cinco tipos de dados primitivos:
inteiro, caractere, ponto flutuante e ponto flutuante de dupla precisão
representados nos programas como:
int, char, float e double.
C não possui um tipo de dado booleano, como true e false, ao invés disso C considera qualquer valor
zero como falso e tudo diferente de zero como verdadeiro.
Junto como os dos tipos primitivos C possui os qualificadores:
signed, unsigned, short e long
Os qualificadores signed e unsigned, servem para definir se a faixa dos números ira incluir números
com sinal ou não. Eles só podem ser empregados com os tipos int e char visto que o C trata o tipo
caractere como um número inteiro. Como signed define os números com sinal ele e redundante e seu
uso e desaconselhado uma vez que a declaração int por padrão assume os números com sinal. A
grande diferença em usar unsigned é que como computadores usam o bit mais significativo (bit de
valor mais alto) como marcador de sinal os valores da faixa de unsigned podem atingir números
inteiros sem sinal em uma faixa maior do que signed.
Os qualificadores short e long servem para prover tamanhos diferentes nos tipos básicos nas
maquinas onde isso é possível, lembrando que o numero de bytes que um computador pode trabalhar
depende de seu hardware.
Todos esses qualificadores podem ser usados com os tipos int e char, fora esses tipos o qualificador
long pode ser usado com o tipo double.
Como estes tipos estão intimamente ligados a maquina em que se está trabalhando na tabela 2
mostramos estes valores em um PC 32/64 bits.

Tipo Bytes Faixa de Valores


char 1 -128 a 127
unsigned char 1 0 a 255
int 4 −2.147.483.648 a 2.147.483.647
unsigned int 4 0 a 4294967295
short int 2 -32.768 a 32.767
unsigned short int 2 0 a 65.535
long int 4 −2.147.483.648 a 2.147.483.647
unsigned long int 4 0 a 4.294.967.295
float 4 seis dígitos de precisão
double 8 dez dígitos de precisão
long double 16 (64) ou 8 (32) dez dígitos de precisão
Tabela 2

11. Variáveis
Variáveis servem para o programa reservar espaço na memória para um determinado tipo de dado.
Variáveis em C devem começar com uma letra ou um sublinhado (_) seguido de letras sublinhados e
números. Exemplos de nomes de variáveis:

peso, altura2, v2t, somA, Soma, xyz_21, _depois


Devo lembrar que C é case sensitive ou seja, ele diferencia maiúsculas e minusculas,
então no caso acima somA e Soma são duas variáveis diferentes.
Por motivos óbvios não se deve dar a variáveis nomes de palavras reservadas em C. Alguns exemplos
de palavras reservadas estão representados na tabela 3 abaixo:

auto break case char continue


do double define else enum
float for goto if int
long return short sizeof static
struct union unsigned void while
Tabela 3
C é uma linguagem fortemente tipada ou seja, uma variável deve ser declarada junto com seu tipo de
dado e não se deve atribuir um valor com tipo de dado diferente a essa variável com o risco de coisas
estranhas ocorrerem.
Vamos agora fazer um pequeno teste com as nossas variáveis e seus tipos de dados. Digite o
programa abaixo e salve-o como tipodados1.c:
/*
Teste 1 dos tipos de dados
*/

#include <stdio.h>

// Inicio do programa
int main() {
int x;
short int y;

x = 400000;
y = x;

printf("\nO valor de int de x é: %i", x);


printf("\nO valor short int de y é: %i\n\n", y);

return 0;
}
Nesse programa criamos a variável x do tipo int e y do tipo short int, lembrando que as variáveis
devem sempre ser declaradas junto com seus tipos antes de serem usadas em no programa e que
embora elas possam ser declaradas em qualquer parte do programa é de boa pratica declararas no
início do programa. Depois de declaradas a variável x recebe o valor de 400000 através do operador
de atribuição = e após isso fizemos y receber o mesmo valor de x.
Após criadas e iniciadas as variáveis x e y nós iremos mostrar esses valores na tela do computador e
para isso estamos usando a função printf incrementada usando o operador de conversão %i
para transformar os valores de x e y em uma seqüência de caracteres numéricos que
serão mostrados na tela do nosso terminal.
Compile e execute o programa e você devera ver algo como na figura 5:

Neste programa temos o típico caso de alguém que esta tentando guardar uma caixa maior em uma
caixa menor, o tipo short int não pode guardar todos o bytes do tipo int, veja a representação dos
valores 400000 e 6748 em bits na tabela 3 abaixo:
400000 0110.0001.1010.1000.0000
6784 0000.0001.1010.1000.0000

Tabela 4
Como você pode observar quanto tentamos guardar o valor de uma variável do tipo int em uma
variável do tipo short int o que programa faz é descartar os bytes a mais da variável int para que ela
possa caber em uma variável short int. Você pode colocar um short int em um int, pois o tipo int tem
como acomodar o numero de bytes do tipo short int, mas não o contrário. Por isso fica desde já aviso:
Nunca é bom misturar variáveis de tipos diferentes em seus programas.

12. Operadores aritméticos


12.1. Operadores aritméticos básicos
Em C existe além dos quatro operadores aritméticos básicos da matemática outros três operadores: os
unários (que atuam sobre um único elemento) para o incremento de um outro para o decremento de
um e o operador de resto de uma divisão, apresentados na tabela 5 abaixo:

Operador aritmético Função


+ Realiza a soma de dois valores
- Realiza a subtração de dois valores
* Realiza a multiplicação de dois valores
/ Realiza a divisão de dois valores
% Retorna o resto de uma divisão por inteiros
++ Incremento
-- Decremento
Tabela 5
Além dos operadores acima temos o operador de atribuição (=) sua função é atribuir o valor da
expressão que se encontra do seu lado direito a uma variável ou ponteiro que deve estar no seu lado
esquerdo.
Exemplo do operador resto:
x = 10 % 7
Neste caso x recebe o valor 3 ou seja, o resto da divisão de 10 por 7, salientando que o uso do
operador resto só pode ocorrer entre números do tipo inteiro.
Exemplos de incremento e decremento:
x = 10;
x++;

Após a aplicação do operador de incremento a variável x agora vale 11.


Exemplo de decremento:
y = 9;
y--;

Após a aplicação do operador de decremento a variável y agora vale 8.


Quando usamos os operadores de incremento e decremento o lugar onde ele é colocado ira
influenciar no resultado de uma atribuição, exemplo:
x = 10;
y = x++;

No caso acima apesar da variável x ter tido seu valor alterado para 11 a variável y recebe o valor 10
pois a operação de incremento foi realizada depois da atribuição. Para que a variável y recebesse 11
como valor deveríamos realizar a operação de decremento antes da atribuição:
x = 10;
y = ++x;

Agora sim a variável y recebe o valor 11.


Não tente aplicar os operadores de incremento ou decremento diretamente a valores como por
exemplo:

x = ++11;

12.2. Operadores aritméticos e ordem de precedência


A ordem de precedência dos operadores é dada pela primeira coluna da tabela 6 onde os operadores
no início da tabela tem maior precedência, a segunda coluna indica a direção da avaliação, além dos
operadores já apresentados inserimos o parenteses que tem maior precedência sobre todos os outros
operadores apresentados até o momento.

Operador aritmético Ordem de avaliação


() esquerda → direita
++ -- direita → esquerda
* /% esquerda → direita
+- esquerda → direita
+=, -=, *=, /= e = esquerda → direita
Tabela 6
Antes de continuarmos devemos saber que uma das coisas que ocorrem quando vamos escrever uma
expressão matemática em um programa é a necessidade de sua linearização como no exemplo
abaixo:
( 4 −20 )
7 => (4 – 20) / 7 +20
+ ¿ 20

Um exemplo de precedências passo a passo:


x = 3 + (4 – 20) / 4 + 2 * 3;
no primeiro passo a operação realizada é a subtração de 4 - 20 por se encontrar
entre parênteses
x = 3 - 16 / 4 + 2 * 3; (resultado do primeiro passo)
no segundo passo a operação realizada e a divisão por ser o operador de
maior precedência mais a esquerda
x = 3 – 4 + 2 * 3; (resultado do segundo passo)
no terceiro passo a operação realizada e a multiplicação por ser o operador de
maior precedência
x = 3 – 4 + 6; (resultado do terceiro passo)
no quarto passo a operação realizada e a subtração de 3 - 4 por ser o operador de
maior precedência mais a esquerda
x = -1 + 6; (resultado do quarto passo)
e por fim o quinto e último passo a soma de -1 + 6 atribuindo o valor 5 a variável x
x = 5; (resultado do quinto passo)
Tente fazer o exemplo acima mas sem os parênteses:
x = 3 + 4 – 20 / 4 + 2 * 3;
Vamos criar um programa para converter uma temperatura em Fahrenheit para Celsius
através da formula:
c
e
l
s
i
u
s
¿
5
9
( ¿ f ¿ a ¿ h ¿ r ¿− ¿ 32 ¿ )

que para nosso programa fica :


celsius = (5 / 9) * (fahr -32);
No programa apresentamos uma nova função (scanf) que serve para leitura de dados
através do teclado, não entraremos em muitos detalhes sobre essa função agora,
portanto, simplesmente copie o código abaixo no seu editor de textos salve-o como
celsius1.c. Ao executar o programa será pedido você entre com u ma temperatura em
Fahrenheit , simplesmente digite a temperatura e tecle enter:

/*
Conversor de Fahrenheit para Celsius
*/

#include <stdio.h>

// Inicio do programa
int main() {
double celsius;
double fahr;

printf("\nEntre com uma temperatura em Fahrenheit: ");


scanf("%lf", &fahr);

celsius = (5 / 9) * (fahr - 32);

printf("\nO valor em Celsius é: %lf\n\n", celsius);

return 0;
}
Quando executamos o programa obtemos o resultado da figura 6 abaixo:

No programa acima nós temos um sério erro, qualquer que seja o valor que você entre com
temperatura em Fahrenheit ele sempre irá retornar zero para a temperatura em Celsius. O que deu
errado no nosso programa é uma peculiaridade de C que acontece ao dividirmos 9 por 5,
o programa considerou que estávamos dividindo dois números inteiros e ao invés de nos
devolver a dizima periódica 0.555555 ele devolve o numero inteiro 0. Para resolver esse
problema devemos avisar que estamos trabalhando com números com ponto flutuante
usando os valore 5.0 e 9.0 para isso.
Corrigindo o programa colocando todos os números com o ponto decimal, bastaria colocar
só os valores de 5 e 9, mas, para evitar outros problemas vamos sempre colocar todos os
valores com ponto decimal:
/*
Conversor de Fahrenheit para Celsius
*/

#include <stdio.h>

// Inicio do programa
int main() {
double celsius;
double fahr;

printf("\nEntre com uma temperatura em Fahrenheit: ");


scanf("%lf", &fahr);

celsius = (5.0 / 9.0) * (fahr - 32.0);

printf("\nO valor em Celsius é: %lf\n\n", celsius);

return 0;
}
Agora sim nosso programa consegue converter Fahrenheit para Celsius como na figura
7:

13. Operadores de bits


C é uma das linguagens de programação que mais se aproxima da linguagem de maquina e um dos
motivos para isso é que C permite operações com bits muito útil na criação de rotinas para
impressoras, modens e etc....
As operações com bits apresentadas abaixo só podem se executadas em variáveis do tipo inteiro ou
caractere:
Operador Nome
& E (AND)
| OU (OR)
^ OU exclusivo (XOR)
~ Complemento de um
<< Deslocamento à esquerda
>> Deslocamento à direita

Tabela 7

13.1.
13.2. O operador & (E)
Segue o esquema bit a bit da tabela 9:
x y x&y
1 1 1
1 0 0
0 1 0
0 0 0

Tabela 8
Exemplo:
x = 90
0 1 0 1 1 0 1 0
y = 98
0 1 1 0 0 0 1 0
14. x & y = 66
0 1 0 0 0 0 1 0

14.1. O operador | (OU)


Segue o esquema bit a bit da tabela 10:
x y x&y
1 1 1
1 0 1
0 1 1
0 0 0

Tabela 9
Exemplo:
x = 90
0 1 0 1 1 0 1 0
y = 98
0 1 1 0 0 0 1 0
15. x | y = 122
0 1 1 1 1 0 1 0

15.1.
15.2. O operador ^ (OU exclusivo )
Segue o esquema bit a bit da tabela 11:
x y x^y
1 1 0
1 0 1
0 1 1
0 0 0

Tabela 10
Exemplo:
x = 90
0 1 0 1 1 0 1 0
y = 98
0 1 1 0 0 0 1 0
16. x ^ y = 122
0 0 1 1 1 0 0 0

16.1. O operador ~ (Complemento de um)


Segue o esquema bit a bit da tabela 12:
x ~x
1 0
0 1

Tabela 11
Exemplo:
x = 90
0 1 0 1 1 0 1 0
~x = 165
1 0 1 0 0 1 0 1

16.2. Operador << (Deslocamento à esquerda)


Desloca para a esquerda os bits da variável a esquerda pelo numero da variável a direita, exemplo
onde x = 25, y = 2:
x = 25
0 0 0 1 1 0 0 1
x << y = 100
0 1 1 0 0 1 0 0

16.3.
16.4. Operador >> (Deslocamento à direita)
Desloca para a esquerda os bits da variável a esquerda pelo numero da variável a direita, exemplo
onde x = 25, y = 2:
x = 25
0 0 0 1 1 0 0 1
x >> y = 3
0 0 0 0 0 1 1 0

Repare que nesse caso os bits mais a direita 0 e 1foram dispensados.

17. As funções printf e scanf


17.1. A função printf
Como já vimos anteriormente a função printf serve para imprimir uma cadeia de caracteres no
terminal. Podemos dizer que essa função recebe um ou mais parâmetros sendo o primeiro uma a
cadeia de caracteres e o restante expressões que podem ser variáveis ou expressões realmente como
por exemplo x + 2 onde x é uma variável já definida com um valor. Veja um exemplo de printf:

printf(“um numero %i e outro numero %i”, x, x + 2);


Onde como vimos %i é um operador de conversão usado para transformar um valor inteiro em uma
sequência de caracteres numéricos sendo que cada operador de conversão deve corresponder a uma
expressão na sequência em que surgem dentro da função, no caso acima o primeiro %i corresponde
ao valor de x, e o segundo corresponde ao valor resultante de x + 2. Abaixo segue a tabela 9 com os
operadores de conversão:

operador conversão
%c caractere
%d inteiros com sinal
%i inteiros com sinal
%f ponto flutuante
%lf ponto flutuante de dupla precisão
%s cadeia de caracteres (string)
%p ponteiro
%e Notação cientifica com e minusculo ex: 1.243255e+22
%E Notação cientifica com e minusculo ex: 3.454353E-05
%o octal
%x Hexadecimal sem sinal com letras minusculas ex: f2
%X Hexadecimal sem sinal com letras maiúsculas ex: C3
%% Escreve o simbolo %
Tabela 12
Além disso temos os caracteres que não possuem representação no teclado e portanto
são apresentados por uma barra invertida seguida de um caractere como \n cujo
significado e o caractere de nova linha (new line) outra representação em que a barra
invertida é usada e no escape de caracteres como aspa dupla (“) que devem ser
escapados para não criarem problemas na representação de uma cadeia de caracteres.
Abaixo na tabela 13 representações e seus significados:
Representação Significado
\b Backspace - retrocesso do cursor em um caractere ()
\f Form feed - salto da página
\n New Line - Insere uma nova linha
\r Carriege Return - retrocede o cursor para o inicio da linha
\t Tab - Tabulação horizontal
\” Aspa dupla
\' Aspa simples
\0 Caractere nulo - corresponde ao final de uma string
\\ Barra invertida
\a Beep - emite um sinal de alerta
Tabela 13
Vamos melhorar o nosso programa celsius1.c, se lembra ele converte a temperatura de Fahrenheit
para Celsius, ficando o novo programa celsius2.c como abaixo:
/*
Conversor de Fahrenheit para Celsius
*/

#include <stdio.h>

// Inicio do programa
int main() {
double celsius, fahr;

printf("\nEntre com uma temperatura em Fahrenheit: ");


scanf("%lf", &fahr);

celsius = (5.0 / 9.0) * (fahr - 32.0);

printf("\nO valor em Celsius é: %.2lf\n\n", celsius);

return 0;
}
Nessa nova versão a primeira coisa que alteramos foi declarar as duas variáveis logo depois do tipo
separadas por uma virgula, sempre que tivermos variáveis do mesmo tipo podemos usar esse tipo de
declaração com as variáveis separadas por virgula e no final o ponto e virgula. Inserimos outra
novidade que é a formatação %.2f, essa é uma formatação para uma saída com só duas casas
decimais em números com ponto flutuante veja a saída na figura 8 abaixo:

Abaixo na tabela 14 como formatar a saída de números inteiros e com ponto flutuante:

operador conversão
%nd Formata um inteiro com n caracteres de saída de se n for maior que o
número de saída o restante sera preenchido com espaços a esquerda
ex: %6d a saída no numero 1060 fica __1060 onde _ e um espaço
em branco
%0nd Formata a saída de um inteiro com n caracteres de saída de se n for
maior que o número de saída o restante sera preenchido com zeros a
esquerda ex: %6d a saída no numero 1060 fica 001060
%nf Formata ponto flutuante com pelo menos n caracteres
%n.kf Formata ponto flutuante com pelo menos n caracteres e k caracteres
depois do ponto decimal
%n.f Formata ponto flutuante com pelo menos n caracteres e nenhum
caractere depois do ponto decimal
%.nf Formata ponto flutuante com pelo menos n caracteres depois do
ponto decimal
%.f Formata ponto flutuante sem nenhum caractere depois do ponto
decimal
Tabela 14

17.2. A função scanf


A função scanf faz o papel inverso do que realiza na função printf, veja o exemplo abaixo:
scanf(“%lf %d”, &x, &y);

No exemplo o primeiro parâmetro “%lf %d” da função scanf faz o papel inverso do que realiza na
função printf os operadores de conversão %lf e %d irão converter caracteres vindos do terminal para
os seus tipos de dados respectivamente, um número de ponto flutuante duplo e um número inteiro,
estes valores serão atribuídos aos parâmetros seguintes &x e &y. Nós parâmetros seguintes da
função scanf aparece o operador unário & que vem a frente das variáveis x e y, este especificador nós
da o endereço na memoria reservado as variáveis x e y e indica que estamos lendo os valores vindos
do terminal para dentro do endereço na memoria apontados por &x e &y.
Vamos criar o programa celsius3.c melhorando nosso programa celsius2.c para que ele leia duas
temperaturas pelo teclado, e a saída seja na forma de uma tabela:
/*
Conversor de Fahrenheit para Celsius
*/

#include <stdio.h>

// Inicio do programa
int main() {
double celsius1, celsius2, fahr1, fahr2;

printf("\nEntre com as duas temperaturas em Celsius\n");


printf("separadas por uma virgula e um espaço em branco: ");
scanf("%lf, %lf", &fahr1, &fahr2);

celsius1 = (5.0 / 9.0) * (fahr1 - 32.0);


celsius2 = (5.0 / 9.0) * (fahr2 - 32.0);

printf("\nFahrenheit\t Celsius\n");
printf("%10.2lf\t%10.2lf", fahr1, celsius1);
printf("\n%10.2lf\t%10.2lf\n\n", fahr2, celsius2);

return 0;
}
Sua saída deve ser semelhante a figura 9:
Como você deve ter reparado nós usamos a função scanf com uma formatação própria de entrada
onde pedimos que a entrada das temperaturas sejam separadas por uma virgula e um espaço em
branco.
scanf("%lf, %lf", &fahr1, &fahr2);

Na função printf colocamos uma formatação %10.2lf que serve para imprimir um valor com no mínimo
10 caracteres, sendo que 2 são depois do ponto decimal, fizemos isso com o intuito de ajustar os
números a tabulação.

18. O escopo de variáveis


As chaves { } marcam o escopo de um bloco de instruções onde as variáveis criadas dentro desse
bloco só serão validas dentro desse bloco ou em blocos mais internos, veja o programa escopo.c
abaixo:
#include <stdio.h>

// Inicio do programa
int main() {
//Bloco Principal
int x = 25;
int y = 30;

{
// Bloco 1
int x = 15;
int y = 10;

printf("\nDentro do Bloco 1\n");


printf("o valor de x é: %i\n", x);
printf("o valor de y é: %i\n", y);
}

{
// Bloco 2
int y = 20;

printf("\nDentro do Bloco 2\n");


printf("o valor de x é: %i\n", x);
printf("o valor de y é: %i\n", y);
}

printf("\nDentro do Bloco Principal\n");


printf("o valor de x é: %i\n", x);
printf("o valor de y é: %i\n\n", y);

return 0;
}
Nesse programa criamos varias variáveis com os mesmos nomes, isso só foi possível porque cada
uma delas esta em um bloco de instruções diferentes. No Bloco Principal criamos as variáveis x e y,
e criamos no Bloco 1 novas variáveis x e y com valores inicias diferentes. Nós podemos ver quando
imprimimos essas variáveis dentro de seus respectivos blocos que elas realmente tem valores
distintos. Também criamos uma nova variável y no Bloco 2, porém não criarmos uma variável x, então,
quando imprimimos a variável x nesse bloco na verdade estamos imprimindo o valor de x relativo ao
bloco mais externo o Bloco Principal. Vale lembrar que variáveis só são validas dentro do bloco em
que foram criadas ou em blocos internos a esses. Podemos verificar isso ao executar o programa
como na figura 10:

19. Constantes em C
Constantes seguem a mesma regra de nomeação de variáveis.
Existem duas formas de se criar uma constante em C:

19.1. Usando a diretiva #define


A diretiva #define vem logo depois da declaração das bibliotecas (#include) e é criada com a sua
declaração seguida do nome da constate e de seu valor, sem a necessidade do uso do operador de
atribuição =, abaixo temos um exemplo da criação de uma constante com o nomo PI:
#include
#define PI 3.1415
As contantes criadas com #define tem escopo global, isso significa que elas são validas em qualquer
bloco de instruções do programa.
Já vimos como converter Fahrenheit para Celsius para converter Celsius para Fahrenheit podemos
usar a formula:
fahr = 32 + 1.8 * celsius
Agora vamos criar o programa fahr1.c para converter Celsius para Fahrenheit usando constantes com
a diretiva #define
/*
Conversor de Celsius para Fahrenheit
*/

#include <stdio.h>

/*
Note que não usamos o sinal de igual
e nem o ponto e vírgula no final
*/
#define K 1.8
#define C 32.0

// Inicio do programa
int main() {
double celsius1, celsius2, fahr1, fahr2;

printf("\nEntre com as duas temperaturas em Celsius\n");


printf("separadas por uma virgula e um espaço em branco ex 23.5,
89.0:\n");
scanf("%lf, %lf", &celsius1, &celsius2);

fahr1 = C + K * celsius1;
fahr2 = C + K * celsius2;

printf("\nFahrenheit\t Celsius\n");
printf("%10.2lf\t%10.2lf", fahr1, celsius1);
printf("\n%10.2lf\t%10.2lf\n\n", fahr2, celsius2);

return 0;
}
Sua saída deve ser semelhante a figura 11:
19.
2.
19.
3. Usa
ndo

const
A criação de constantes com const é muito similar a declaração de variáveis:
const double PI = 3.1415;

Onde a constante tem um tipo é o mesmo escopo de uma variável.


No programa fahr2.c substituímos #define por const para declarar as constantes:
/*
Conversor de Celsius para Fahrenheit
*/

#include <stdio.h>

// Inicio do programa
int main() {
const double C = 32.0, K = 1.8;

double celsius1, celsius2, fahr1, fahr2;

printf("\nEntre com as duas temperaturas em Celsius\n");


printf("separadas por uma virgula e um espaço em branco ex
23.5, 89.0:\n");
scanf("%lf, %lf", &celsius1, &celsius2);

fahr1 = C + K * celsius1;
fahr2 = C + K * celsius2;

printf("\nFahrenheit\t Celsius\n");
printf("%10.2lf\t%10.2lf", fahr1, celsius1);
printf("\n%10.2lf\t%10.2lf\n\n", fahr2, celsius2);

return 0;
}

20. Op
era
dor
es

relacionais e lógicos
Como qualquer linguagem de programação C possui estruturas capazes de tomarem
decisões durante a execução do programa través de expressões condicionais que
retornam verdadeiro ou falso com base nos operadores relacionais (tabela 15) e
operadores lógicos (tabela 16).
Operador relacional Descrição
> Maior que
>= Maior ou igual
< Menor que
<= Menor ou igual
== Igual
!= Diferente

Tabela 15
Operador logico Descrição Ação
&& AND (E) Retorna falso se uma das condições for
falsa
|| OR (OU) Retorna falso somente se ambas as
condições forem falsas
! NOT (NÂO) Usado para alterar a condição se ela for
verdadeira passa a ser falsa e vice-versa
Tabela 16
A função dos operadores relacionais é de comparar duas expressões e verificar se esta comparação é
verdadeira ou falsa exemplos:
(10 - 9) < (12 - 8)

é verdadeira pois (10 - 9) é igual a 1 que (12 - 8) é igual a 2 então a expressão (10 -9) é menor que (12
-8)
(4 - 3) == 5

é falsa pois 1 não é igual a 5


Os operadores lógicos concatenam uma serie de expressões com os operadores relacionais e
verificam o resultado. A tabela 17 mostra os resultados dessas concatenações considerando P e Q
duas comparações relacionais cuje os resultados podem ser V de verdadeiro ou F de falso:

P Q P && Q P || Q !P
F F F F V
F V F V V
V F F V F
V V V V F
Tabela 17
Os operadores lógicos também possuem uma ordem de precedência sendo que em primeiro lugar sua
ordem de precedência é menor que as dos operadores aritméticos, abaixo na tabela 18 as ordens de
precedência de todos os operadores vistos até aqui, sendo os na parte de cima da tabela de maior
precedência e os de baixo de menor precedência:

Operador Descrição
++ – ~ Incremento, decremento e complemento de um
* / % * & multiplicação divisão, resto e operadores de ponteiro
+- soma e subtração
<< >>
20.1. deslocamento à esquerda,
deslocamento à direita
< > >= <= menor, maior que, menor ou igual e maior ou igual
== != igual, diferente
& AND (E) bit a bit
^ XOR (OU exclusivo)
| OR (OU)
&& AND (E)
|| OR (OU)
+= -= *= /= = Atribuições (menor precedência)
Tabela 18

21. Estrutura de decisão if-else


21.1. A estrutura if-else
Se chover
eu vou ao cinema
se não
eu vou a praia
É basicamente isso que a estrutura if-else fazem o analisam uma condição é tomam uma decisão
conforme a estrutura mostrada abaixo:
if (expressão_condicional) {
códigos dento do if
} eles {
códigos dento do else
}
continua o programa
O seu significado é bem simples se o que estiver na expressão condicional for verdadeiro faça o que
se encontra dentro do bloco de instruções do if, lembre que o abra e fecha ({) chaves (}) marcam o
inicio e fim de um bloco de instruções, se for falso faça o que se encontra dentro do bloco de
instruções do else . Caso o if ou else abranja uma única instrução você pode ignorar as chaves.
If (x < 0)
printf(“x é menor que zero”);
else
Printf(“não é menor que zero);
continua o programa
O programa media.c abaixo faz um pequeno teste para verificar se um aluno vai prestar exame final
ou não de acordo com sua media:
/**
Programa Media
*/

#include <stdio.h>

int main() {
float nota1, nota2, media;

printf("\nEntre com a primeira nota: ");


scanf("%f", &nota1);

printf("\nEntre com a segunda nota: ");


scanf("%f", &nota2);

media= (nota1 + nota2) / 2;

if (media >= 7)
printf("\nAluno aprovado\n\n");
else
printf("\nAluno em prova final\n\n");

return 0;
}
Executando o programa de acordo com suas entradas você terá algo de como a figura 13:

Como dito anteriormente


algumas linguagens de
programação apresentam um tipo de dado chamado de booleano somente para dizer se
um valor é verdadeiro ou falso, esse tipo de dado só aceita dois valores TRUE(ou true)
para verdadeiro e FALSE (ou false) para falso,mas, em C se atribui 0 (zero) para tudo que
for falso e qualquer coisa diferente de 0 (zero) como verdadeiro.
O programa bool.c mostra como isso funciona:
/**
Programa Booleanos
*/

#include <stdio.h>

int main() {
int x = 0;
int y = 2;
if (x) {
printf("\n%i é verdadeiro\n", x);
} else {
printf("\n%i é falso\n", x);
}

if (y) {
printf("%i é verdadeiro\n", y);
}

if (x - y) {
printf("%i é verdadeiro\n\n", x - y);
}

return 0;
}
Sua saída é:

No programa acima nós usamos duas vezes o if sem o seu parceiro o else é isso é valido você não
pode é usar um else sem um if, até porque não cabe ao else avaliar nenhuma condicional.
Em muitos programas teremos que avaliar mais de uma estrutura de decisão para obtermos a resposta
ao problema. Por exemplo no caso do programa media1.c acima poderíamos ter uma outra condição a
de que alunos com media menor 3 estariam automaticamente reprovados, nesse caso a nossa
estrutura de decisões anterior se tornaria ineficaz.

Uma das maneiras para solucionar o problema do nosso programa media1.c para a nova
condição imposta seria como no programa media2.c:
/**
Programa Media
*/

#include <stdio.h>

int main() {
float nota1, nota2, media;

printf("\nEntre com a primeira nota: ");


scanf("%f", &nota1);
printf("\nEntre com a segunda nota: ");
scanf("%f", &nota2);

media= (nota1 + nota2) / 2;

if (media >= 7)
printf("\nAluno aprovado\n");
else {
if (media < 3)
printf("\nAluno reprovado\n");
else
printf("\nAluno em prova final");
}

return 0;
}

A estrutura acima é conhecida como escada if-else-if devido a sua aparência. Se você seguir as boas
praticas de programação e recuar seus códigos para mantê-los legíveis e organizados essa estrutura
pode se tornar excessivamente profunda, por isso C possibilita uma outra forma para se escrever uma
escada if-else-if apresentada abaixo:

if (expressão_condicional) {
alguns códigos aqui
} else if (expressão_condicional) {
outros códigos aqui
} else if (expressão_condicional) {
outros códigos aqui
} else if (expressão_condicional) {
outros códigos aqui
…..
} else {
outros códigos aqui
}
continua o programa
Com isso podemos reescrever nosso programa media2.c como o programa media3.c:
/**
Programa Media
*/
#include <stdio.h>

int main() {
float nota1, nota2, media;

printf("\nEntre com a primeira nota: ");


scanf("%f", &nota1);

printf("\nEntre com a segunda nota: ");


scanf("%f", &nota2);

media= (nota1 + nota2) / 2;

if (media >= 7)
printf("\nAluno aprovado\n\n");
else if (media < 3)
printf("\nAluno reprovado\n\n");
else
printf("\nAluno em prova final\n\n");

return 0;
}

21.2. O operador ternário ?


O operador ternário ? é uma alternativa a uma estrutura if-else simples, sua estrutura é mostrada
abaixo:
y = x > 7 ? 2 : 10;

Na estrutura acima se x for maior que 7 então y é igual a 2, se não então y é igual a 10.
Uma forma muito usada dessa estrutura é impedir a divisão de um numero por zero e assim impedir
um erro em tempo de execução:
z = y ? x/y : 0;

Nesse caso se y é diferente de zero (verdadeiro) z recebe a divisão de x por y caso y seja igual a zero
z recebe o valor zero.
O programa divnum.c a seguir mostra como a estrutura mostrada acima funciona, impedindo uma
divisão por zero.
/**
Dividir dois números
*/

#include <stdio.h>

int main() {
float x, y, z;

printf("\nDigite um numero: ");


scanf("%f", &x);

printf("\nDigite outro numero: ");


scanf("%f", &y);

z = y ? x/y : 0;

if(z)
printf("\nO resultado da divisão é: %.2f\n", z);
else
printf("\nerro divisão por zero\n");

return 0;
}
21.3. A estrutura switch … case

Você também pode gostar