Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Fontes:
http://www.juliobattisti.com.br/tutoriais/default.asp?cat=0001&ast=0042
http://www.dee.feis.unesp.br/graduacao/disciplinas/langc/modulo_linguagemc/modulo5.htm
Menu
Operadores
Definies
Printf
Scanf
If
Funes
Funes II
Matrizes
Matrizes II
Ponteiros
Ponteiros II
Operadores
Objetivos
Abordar os conceitos sobre os Operadores demonstrando o seu uso com exemplos para
um melhor aprendizado.
Pr-requisitos
necessrio que o leitor tenha acompanhado o artigo anterior, pois os artigos obedecem
a uma seqncia.
Operadores
Os operadores indicam ao compilador a necessidade de se fazer manipulaes
matemticas ou lgicas.
Operadores aritmticos
Os operadores aritmticos so usados para calcular expresses matemticas. Sendo
classificados em duas categorias: os binrios ou unrios. Os operadores unrios atuam
na inverso de valores. Veja a tabela abaixo.
Operador unrio Ao
Sinal negativo
+
Sinal positivo
Tabela Operadores aritmticos
Sada do programa:
69+24=93
69-24=45
69x24=1656.000
69/24=2.875
69 mod 24=21.000
Operador Instruo
++
--
Ps-fixado Pr-fixado
var = var++; var = ++var;
var = var+1;
ou
ou
var++;
++var;
var = var--; var= --var;
var = var-1;
ou
ou
var--;
--var;
No caso das instrues mostradas acima no existe diferena, podemos aplicar tanto o
ps-fixado quanto o pr-fixado. Mas quando esses operadores so usados em outras
expresses necessita-se de cuidado, pois o uso incorreto pode ocasionar resultados
inesperados. A diferena entre eles que o pr-fixado incrementa a varivel para depois
executar a instruo e a ps-fixado executa a instruo para depois fazer o incremento
da varivel. Veja o exemplo abaixo:
Sada do programa:
var=6
var2=6
O programa acima incrementa a varivel var e coloca o valor na var2 que no nosso caso
ser 6. J o cdigo abaixo coloca o valor da varivel var na var2 que 5 para depois
incrementar a varivel var.
Sada do programa:
var=6
var2=5
Veja alguns exemplos utilizando duas variveis (var e expr) que devem ser declaradas
em seus programas.
Instruo normal
var = var + expr;
Var=var expr;
Var=var/expr;
Var=var*expr;
Instruo reduzida
var+=expr;
Var-=expr;
Var/=expr;
Var*=expr;
Operadores relacionais
Esses operadores so responsveis pelas comparaes de expresses nos programas. A
lista completa se encontra abaixo:
Operador
>
>=
<
<=
==
!=
Descrio
Maior
Maior igual
Menor
Menor igual
Igualdade
Diferente
Sada do programa:
Operadores lgicos
Os operados lgicos servem para interligar mais de uma operao relacional. E assim
como os relacionais retornam zero para falso e um para verdadeiro.
Operador
Descrio
&&
||
!
AND
OR
NOT (operador de negao)
Sada do programa:
Nesse programa o operador lgico (&&) faz a ligao das operaes relacionais (x>65)
e (x<=80), verificando se o nmero dado (x) est entre essa faixa. A instruo if ser
estudada no prximo artigo.
Operador
Descrio
&
|
^
<<
>>
AND
OR
XOR (OR exclusivo)
Deslocamento para esquerda
Deslocamento para direita
Embora a descrio na tabela seja parecida com as dos operadores Lgicos eles no
devem ser confundidos. Os operadores bit a bit so muito usados em rotinas de modens
e de impressoras.
Operador Cast
Tem como funo forar para que uma expresso seja de um determinado tipo. Sua
sintaxe :
O tipo de dado pode ser qualquer um dos definidos pelo padro ANSI. Um exemplo da
utilizao deste operador pode ser visto no programa mostrado neste artigo para
exemplificar o uso dos operadores aritmticos. Nesse programa o operador cast usado
para forar a diviso de dois nmeros inteiros ser do tipo float.
Operador Sizeof
Este operador usado em tempo de execuo e tem como objetivo retornar o tamanho
em bytes da varivel.
Sada do programa:
Precedncias
Precedncia a prioridade com que os operadores so executados pelo compilador.
Caso os operadores tenham o mesmo nvel de precedncia eles so analisados da
esquerda para direita.
A precedncia dos operadores pode ser mudada utilizando parentes. Para entender
melhor veja o exemplo abaixo, onde as duas expresses so iguais, porm o uso de um
parntese fez mudar a precedncia obtendo assim resultados diferentes.
4/2*5+1=11
4/2*(5+1)=12
Concluso
Conclui-se que os operadores so indispensveis em nossos programas e que a
linguagem C possui um nmero muito grande de operadores. Alguns inclusive sero
mostrados mais adiante, por exemplo, os operadores de ponteiro, devido serem muito
complexos.
Mdulo 2 Caractersticas e
Definies Gerais da Linguagem C
2.1 Palavras Reservadas na Linguagem C
Na Linguagem C existem palavras que so de uso reservado, ou seja, no podese us-las para escrever programas, por exemplo usando o nome de uma palavra
reservada para referenciar uma varivel. Uma palavra reservada essencialmente um
comando e, na maioria das vezes, as palavras reservadas de uma linguagem definem o
que pode ser feito e como pode ser feito.
O conjunto de palavras reservadas em Linguagem C especificado pelo padro
ANSI C so as relacionadas abaixo:
auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
Incorreto
1count
Ol! Aqui
high..balance
Um identificador no pode ser o mesmo que uma palavra reservada e no devem ter o
mesmo nome de uma funo tanto uma funo que voc tenha escrito como uma
funo de biblioteca da linguagem C.
Tipo
Intervalo
Char
-128 a 127
Int
16
-32768 a 32767
Float
32
3,4E-38 a 3,4E+38
double
64
1,7E-308 a 1,7E+308
void
sem valor
Intervalo
char
-128 a 127
unsigned char
0 a 255
signed char
-128 a 127
int
16
-32768 a 32767
unsigned int
16
0 a 65535
signed int
16
-32768 a 32767
short int
16
-32768 a 32767
16
0 a 65535
16
-32768 a 32767
long int
32
-2147483648 a 2147483647
32
-2147483648 a 2147483647
32
0 a 4294967295
float
32
3,4E-38 a 3,4E+38
double
64
1,7E-308 a 1,7E+308
long double
80
3,4E-4932 a 1,1E+4932
Exemplos:
int mul = 100;
char a, b, c;
float valor;
Exemplos:
#define PI 3,1415926536
#define SINAL "aberto"
#define MULT
A*B
Cdigo
\b
\n
\t
\
\\
\a
\xN
Significado
Retrocesso
Nova linha
Tabulao horizontal
Apstrofo
Barra invertida
Sinal sonoro
Constante hexadecimal
Cdigo
\f
\r
\
\0
\v
\N
Significado
Alimentao de formulrio
Retorno de carro
Aspas
Nulo
Tabulao vertical
Constante octal
Usa-se um cdigo de barra invertida exatamente da mesma maneira como usa qualquer
outro caractere. Por exemplo:
ch = \t;
printf (este um teste\n);
Esse fragmento de cdigo primeiro atribui uma tabulao a ch e, ento, imprime este
um teste na tela, seguido de uma nova linha.
2.6 Operadores
A linguagem C muito rica em operadores internos. Um operador um smbolo que
diz ao compilador para realizar manipulaes matemticas e lgicas especficas. A linguagem C
possui trs classes gerais de operadores: aritmticos, relacionais e lgicos e bit-a-bit.
Ao
Soma
subtrao
multiplicao
diviso
mdulo da diviso (resto da diviso inteira)
Ao
>
>=
<
<=
Maior
maior ou igual
Menor
menor ou igual
Igual
no igual (diferente)
==
!=
Ateno!
Ao
operao AND
operao OR
operador de negao NOT (operador unrio)
/*
(a == b) || (b == c)
*/
/*
&
|
Ao
bit and
bit or
^
<<
>>
~
->
var op = expr
Ao
Soma
Subtrao
Multiplicao
Diviso
mdulo (resto da diviso)
Rotao a direita
Rotao a esquerda
And
xor - exclusive or
Or
Exemplo de aplicao:
i+= 2; /* equivalente a: i = i + 2 */
j-= 3; /* equivalente a: j = j 3 */
k >>= 3; /* equivalente a: k = k >> 3;*/
z &= flag; /* equivalente a: z = z & flag;*/
i = ++i;
++i;
i = i 1;
i = --i;
--i;
z = a; a = a + 1;
z = a++;
z = a;
z = a--;
a = a 1;
a = a + 1; z = a;
z = ++a;
a = a - 1; z = a;
z = --a;
Significado
endereo de uma varivel
contedo do endereo especificado
Exemplos:
int var, *x;
x = &var;
var = *x;
Funo
menos unrio
mais unrio
negao lgica
bitwise not
endereo de
referncia a ptr
tamanho de var
incremento
decremento
multiplicao
diviso inteira
diviso real
resto da diviso
soma
subtrao
shift right
shift left
maior que
maior ou igual a
Exemplo C
a = -b;
a = +b ;
! flag
a = ~b ;
a = &b ;
a = *ptr ;
a = sizeof(b) ;
++a; ou a++;
--a; ou a--;
a = b * c;
a = b / c;
a = b / c;
a = b % c;
a = b + c;
a = b c;
a = b >> n;
a = b << n;
a>b
a >= b
<
<=
==
!=
&
|
^
&&
||
=
OP=
menor que
menor ou igual a
igual a
diferente de
bitwise AND
bitwise OR
bitwise XOR
logical AND
logical OR
assinalamento
assinalamento
a<b
a <= b
a == b
a != b
a = b & c;
a = b | c;
a = b ^ c;
flag1 && flag2
flag1 || flag2
a = b;
a OP= b;
2.8 Expresses
Operadores, constantes e variveis constituem expresses. Uma expresso em C
qualquer combinao vlida dessas partes. Uma vez que muitas expresses tendem a seguir as
regras gerais da lgebra, estas regras so freqentemente consideradas. Entretanto, existem
alguns aspectos das expresses que esto especificamente relacionadas com a linguagem C e
sero discutidas agora.
Pode-se colocar espaos numa expresso para torn-la mais legvel. O uso de parnteses
redundantes ou adicionais no causar erros ou diminuir a velocidade de execuo da
expresso. estimulado o uso de parnteses para tornar clara e exata a ordem de
avaliao, tanto para voc como para outros que precisarem entender o seu programa
mais tarde. Por exemplo, as duas expresses seguintes so as mesmas:
x=645/(num_entry)-y*(3217/balance);
x = 645 / (num_entry) y * (3127 / balance);
devem ser declaradas, ou seja, devem ser definidos nome, tipo e algumas vezes seu valor
inicial. As variveis so classificadas em variveis locais e globais.
2.5 Definio de Constantes: definimos uma constante quando atribumos um
certo valor constante um nome. Quando este nome referenciado dentro de um programa,
ser utilizado nas operaes o valor atribudo a este nome.
2.5.1 Constantes Hexadecimais e Octais: em programao algumas vezes
comum usar um sistema de numerao baseado em 8 ou 16 em vez de 10. Por causa da
freqncia com que estes dois sistemas numricos so usados, a linguagem C permite que se
especifique constantes inteiro em hexadecimal ou octal em vez de decimal, se preferir.
2.5.2 Constantes Strings: Outro tipo de constante suportada pela Linguagem C o
tipo string. Uma string um conjunto de caracteres entre aspas. Por exemplo, voc um
vencedor uma string.
2.5.3 Cdigos de Barra Invertida: colocar todas as constantes caractere entre
aspas funciona para muitos caracteres, mas alguns, como o retorno de carro, so impossveis
de serem inseridos em uma string a partir do teclado. Por isso, a linguagem C fornece
constantes caractere mais barra invertida especiais. Estes cdigos foram mostrados em uma
tabela.
2.6 Operadores: Um operador um smbolo que diz ao compilador para realizar
manipulaes matemticas e lgicas especficas. A linguagem C possui trs classes gerais de
operadores: aritmticos, relacionais e lgicos e bit-a-bit.
2.6.1 Operador de atribuio: o operador = atribui um valor ou resultado de
uma expresso contida a sua direita para a varivel especificada a sua esquerda.
2.6.2 Operadores Aritmticos: so aqueles que operam sobre nmeros e
expresses, resultando valores numricos.
2.6.3 Operadores Relacionais: operam sobre expresses, resultando valores
lgicos de TRUE (verdadeiro) ou FALSE (falso).
2.6.4 Operadores Lgicos: operam sobre expresses, resultando valores lgicos de
TRUE (verdadeiro) ou FALSE (falso). Possuem a caracterstica de short circuit, ou seja, sua
execuo curta e s executada at o ponto necessrio.
2.6.5 Manipulao de bits: a manipulao feita em todos os bits da varivel a
qual no pode ser do tipo float ou double. Os operadores que manipulam bits foram
relacionados em uma tabela.
2.6.6 Operadores de assinalamento: assinalam o uso de uma operao,
combinando operadores de tal forma a diminuir o cdigo e facilitar sua posterior
compreenso.
2.6.7 Operadores de Pr e Ps-Incremento: operadores de pr e ps-incremento
so aqueles usados quando necessrio incrementar ou decrementar um determinado valor.
A string de controle contm tanto caracteres para serem impressos na tela como
cdigos de formato que especificam como apresentar o restante dos argumentos.
Quando os programas trabalharem com variveis, ser possvel usar printf() para exibir
Significado
Exibe um caractere
%d
%i
%e
%E
%f
%g
%G
%o
%s
%u
%x
%X
%%
%p
peso, altura);
printf("%d mais %d igual a %d\n", 1, 2, 1 + 2);
}
{
unsigned int valor = 42000;
printf("Exibindo 42000 como unsigned %u\n", valor);
printf("Exibindo 42000 como int %d\n", valor);
}
{
printf("Exibir 0.1234 resulta em %g\n", 0.1234);
printf("Exibir 0.00001234 resulta em %g\n", 0.00001234);
}
#include <stdio.h>
void main(void)
{
int neg_int = -5;
int pos_int = 5;
float neg_flt = -100.23;
float pos_flt = 100.23;
printf("Os valores inteiros so %+d and %+d\n",neg_int,
pos_int);
printf("Os valores em ponto flutuante so %+f %+f\n", neg_flt,
pos_flt);
}
No item anterior, foi visto como formatar uma sada instruindo printf() a exibir um
determinado nmero de dgitos. No caso anterior, printf() colocava espaos antes do valor a
ser exibido, mas possvel configur-lo de tal maneira que ele exiba zeros antes do valor ou
caracter que necessrio exibir. Esses zeros so chamados de zeros de preenchimento. Para
instruir printf() a preencher um valor com zeros, coloca-se um 0 (zero) imediatamente aps o
% no especificador de formato, antes do nmero desejado de dgitos. O exemplo abaixo ilustra
o uso desta propriedade.
#include <stdio.h>
void main(void)
{
int valor = 5;
printf ("%01d\n", valor);
printf ("%02d\n", valor);
printf ("%03d\n", valor);
printf ("%04d\n", valor);
}
Por padro, quando for exibido o texto usando os caracteres de formatao, printf()
exibir o texto justificado direita. Dependendo do programa, algumas vezes necessrio que
printf() justifique o texto esquerda. Para justificar o texto esquerda, coloque um sinal de
subtrao (-) imediatamente aps o % no especificador de formato. O exemplo a seguir ilustra
o uso desta tcnica de formatao.
#include <stdio.h>
void main(void)
{
int int_valor = 5;
float flt_valor = 3.33;
printf("Justificado direita %5d valor\n", int_valor);
printf("Justificado esquerda %-5d valor\n",
int_valor);
printf("Justificado direita %7.2f valor\n", flt_valor);
printf("Justificado esquerda %-7.2f valor\n",
flt_valor);
}
caracteres de escape (referenciados no Mdulo 2 item 2.4.3) para facilitar para voc a incluso
de caracteres especiais dentro de uma string. Um exemplo o uso do caracter de nova linha
(\n) para avanar a sada para o incio da prxima linha.
printf("Linha 1\nLinha2\nLinha 3\n");
Significado
L um nico caractere
L um decimal inteiro
L um decimal inteiro (no pode ser octal ou hexadecimal)
L um decimal sem sinal
L um nmero em ponto flutuante com sinal opcional
L um nmero em ponto flutuante com ponto opcional
L um nmero em ponto flutuante com expoente opcional (double)
L um nmero em base octal
L uma string
L um nmero em base hexadecimal
L um ponteiro
caractere especificado no encontrado, a funo scanf( ) terminar. Pode-se usar esta tcnica
para separa os especificadores de formato, tornando o cdigo mais legvel.
#include <stdio.h>
void main(void)
{
int a,b;
scanf("%d,%d", &a, &b);
}
Nesse caso, nome j um endereo e no precisa ser precedido pelo operador &.
Os itens de dados de entrada devem ser separados por espaos, tabulaes ou novas
linhas. Pontuaes como vrgula, ponto-e-vrgula e semelhantes no contam como
operadores. Isso significa que scanf(%d%d, &r, &c); aceitar uma entrada dos nmeros 10
20, mas falhar com 10,20. Como na funo printf( ), os cdigos de formato da funo scanf( )
devem ser correspondidos na ordem com as variveis que esto recebendo a entrada na lista
de argumento.
Um * colocado depois do % e antes do cdigo de formato ler um dado de um tipo
especificado, mas suprimir a sua atribuio. Assim, scanf(%d%*c%d, &x, &y); dando-se a
entrada 10/20, colocar o valor 10 em x descartando o sinal de diviso, e dar a y o valor 20.
Ainda que espaos, tabulaes e novas linhas sejam usados como separadores de
campos, quando da leitura de um nico caractere, esses ltimos so lidos como qualquer
outro caractere. Por exemplo, com uma entrada de x y; scanf(%c%c%c, &a, &b, &c);
retornar com o caractere x em a, um espao em b e o caractere y em c.
um sinal de porcentagem. Por exemplo, este scanset diz funo scanf( ) para ler somente os
dgitos de 0 a 9: %[1234567890].
4.1.9 Exibindo uma String de Caracteres: foi visto que para exibir uma string de
caracteres com a funo printf(), deve-se usar o especificador de formato %s.
4.1.10 Exibindo um Endereo de Ponteiro: foi visto que para exibir um endereo
de ponteiro com a funo printf(), deve-se usar o especificador de formato %p.
4.1.11 Precedendo um Valor com um Sinal de Adio ou de Subtrao: foi visto
que para instruir printf() a exibir um sinal de um valor, deve-se incluir um sinal de adio
imediatamente aps o % no especificador de formato.
4.1.12 Formatando um Valor Inteiro: neste item foi visto como configurar printf()
de tal forma que sua valores a serem exibidos tenha seu formato de sada na tela especificado
pelo programador.
4.1.13 Sada de Inteiros Preenchida com Zeros: foi visto neste item que
possvel configurar printf() de tal maneira que ele exiba zeros antes do valor ou caracter que
necessrio exibir.
4.1.14 Exibindo um Prefixo Antes dos Valores Octais ou Decimais: foi visto como
preceder os valores em octal com um zero, e os hexadecimais com 0x .
4.1.15 Formatando um Valor em Ponto Flutuante: foi visto que quando formatase um valor em ponto flutuante especifica dois valores. O primeiro valor diz a printf() o
nmero mnimo de caracteres a serem exibidos. O segundo valor diz a printf() o nmero de
dgitos a serem exibidos direita do ponto decimal. Com isto foi apresentada uma tcnica de
formatao de printf().
4.1.16 Formatando a Sada Exponencial: foi visto como configurar printf() de tal
forma a exibir a sada em ponto flutuante em um formato exponencial.
4.1.17 Justificando Esquerda a Sada de Printf(): foi apresentado que para
justificar o texto esquerda, coloca-se um sinal de subtrao (-) imediatamente aps o % no
especificador de formato.
4.1.18 Combinando os Especificadores de Formato de Printf(): apresentado
neste item a possibilidade de aproveitar dois ou mais especificadores de formato de printf()
com intuito de deixar o cdigo mais enxuto.
4.1.19 Trabalhando com os Caracteres Escape de Printf():. Foi visto que a
Linguagem C define vrios caracteres de escape (referenciados no Mdulo 2 item 2.4.3) para
facilitar para voc a incluso de caracteres especiais dentro de uma string.
4.1.20 Determinando o Nmero de Caracteres que Printf() Exibiu: Foi visto que
quando usa-se o especificador de formato %n, printf() atribuir uma varivel (passada por
ponteiro) um contador do nmero de caracteres que printf() exibiu.
4.1.21 Usando o Valor de Retorno de Printf(): foi mostrado que possvel utilizar
o valor que printf() retorna quando ele finaliza suas tarefas. Este valor retornado pode ser
utilizado de vrias formas, variando o uso de acordo com as caractersticas do programa.
4.2 Funo SCANF(): foi feita neste item uma introduo funo scanf(). Foi
mostado que a funo scanf( ) uma das funes de entrada de dados da Linguagem C, que
pode ser usada para ler virtualmente qualquer tipo de dado inserido por meio do teclado.
Alm da introduo funo foi apresentada sua estrutura e caractersticas.
4.2.1 Usando Caracteres em Scanf() que Sero Descartados: foi mostrado que
possvel inserir dentro da funo scanf() caracteres que no sero lidos. Estes caracteres
servem apenas na tornar o cdigo mais legvel e de fcil entendimento.
4.2.2 Lendo Valores em Variveis: foi visto que possvel utilizar a funo scanf()
para obter valores para determinadas variveis.
4.2.3 Lendo String de Caracteres: foi mostrado como usar a funo scanf() para
ler string de caracteres que sero armazenadas em vetores.
4.2.4 Formatando a Entrada de Scanf(): neste item mostrado como formatar
scanf()de tal forma a atender as especificaes de cada programa para entrada de dados.
4.2.5 Determinando o Nmero Mximo de Caracteres a ser Lido: foi mostrado
que possvel especificar o nmero de caracteres lidos por scanf(), de tal forma a desprezar
caracteres que forem digitados a mais, por exemplo.
4.2.6 Lendo Somente Caracteres Pr-Determinados: foi visto que pode-se
previamente especificar os caracteres que sero lidos por scanf(), sendo que o caracter que
no estiver dentro destes especificados ser ignorado.
A clusula else opcional. Se condio for verdadeira (qualquer coisa diferente de 0),
o bloco que forma o destino de if ser executado; caso contrrio o bloco que forma o destino
de else ser executado (desde que exista else).
Lembre-se que somente o cdigo associado a if ou o cdigo associado a else ser
executado, nunca os dois. O destino dos dois, if e else, pode ser um comando simples ou um
bloco de comandos.
O comando if ser demonstrado atravs de um programa simples que converte bases
numricas. Este programa ser capaz de apresentar as seguintes converses:
Decimal para Hexadecimal;
Hexadecimal para Decimal.
int valor;
printf (Converter: \n);
printf (1: decimal para hexadecimal\n);
printf (2: hexadecimal para decimal\n);
printf (\nInforme sua opo: );
scanf (%d, &opcao);
if (opcao == 1)
{
printf (\nInforme o valor em decimal: );
scanf (%d, &valor);
printf (%d em hexadecimal e: %x, valor, valor);
}
if (opcao == 2)
{
printf (\nInforme o valor em hexadecimal: );
scanf (%x, &valor);
printf (%x em decimal e: %d, valor, valor);
}
}
{
int i;
printf (Informe um nmero: );
scanf (%d, &i);
if (i < 0) printf (O nmero negativo);
else printf (O nmero positivo ou nulo);
}
As expresses condicionais sero avaliadas de cima para baixo. Assim que uma
condio verdadeira encontrada, o bloco associado a ela ser executado, e o resto do
encadeamento ignorado. Se nenhuma das condies for verdadeira, ento o else final ser
executado.
Se o else final no estiver presente e todas as outras condies forem falsas, ento
nenhuma ao ser realizada.
Pode-se usar o encadeamento if-else-if para implementar o programa de converso de
base numrica desenvolvido anteriormente. Na verso original, cada declarao if era avaliada
sucessivamente, mesmo se uma das declaraes anteriores tivesse xito. Ainda que no haja
grande significado neste caso, a avaliao redundante de todos os ifs no muito eficiente ou
elegante. O seguinte programa resolve este problema. Nessa verso de encadeamento if-elseif, to logo uma declarao if satisfeita, o resto das declaraes ignorado.
/* Programa de converso de base numrica if-else-if
decimal ---> hexadecimal
hexadecimal ---> decimal
*/
#include <stdio.h>
void main()
{
int opcao;
int valor;
printf (Converter: \n);
printf (1: decimal para hexadecimal\n);
printf (2: hexadecimal para decimal\n);
printf (\nInforme sua opo: );
scanf (%d, &opcao);
if (opcao == 1)
{
printf (\nInforme o valor em decimal: );
scanf (%d, &valor);
printf (%d em hexadecimal e: %x, valor, valor);
}
else if (opcao == 2)
{
printf (\nInforme o valor em hexadecimal: );
scanf (%x, &valor);
printf (%x em decimal e: %d, valor, valor);
}
else
{
printf (\nA opo escolhida invlida.)
}
}
porque redundante.
O else agora est associado ao if(x), j que ele no parte do bloco de cdigo do if(y).
comando;
Como pode-se verificar, o primeiro lao for exibe os nmeros de 1 at 5. O segundo lao
exibe os valores de 1 at 10. O terceiro lao no exibe nenhum valor. Se for examinado com
ateno, ser visto que o programa inicialmente atribui varivel de controle do lao o valor
100. Quando o comando for testa o valor, o lao for atende imediatamente condio final,
de modo que o lao no executado.
No entanto, se for omitido uma das sees do lao for, precisa-se incluir o
ponto-e-vrgula correspondente. Por exemplo, o lao for a seguir omite as sees de
inicializao e de incremento:
for(; conta < 1000; )
printf("%d", conta++);
/* no faz nada */
/* no faz nada */
Usar as tcnicas de retardo, tais como o lao nulo, poder causar problemas.
Primeiro, se o programa estiver rodando em um computador 286, 386 ou 486, a durao
do retardo diferir simplesmente devido diferena de velocidade entre os diferentes
microprocessadores. Segundo, se o programa estiver rodando em um ambiente
multitarefa, tal como o Windows, OS/2 ou Unix, os laos "no fazem nada" consomem
tempo que o processador poderia estar gastando fazendo trabalho importante em outro
programa.
/*causa do erro*/
}
printf("Resultado %d\n", result);
}
muitos
casos,
os
programas
precisam
repetir
um
ou
mais
comando;
O programa a seguir, usa o lao while para repetir um lao at que seja pressionado a
tecla S ou N em resposta a uma pergunta:
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
void main(void)
{
char letra;
/* L a letra */
/* Soa o alto-falante */
letra = getch();
/* L a letra */
letra = toupper(letra);
/* Converte a letra para maiscula */
}
Descrio
Inicializa a varivel de controle do lao
Testa a varivel de controle ou a condio do lao
Executa os comando desejados no lao
Modifica o valor da varivel de controle ou efetua uma operao que
afetar a condio que voc est testando
{
printf("%d ", contador);
contador++;
/* Executa os comandos */
}
}
Talvez o uso mais comum do lao do-while seja em uma rotina de seleo em menu. J
que sempre ser preciso de uma rotina de seleo em menu para ser executada no mnimo
uma vez, o lao do-while uma opo bvia. O seguinte fragmento mostra como adicionar um
lao do-while no menu do programa de converso numrica.
/* Assegura que o usurio especificou uma opo vlida */
do
{
printf (Converte:\n);
printf ( 1: decimal para hexadecimal\n);
printf ( 2: hexadecimal para decimal\n);
printf (informe sua opo: );
scanf (%d, &opcao);
}while(opcao < 1 || opcao > 2);
Depois que a opo tiver sido apresentada, o programa se repetir at que uma
opo vlida seja selecionada.
/* mpar */
continue;
printf("%d ", contador);
}
printf("\nValores mpares\n");
contador = 0;
while (contador <= 100)
{
contador++;
if (! (contador % 2)) /* Par */
continue;
printf("%d ", contador);
}
}
/* Par */
contador = 0;
while (contador <= 100)
{
contador++;
if (contador % 2) /* mpar */
printf("%d ", contador);
}
}
Quando usa-se o comando goto, o rtulo precisa residir na funo atual. Em outras
palavras, no pode-se usar goto para desviar-se de main para um rtulo que aparece em
outra funo e vice - versa.
mesmo o seu autor. Por esse motivo, a linguagem C tem internamente uma declarao de
deciso de mltipla escolha chamada de switch. Na declarao switch, a varivel
sucessivamente testada contra uma lista de inteiros ou constantes caractere. Quando uma
associao encontrada, o conjunto de comandos associado com a constante executado.
As constantes no precisam sequer estar em qualquer ordem especial. A forma geral
da declarao switch :
switch (varivel)
{
case constante1:
commandos;
break;
case constante2:
commandos;
break;
case constante3:
commandos;
break;
M
default
commandos;
}
switch(y){
case 0:
printf (erro de diviso por zero);
break;
case 1:
process (x, y);
}
break;
case 2:
.
.
.
case R:
printf (Vendas: R$%d\n, 10000);
break;
case J:
printf (Vendas: R$%d\n, 12000);
break;
case M:
printf (Vendas: R$%d\n, 14000);
}
break;
case O:
printf (Vendedores so: Ronaldo, Lisa e Hilton\n);
printf (Informe a primeira letra do vendedor: );
vendedor = toupper(getche());
printf (\n);
switch (vendedor)
{
case R:
printf (Vendas: R$%d\n, 10000);
break;
case L:
printf (Vendas: R$%d\n, 9500);
break;
case H:
printf (Vendas: R$%d\n, 13000);
}
break;
case N:
printf (Vendedores so: Toms, Joo e Raquel\n);
printf (Informe a primeira letra do vendedor: );
vendedor = toupper(getche());
printf (\n);
switch (vendedor)
{
case R:
printf (Vendas: R$%d\n, 5000);
break;
case J:
printf (Vendas: R$%d\n, 9000);
break;
case T:
printf (Vendas: R$%d\n, 14000);
}
break;
}
}
Para ver como o programa funciona, seleciona-se a regio Oeste, digitando O. Isso
indica que case O selecionado pela declarao switch externa. Para ver o total de vendas de
Hilton, digite H. Isso faz com que o valor 13000 seja apresentado.
Note que a declarao break em um switch aninhado no tem efeito no switch
externo.
Quando um lao est dentro de outro, diz-se que o lao mais interno aninhado.
Laos aninhados propiciam o meio de resolver alguns problemas interessantes de
programao. Por exemplo, este pequeno programa exibe as quatro primeiras potncias dos
nmeros de 1 a 9.
/* Exibe uma tabela das 4 primeiras potencies de 1 a 9 */
#include <stdio.h>
void main()
{
int i, j, k, temp;
printf( i i^2 i^3 i^4\n);
for (i = 1; i < 10; i++)
{ /* lao externo */
for (j = 1; j < 5; j++)
{ /* primeiro aninhamento */
temp = 1;
for (k = 0; k < j; k++) /* segundo aninhamento */
temp = temp * i;
printf (%9d, temp);
}
printf (\n);
}
}
simplesmente converter um nmero toda vez que for executado, o programa repete at
que o usurio queira parar.
/* Programa de converso de base numrica verso final
decimal ---> hexadecimal
hexadecimal ---> decimal*/
#include <stdio.h>
void main()
{
int opcao;
int valor;
/*repete at que o usurio diga para terminar*/
do
{
/*assegura que o usurio especificou uma opo vlida*/
do
{
printf (Converter: \n);
printf (1: decimal para hexadecimal\n);
printf (2: hexadecimal para decimal\n);
printf (3: fim\n);
printf (\nInforme sua opo: );
scanf (%d, &opcao);
}
while(opcao < 1 || opcao > 3);
switch(opcao)
{
case 1:
printf (\nInforme o valor em decimal: )
scanf (%d, &valor);
printf (%d em hexadecimal e: %x, valor, valor);
break;
case 2:
printf (\nInforme o valor em hexadecimal: )
scanf (%x, &valor);
printf (%x em decimal e: %d, valor, valor);
break;
case 3:
default:
printf (\nOpo invlida. Tente outra vez.)
}
printf (\n);
}
while(opcao != 5);
}
Funes
Objetivos
No primeiro captulo foi dito que um programa em C pode ser composto de uma ou
mais funes, sendo que a nica obrigatria main(). Agora, estudaremos como utilizar
outras funes em nossos programas.
Pr-requisitos
Para um melhor aprendizado necessrio que o leitor tenha acompanhado o artigo
anterior, pois os artigos obedecem a uma seqncia.
Funes
As funes so blocos de instrues que facilitam o entendimento do cdigo. Sua
sintaxe :
corpo da funo
}
O tipo da funo pode ser qualquer um dos mostrados at agora e representa o tipo do
dado que retornado pela funo. Caso a funo no retorne nenhum valor dizemos que
ela do tipo void. E caso no seja especificado nenhum tipo, por padro a funo
retorna um inteiro. Mas importante lembrar que sempre se deve declarar o tipo da
funo garantindo assim maior portabilidade. Entre parnteses esto os parmetros da
funo que constitudo pelos nomes das variveis que se deseja passar para funo
separados por virgulas e acompanhados de seus respectivos tipos, como mostra a
sintaxe acima. No caso da funo no conter parmetros a lista de parmetros ser
vazia, mas mesmo assim ser necessrio utilizar os parnteses. No corpo da funo vem
o cdigo em C, este cdigo privativo da funo, ou seja, nenhuma outra funo poder
acessa-la com nenhum comando, exceto por meio de uma chamada a funo. Isso quer
dizer que o cdigo da funo no pode afetar outras partes do programa, a menos que
sejam utilizadas variveis Globais. Isto porque as variveis contidas em uma funo so
locais, s existem naquela funo. Essas variveis so criadas quando entram na funo
e destrudas ao sair.
Para entender melhor o uso de funes veja o exemplo abaixo. Este programa calcula o
fatorial de um nmero qualquer.
O comando return usado no final da funo o responsvel por retornar um valor para
a instruo que o chamou, neste caso para a varivel Fatorial. Que por sua vez
impressa na tela.
Caso a funo no utilize nenhum parmetro deve-se utilizar o void. Dessa forma
teramos:
tipo Nome_Da_Funo(void);
importante lembrar que antes que a funo seja usada pela primeira vez necessrio
que ela seja declarada. Isso ocorre devido o compilador C (em sua grande maioria) por
padro assume que uma funo devolve um valor inteiro. Portanto se alguma funo
devolver um tipo diferente de inteiro o compilador gera um cdigo errado para chamla. Por esse motivo que importante declarar o tipo que a funo retorna no inicio do
programa e isso pode ser feito utilizando os prottipos. Alm dos prottipos existe um
outro mtodo que era muito usado quando a linguagem C foi inventa, no entanto hoje
ela considerada obsoleta. Porm existem alguns programas que ainda usa este mtodo
obsoleto, dessa forma sua declarao seria:
tipo Nome_Da_Funo();
A diferena deste mtodo para o do prottipo que neste mesmo que a funo tenha
argumentos no preciso de declara-los. Na verdade o prottipo uma extenso deste
mtodo.
Neste ultimo programa, temos uma funo que tem como parmetros os coeficientes de
uma equao do tipo:
. Esta funo verifica se a for igual a zero
identificando assim a equao como sendo do 2 Grau e posteriormente se delta maior
ou igual a zero, caso seja a equao ser resolvido pela formula de baskara. Caso delta
seja menor que zero ser impresso a seguinte mensagem: No foi possvel calcular x1 e
x2, pois so nmeros imaginrios. Se a diferente de zero a equao ser do 1 grau,
ento verifica se b igual a zero, caso seja no ter soluo, pois no pode haver diviso
por zero. A funo CalculaEquacao do tipo void pois no retorna nenhum valor para
funo main(). Exatamente por esse motivo a funo principal apenas chama a
CalculaEquacao. A biblioteca math.h foi inserida pela diretiva include, ou seja, a
linha #include <math.h> foi inserida no programa para que as funes pow() e sqrt()
pudessem ser utilizadas. A funo pow() calcula a base elevada uma potencia. J a
funo sqrt() calcula a raiz quadrada de um nmero. Estas e outras funes pertencentes
biblioteca math.h sero descritas e estudas com mais detalhes no decorrer deste
tutorial.
No exemplo anterior no foi utilizada a funo return, pois nenhum valor necessitou ser
devolvido. Neste caso o programa retorna funo que a chamou quando o ultimo
comando (}) da funo CalculaEquacao for encontrado. claro que a chave no estar
no cdigo-objeto do programa, mas pode-se imaginar como se estivesse. O cdigoobjeto nada mais do que o cdigo contendo as instrues traduzidas para a linguagem
de maquina.
Concluso
Neste artigo vimos como utilizar funes em nossos programas, facilitando assim o
entendimento do cdigo. Atravs desse estudo conclui-se que as funes devem
obedecer sintaxe apresentada neste trabalho onde deve ser definidos o tipo de dado
que a funo retorna, os parmetros e os seus respectivos tipos. Os tipos dos argumentos
e dos parmetros das funes devem ser compatveis. Do mesmo modo a quantidade de
argumentos deve ser igual as dos parmetros. Para que a funo retorne um valor
utiliza-se return. Foi visto tambm que as funes devem ser declaradas antes de serem
chamadas e isto pode ser feito utilizando os prottipos de funes. Lembre-se que o
compilador C por padro define que toda funo retorna um valor inteiro, portanto
necessrio muito cuidado caso a funo retorne um tipo diferente de inteiro. Todas essas
informaes foram apresentadas atravs de exemplos simples e prticos. Com isso
verifica-se que o uso de funes em nossos programas so indispensveis.
A palavra chave void diz a Linguagem C que a funo no retorna um valor. Em muitos
casos, as funes usaro return para retornar o valor de um clculo para a funo chamadora.
Se a funo no usa return para retornar um resultado, deve-se preceder o nome da funo
com void. O void que aparece nos parmetros diz que a funo no usa parmetros. Um
parmetro a informao que o programa passa para a funo. Por exemplo, quando os
programas chamam printf, as informaes que se especifica dentro dos parnteses so
parmetros. Quando uma funo no usa parmetros, deve-se colocar void dentro dos
parnteses. Para usar uma funo, especifica-se o nome da funo seguido de parnteses. Os
programadores referenciam o uso de uma funo como uma chamada da funo. O programa
a seguir, usa a funo oi_pessoal:
#include <stdio.h>
void ola_pessoal(void)
{
printf("Ol
}
pessoal!\n");
void main(void)
{
ola_pessoal();
}
}
void main(void)
{
tres_olas();
}
Quando se declara variveis dentro de uma funo, os nomes usados para essas
variveis so exclusivos para a funo.
Portanto, se o programa usa dez funes diferentes e cada funo usa uma varivel
chamada contador, a Linguagem C considera a varivel de cada funo como distinta. Se uma
funo requer muitas variveis, elas devero ser declaradas no incio da funo, exatamente
como se faria dentro de main.
ola_pessoal();
}
void main(void)
{
tres_olas();
}
Uma funo mais til permite especificar, como um parmetro, o nmero de vezes que
quer que o programa exiba a mensagem. Para usar um parmetro, a funo precisa
especificar o nome e o tipo do parmetro, como mostrado aqui:
void ola_conta(int msg_conta)
O programa a seguir ilustra como pode usar uma funo com um parmetro:
#include <stdio.h>
void oi_pessoal(void)
{
printf("Ola, pessoal!\n");
}
void ola_conta(int msg_conta)
{
int contador;
for (contador = 1; contador <= msg_conta; contador++)
oi_pessoal();
}
void main(void)
{
printf("Exibe a msg duas vezes\n");
ola_conta(2);
printf("Exibe a msg cinco vezes\n");
ola_conta(5);
}
/*Comandos da funo*/
}
Quando o programa chamar a funo, ser necessrio especificar valores para cada
parmetro, como mostrado aqui:
uma_funcao(33, 40000.00, 534);
O tipo de valor que a funo retorna (int, float, char, etc.) determina o tipo da funo.
Por exemplo, se uma funo retorna um valor do tipo int, necessrio preceder o nome da
funo com o nome do tipo, como mostrado aqui:
int uma_funo(int valor)
{
/*Comandos da funo*/
}
Como visto, a funo usa o comando return para retornar o resultado do clculo ao
chamador. O cdigo dentro da funo de chamada pode atribuir o resultado da funo
chamada (tambm conhecido como valor de retorno) a uma varivel, ou o cdigo pode usar o
valor de retorno dentro de uma terceira funo, tal como printf, como mostrado aqui:
result = i_cubo(5);
printf(O cubo de 5 %d\n, I_cubo(5));
O programa a seguir usa a funo i_cubo para determinar vrios valores diferentes ao
cubo:
#include <stdio.h>
int i_cubo(int valor)
{
return(valor * valor * valor);
}
void main(void)
{
printf("O cubo de 3 %d\n", i_cubo(3));
printf("O cubo de 5 %d\n", i_cubo(5));
printf("O cubo de 7 %d\n", i_cubo(7));
}
Os valores que so passados para uma funo precisam corresponder aos tipos de
parmetros contidos dentro da declarao dessa funo. Por exemplo, se quiser
determinar o cubo de um valor em ponto flutuante, crie uma segunda funo chamada
f_cubo, como mostrado a seguir (observe que o valor de retorno tambm do tipo
float):
float f_cubo(float valor)
{
return (valor *valor *valor);
}
{
if (primeiro == segundo)
return (0);
else if (primeiro > segundo)
return (1);
else if (primeiro < segundo)
return (2);
}
Significado
Os valores so iguais
O primeiro valor maior que o segundo
O segundo valor maior que o primeiro
Como regra, deve-se tentar limitar as funes a usar somente um comando return.
medida que as funes se tornarem maiores e mais complexas, ter muitos comandos return
normalmente tornar as funes mais difceis de compreender. Na maioria dos casos, pode-se
reescrever a funo para que ela use somente um comando return, como mostrado aqui:
int compara_valores(int primeiro, int segundo)
{
int result;
if (primeiro == segundo)
return = 0;
else if (primeiro > segundo)
return = 1;
else if (primeiro < segundo)
return = 2;
return(result);
}
funes se tornarem mais complexas, a vantagem ficar mais clara. Pode-se observar
que, algumas vezes, usar mais de um comando return produz um cdigo mais legvel do
que a alternativa de um nico return. Deve-se escrever o cdigo mais legvel e
facilmente modificvel quanto possvel; se usar mltiplos return atingir os objetivos
pr-estabelecidos, ento utilize quantos comandos return forem necessrios.
float f_cubo(float);
Embora o uso da pilha seja poderoso porque permite que o programa chame e passe as
informaes para as funes, tambm consome tempo de processamento. Os
programadores chamam a quantidade de tempo que o computador requer para colocar e
retirar informaes da pilha de sobrecarga da funo. Para compreender melhor o
impacto da sobrecarga da funo no desempenho do seu programa, considere o
programa a seguir. Primeiro o programa usa um lao para somar os valores de 1 a
100.000. Em seguida, repete um lao novamente, mas usa uma funo para somar os
valores, como mostrado aqui:
#include <stdio.h>
#include <time.h>
float soma(long int a, float b)
{
float result;
result = a + b;
return(result);
}
void main(void)
{
long int i;
float result = 0;
time_t hora_inicio, hora_parada;
printf("Trabalhando...\n");
time(&hora_inicio);
for (i = 1; i <= 100000L; i++)
result += i;
time(&hora_parada);
printf("Usando lao %d segundos\n", hora_parada - hora_inicio);
printf("Trabalhando...\n");
time(&hora_inicio);
for (i = 1; i <= 100000L; i++)
result = soma(i, result);
time(&hora_parada);
printf("Usando funo %d segundos \n", hora_parada hora_inicio);
}
/* Variaveis globais */
void valores_globais(void)
{
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
void main(void)
{
valores_globais();
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
/* Variveis globais */
void conflito_a(void)
{
int a=100;
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
void main(void)
{
conflito_a();
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
usa chamada por valor, a funo no altera os valores das variveis dentro do chamador, como
mostrado a seguir:
#include <stdio.h>
void exibe_e_altera(int primeiro, int segundo, int terceiro)
{
printf("Valores originais da funo %d %d %d\n",
primeiro, segundo, terceiro);
primeiro += 100;
segundo += 100;
terceiro += 100;
printf("Valores finais da funo %d %d %d\n", primeiro,
segundo, terceiro);
}
void main(void)
{
int a = 1, b = 2, c = 3;
exibe_e_altera(a, b, c);
printf("Valores finais em main %d %d %d\n", a,b,c);
}
Como pode ser visto, as alteraes que a funo faz nas variveis somente so visveis
dentro da prpria funo. Quando a funo termina, as variveis dentro de main esto
inalteradas.
uma cpia do valor de um parmetro. Por outro lado, com a chamada por referncia, as
funes recebem o endereo de memria da varivel. Portanto, as funes podem alterar o
valor armazenado na posio de memria especfica (em outras palavras, o valor da varivel);
alteraes essas que permanecem aps a funo terminar. Para usar a chamada por
referncia, seu programa precisar usar Ponteiros. O Mdulo sobre Ponteiros, mais adiante,
discute os Ponteiros em detalhes. No entanto, por ora, pense em um Ponteiro simplesmente
como um endereo de memria. Para atribuir o endereo de uma varivel a um ponteiro,
necessrio usar o operador de endereo "&". Para acessar posteriormente o valor na posio
de memria para o qual o Ponteiro aponta, use o operador de direo "*".
precede os nomes das variveis ponteiro. As declaraes a seguir criam variveis ponteiro do
tipo int, float e char:
int *i_ponteiro;
float *f_ponteiro;
char *c_ponteiro
Em seguida, para usar o valor apontado para a varivel ponteiro, os programas precisam
usar o operador de redireo da Linguagem C - o asterisco (*). Por exemplo, o
comando a seguir atribui o valor 5 varivel a (cujo endereo est contido na varivel
i_ponteiro):
i_ponteiro = 5;
Quando quiser usar o valor apontado por uma varivel ponteiro, usa-se o operador de
redireo (*). Quando quiser atribuir o endereo de uma varivel uma varivel
ponteiro, usa-se o operador de endereo (&). O programa a seguir ilustra o uso de uma
varivel ponteiro. Ele atribui varivel ponteiro i_ponteiro o endereo da varivel O
programa ento usa a varivel ponteiro para alterar, exibir e atribuir o valor da varivel:
#include <stdio.h>
void main(void)
{
int a = 1, b = 2;
int *i_ponteiro;
i_ponteiro = &a;
*i_ponteiro = 5;
para 5 */
/* Atribui um endereo*/
/* Altera o valor apontado por i_ponteiro
/* Atribui o valor */
Como pode ser visto, a funo muda_primeiro usa a chamada por referncia para
alterar o valor do parmetro primeiro, e chamada por valor para o parmetro segundo.
Quando os programas usam ambas as tcnicas, precisa ter-se em mente quando usar
ponteiros e quando referenciar diretamente a varivel. Como regra, os parmetros cujos
valores sero alterados iro requerer chamada por referncia. Para compreender melhor o
impacto da chamada por referncia versus chamada por valor, modifique a funo
muda_primeiro, como mostrado aqui:
void muda_primeiro(int *primeiro, int segundo)
{
*primeiro = segundo; /*Atribui o valor de segundo a primeiro*/
segundo = 100;
}
Quando este programa for compilado e executado, ver que o valor de primeiro foi
alterado, mas o valor de segundo no foi. Como o parmetro segundo foi passado usando
chamada por valor, a alterao do parmetro visvel fora da funo.
apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
3.1 Funes: dada uma explicao detalhada sobre as caractersticas gerais de
funes na Linguagem C.
3.2 Variveis dentro das Funes: foi visto que possvel e muito valioso o uso
de variveis dentro das funes. Foi mostrado que as variveis declaradas dentro de uma
funo, so vlidas apenas para aquela funo.
3.3 Main como uma Funo: foi visto que quando um programa criado, usa-se
o nome da funo main para determinar o primeiro comando que o programa executar. A
funo main a principal funo em um programa.
3.4 Introduo aos Parmetros: foi visto que um parmetro uma valor
passado a uma funo. Com eles a funo se torna mais til ao programa e facilita vria
operaes.
3.5 Parmetros Mltiplos: foi mostrado que em geral, pode-se passar um
nmero irrestrito de parmetros para uma funo. Quando a funo usa mais de um
parmetro, precisa especificar o tipo e o nome de cada parmetro e separar os parmetros por
vrgulas.
3.6 Retornando um Valor de uma Funo: foi visto que funes usam o
comando return para retornar o resultado do clculo ao chamador. O tipo de valor que a
funo retorna (int, float, char, etc.) determina o tipo da funo. Os valores que so passados
para uma funo precisam corresponder aos tipos de parmetros contidos dentro da
declarao dessa funo.
3.7 Comando Return: foi visto que quando a Linguagem C encontra um
comando return em uma funo, ela finaliza imediatamente a execuo da funo e retorna o
valor especificado para o chamador. O programa no executa quaisquer outros comandos
dentro da funo aps o comando return. Em vez disso, ele continua a execuo da funo
chamadora.
3.8 Prottipos de Funo: foi explicado que o prottipo de uma funo
especifica os tipos de parmetro e de retorno da funo.
3.9 Biblioteca de Execuo: foi explicado que a maioria dos compiladores
fornece centenas de funes de biblioteca de execuo com propsito que vo de abertura e
trabalho com arquivos para acessar informaes do disco ou de diretrio para determinar o
tamanho de uma string de caracteres, poupando horas de trabalho de programao.
3.10 Funes que no Retornam Int: foi visto que quando uma determinada
funo no retorna um valor do tipo int (em vez disso ela pode retornar float, double, char,
etc.) precisa-se informar ao compilador o tipo de retorno da funo.
3.11 Variveis Locais: foi explicado que variveis so locais, quando seus nomes
e valores somente tm significado dentro da funo que contm a declarao da varivel.
3.12 Sobrecarga da Funo: foi visto que a quantidade de tempo que o
computador requer para colocar e retirar informaes da pilha de sobrecarga da funo. Este
tempo tem um papel fundamental no desempenho dos programas em execuo.
3.13 Declarando Variveis Globais: foi visto que variveis globais so aquelas
cujos nomes, valores e existncia so conhecidos em todo o seu programa. Foi visto tambm
como declar-las.
3.14 Solucionando os Conflitos de Nomes de Variveis Locais e Globais: foi
visto que quando nomes de variveis globais e locais estiverem em conflito, a Linguagem C
usar sempre a varivel local.
3.15 Chamada por Valor: foi explicado que na chamada por valor, quaisquer
modificaes que a funo fizer nos parmetros existem apenas dentro da prpria funo.
Quando a funo termina, o valor das variveis que a funo chamadora passou para a funo
no modificada dentro da funo chamadora.
3.16 Chamada por Referncia: foi visto que quando as funes alteram o valor
de um parmetro, os programas precisam passar o parmetro para a funo usando chamada
por referncia.
3.17 Obtendo um Endereo: foi visto que para determinar o endereo de uma
varivel, usa-se o operador de endereo "&".
3.18 Usando um Endereo de Memria: foi visto que quando se passa um
endereo para uma funo, precisa-se informar ao compilador que a funo estar usando um
ponteiro (o endereo de memria) de uma varivel, e no o valor de uma varivel. Para fazer
isto, necessrio declarar uma varivel ponteiro.
3.19 Alterando o Valor de um Parmetro: foi mostrado um programa que usa
ponteiros e endereos (chamada por referncia) para exibir e, depois, alterar os parmetros
que o programa passa para uma funo.
3.20 Alterando Somente Parmetros Especficos: foi mostrado como fazer para
que as funes alterem o valor de um parmetro e ao mesmo tempo deixe o valor de um
segundo parmetro inalterado.
3.21 Funes Recursivas: foi explicado que uma funo recursiva se um
comando no corpo da funo chama ela mesma. Alm disso, foi dada uma viso geral sobre
funes recursivas.
Matrizes
Objetivos
Neste artigo estudaremos os conceitos relacionados as matrizes unidimensionais
(vetores) e multidimensionais.
Pr-requisitos
Para um melhor aprendizado necessrio que o leitor tenha acompanhado o artigo
anterior, pois os artigos obedecem a uma seqncia.
Matrizes unidimensionais
So matrizes de uma nica dimenso. Essas matrizes tambm so chamadas de vetores.
A declarao de vetores em C deve obedecer a seguinte sintaxe:
Tipo nome_vetor[tamanho];
int vetor_exemplo[9];
Tipo nome_vetor[tamanho]={lista_de_valores};
Sendo que todos os elementos da lista de valores devem ser separados por virgula e
serem todas do mesmo tipo de dados especificado. A seguir temos a declarao do
vetor_exemplo com os valores atribudos.
int vetor_exemplo[9]={0,1,2,3,4,5,6,7,8,9};
Exemplo de um programa completo utilizando vetores e outros conceitos estudados at
o momento.
#include<stdio.h>
void main()
{
int vet1[5]={1,2,3,4,5}; /*declarao e inicializao do vetor vet1*/
int vet2[5]={6,1,2,2,5}; /*declarao e inicializao do vetor vet2*/
int vetSoma[5]; /*declarao do vetor vetSoma que vai guardar o resutado da soma dos
dois vetores(vet1 e vet2).*/
int x;
} /*fim do programa*/
O programa acima soma dois vetores (vet1 e vet2) e exibe sua resposta na tela. O
objetivo deste exemplo mostrar como declarar e inicializar um vetor. Veja a seguir a
sada do programa:
vetSoma[1]:3
vetSoma[2]:5
vetSoma[3]:6
vetSoma[4]:10
Os vetores so muito usados para criar uma string de caracteres, pois em C no existe
nenhum tipo de dados para definir uma string.A declarao de um vetor contendo uma
string sempre deve ser maior que o nmero de caracteres, pois o compilador acrescenta
automaticamente no final da string um espao nulo que indica o seu trmino. Este
segundo exemplo muito simples, mostra apenas como podem ser feitas a declarao e
inicializao de um vetor de string.
#include<stdio.h>
void main()
{
char c1 = 'a';
char vet1[30]="Aprendendo a mexer com string\n";
} /*fim do programa*/
Sada do programa:
Para trabalhar com uma string deve ser declarado um vetor do tipo char
O vetor do tipo char contem a string: Aprendendo a mexer com string
Matrizes Bidimensionais
So matrizes linha-coluna, onde o primeiro ndice indica a linha e o segundo a coluna.
Esse tipo de matriz considerado o caso mais simples de matrizes multidimensionais.
Veja o programa abaixo:
#include<stdio.h>
void main()
{
int mat[2][2];
float det;
int x,y;
for(y=0;y<2;y++)
{
printf("mat[%d][%d]=",x+1,y+1);
scanf("%d",&mat[x][y]);
} /*fim do for*/
} /*fim do for*/
} /*fim do programa*/
Esse exemplo calcula a determinante de uma matriz de ordem 2 e atravs dele podemos
ver como deve ser feita a declarao de uma matriz bidimensional.
int mat[2][2];
tipo nome_matriz[numero_linhas][numero_colunas];
Matrizes multidimensionais
A linguagem c permite tambm utilizar matriz de trs ou mais dimenses, porm no
freqentemente usada, pois requer uma quantidade grande de memria e os acessos aos
seus elementos so mais lentos. Por esses motivos este tipo de matrizes no sero
abordados com detalhes
Matrizes no-dimensionadas
As matrizes no-dimensionais so aquelas cujo tamanho no especificado. Nesse caso
o compilador cria uma matriz grande para conter todos os seus elementos. As
declaraes de matrizes unidimensionais com essa caracterstica podem ser vista no
programa abaixo:
#include<stdio.h>
void main()
{
char vet1[37]="Estou aprendendo a programar em C!!!";
char vet2[]="Estou aprendendo a programar em C!!!"; /*vetor no-dimensionado*/
Observe na sada abaixo que os vetores (vet1 e vet2) declarados de forma diferentes
obtiveram os mesmo efeitos. A diferena que no vetor vet2 no foi especificado a
quantidades de caracteres (vetor no-dimensionado).
#include<stdio.h>
void main()
{
int mat1[2][2]={4,5,-2,1};
int mat2[][2]={4,5,-2,1}; /*Matriz no-dimensionada*/
int x,y;
printf("\n");
printf("Imprimindo a matriz mat2 cujo o tamanho nao foi especificado:\n");
for(x=0;x<2;x++)
{
for(y=0;y<2;y++)
{
printf("mat2[%d][%d]=%d",x,y,mat2[x][y]);
printf("\n");
} /*fim do for*/
} *fim do for*/ /
} /*fim do programa*/
Do mesmo modo verifica-se atravs da sada abaixo que tanto a matriz mat1 como a
matriz mat2, obtiveram os mesmos resultados embora tenham sido declaradas de
maneira diferente.
Concluso
De forma similar, a seguinte declarao cria uma matriz do tipo float, que
contm 50 salrios:
float salarios [50];
matriz[i] = 80;
Por exemplo, suponha que seja necessrio alterar o cdigo anterior de tal forma
que ele suporte 10 valores. Precisar alterar no somente a declarao da matriz, mas
tambm o lao for. Quanto mais alteraes forem feitas em um programa, maiores as
chances de errar. O programa a seguir declara uma matriz com base na constante
TAM_MATRIZ. Como se v, o programa no somente usa a constante para declarar a
matriz, mas tambm usa a constante como a condio final para o lao for:
#include <stdio.h>
#define TAM_MATRIZ 5
void main(void)
{
int valores[TAM_MATRIZ] = {80, 70, 90, 85, 80};
int i;
for (i = 0; i < TAM_MATRIZ; i++)
printf("valores[%d] %d\n", i, valores[i]);
}
Se mais tarde for necessrio alterar o tamanho da matriz, poder alterar o valor
atribudo constante TAM_MATRIZ para que o programa automaticamente atualize os
laos que controlam a matriz como o tamanho da matriz.
Quando uma funo recebe uma matriz como parmetro, o programa no precisa
especificar o tamanho da matriz na declarao do parmetro. No caso da funo
exibe_valores, os colchetes aps o nome da varivel valor informam o compilador de
que o parmetro uma matriz. Sabendo que o parmetro uma matriz, o compilador
no se preocupa com o tamanho da matriz que o programa passa para a funo.
exibe_matriz(notas, 5);
exibe_matriz(conta, 10);
exibe_matriz(pequeno, 2);
}
outros tipos, tais como int, float ou long, no tem um caracter finalizador equivalente.
Portanto, voc normalmente precisa passar para as funes que trabalham com matrizes
o nmero de elementos que a matriz contm.
/* 66,000 bytes */
int values[33000L];
float numbers[17000];
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Ponteiros
Objetivos
Neste artigo estudaremos o que so ponteiros, qual a sua importncia e como utiliza-los.
Pr-requisitos
necessrio que o leitor tenha acompanhado o artigo anterior, pois os artigos obedecem
a uma seqncia.
Ponteiros
O ponteiro nada mais do que uma varivel que guarda o endereo de uma outra
varivel. A declarao de ponteiros feita da seguinte forma:
A instruo acima indica que pa um ponteiro do tipo int. Agora veremos como atribuir
valor ao ponteiro declarado. Para isto necessrio saber que existem dois operadores
unitrios que so utilizados com os ponteiros. O primeiro o operador (*) atravs dele
possvel retornar o valor da varivel que est localizada no ponteiro. E o segundo o
operador (&) que retorna o endereo de memria que est localizado o valor da variavel
contida no ponteiro. Portanto para atribuirmos um valor para o ponteiro necessrio
referencia o valor da varivel que se encontra no ponteiro utilizando o operador (*),
como ser demonstrado a seguir.
Desta forma estamos atribuindo o valor 24 para a varivel que est contida no ponteiro.
Para entender melhor quando e como utilizar os operadores (*) e (&), veja o programa
mostrado abaixo.
Sada do programa:
Atravs do programa abaixo possvel verificar que se pode fazer comparaes entre
ponteiros.
Sada do programa:
Isso far com que o ponteiro aponte para a posio do prximo elemento. Como
estamos a considerar que o tipo inteiro do tamanho de 2 bytes, o ponteiro est sendo
incrementado de 2, ou seja, o nmero de incrementos depende do tamanho do tipo de
dados. O mesmo acontece com o decremento, porm aponta para a posio anterior.
Isso feito pela instruo:
Isso far com que o ponteiro aponte para a posio do prximo elemento. Como
estamos a considerar que o tipo inteiro do tamanho de 2 bytes, o ponteiro est sendo
incrementado de 2, ou seja, o nmero de incrementos depende do tamanho do tipo de
dados. O mesmo acontece com o decremento, porm aponta para a posio anterior.
Isso feito pela instruo:
Dessa forma o ponteiro ir apontar para o quinto elemento do tipo px1 adiante do
elemento que o ponteiro estava a apontar. importante saber que no se pode nem
multiplicar e nem dividir ponteiros.
Do mesmo modo que se tem um ponteiro (que o endereo de uma varivel) pode-se
ter ponteiro para ponteiro, ou seja, um ponteiro aponta para um outro ponteiro que
finalmente aponta para a varivel com o valor a ser utilizado. O que chamamos de
indireo mltipla e pode ser vista no prximo programa.
Dados de sada:
Como visto no cdigo fonte anterior, uma varivel que ponteiro para ponteiro deve ser
declarada da seguinte forma:
Da mesma forma para acessar o valor final utilizado o operador * duas vezes,
conforme visto no neste exemplo.
Concluso
Neste artigo vimos que um ponteiro uma varivel que guarda um endereo de uma
outra varivel. Estudamos como declara-las e que antes de utiliza-las necessrio
atribuir um endereo vlido. Foi visto tambm que podemos utilizar ponteiros para
ponteiros. Tudo isto foi mostrado com exemplos simples e didticos. Conclui-se, no
entanto que o uso de ponteiro importante em muitos casos e que se deve tomar muito
cuidado ao usa-los. Nos prximos artigos sero estudadas algumas situaes em que
ponteiros so muito teis. Como por exemplo: o uso de ponteiros para mudar os
argumentos das funes e as alocaes dinmicas.
Mdulo 7 Ponteiros
7.1 Ponteiros como Endereos
Como j foi visto, uma varivel o nome de uma posio na memria que pode
armazenar um valor de um determinado tipo. Os programas referenciam cada posio
na memria usando um endereo exclusivo. Um ponteiro uma varivel ou um valor
que contem um endereo. A Linguagem C utiliza muito os ponteiros. Quando se passa
matrizes ou string para as funes, o compilador C passa um ponteiro. Da mesma
forma, quando uma funo precisa alterar o valor de um parmetro, o programa deve
passar para a funo um ponteiro para o endereo de memria da varivel.
#include <stdio.h>
void main(void)
{
int *iptr;
int conta = 1;
iptr = &conta;
printf("Valor de iptr %x Valor de conta %d Endereo de conta
%x\n", iptr, conta, &conta);
}
Da mesma forma, o comando a seguir atribui o valor apontado pela varivel iptr
para a varivel conta:
conta = *iptr;
iptr = &contador;
/* Atribui o endereo */
/* apontado por a */
*a = *b;
/* Atribui o valor de b a a */
*b = temp;
/* Atribui o valor de a a b */
}
void main(void)
{
int um = 1, dois = 2;
troca_valores(&um, &dois);
printf("um contm %d dois contm %d\n", um, dois);
}
Como pode ser visto, a funo exibe_string declara a varivel string como um
ponteiro. Usando o ponteiro, a funo simplesmente percorre os caracteres da string at
encontrar o caractere NULL. Para exibir o caractere, a funo exibe_string primeiro
desreferencia o endereo do ponteiro (obtendo o caractere). Em seguida, a funo
incrementa o ponteiro para apontar para o prximo caractere na string.
return(ender_inicial);
}
void main(void)
{
char *titulo = "UNESP Ilha Solteira";
char *string;
string = string_maiusc(titulo);
printf("%s\n", string);
printf("%s\n", string_maiusc("Matrizes e Ponteiros"));
}
Segunda,
Tera,
Quarta,
Quinta,
Se for examinado o tipo da matriz da direita para a esquerda, ser visto que a
matriz contm sete elementos. O asterisco antes do nome da varivel especifica um
ponteiro. Se combinar o nome do tipo char que precede o nome da varivel, a
declarao se tornar uma matriz de ponteiros para strings de caractere.
int i;
for (i = 0; i < 7; i++)
printf("dias[%d] contm %s\n", i, dias[i]);
}
{
return(compare(a, b));
}
int max(int a, int b)
{
printf("Em max\n");
return((a > b) ? a: b);
}
int min(int a, int b)
{
printf("Em min\n");
return((a < b) ? a: b);
}
void main(void)
{
int result;
result = pega_result(1, 2, &max);
printf("O maximo entre 1 e 2 %d\n", result);
result = pega_result(1, 2, &min);
printf("O minimo de 1 e 2 %d\n", result);
}
#include <stdio.h>
int qual_e_o_valor(int ***ptr)
{
return(***ptr);
}
void main(void)
{
int *nivel_1, **nivel_2, ***nivel_3, valor = 1001;
nivel_1 = &valor;
nivel_2 = &nivel_1;
nivel_3 = &nivel_2;
printf("O valor %d\n", qual_e_o_valor(nivel_3));
}