Laboratório de Programação
Prof. Oscar Luiz Monteiro de Farias
[email protected]
Ementa:
Equivalente ao sumário do livro:
The C Programming Language, Second edition.
Autores: Brian W. Kernighan, Dennis M. Ritchie
Bibliografia


The C Programming Language, Second edition.
Brian W. Kernighan, Dennis M. Ritchie.
Internet hyperlinks
Capítulo 1


Sucinta introdução à linguagem C
Analisar programas em C com os elementos
essenciais da linguagem:





Variáveis e constantes
Aritmética
Fluxo de controle
Funções
Rudimentos de E/S
Primeiro programa
Imprima as palavras:
“hello, world”
Primeiro programa – obstáculos





Aonde criar o texto do programa?
Como compilá-lo?
Como carregá-lo?
Como executá-lo?
Aonde e como ver o resultado de sua execução?
Código de helloworld.c
#include <stdio.h>
main()
{
printf("hello, world\n");
}
--------------------------prog01-chap01-pg09.c
Etapas:
Usar um editor (ex. gedit) para criar o texto do
programa, salvando-o no arquivo helloworld.c
 Compilar o programa (usamos o compilador
gcc)
$ gcc helloword.c -o nome_do_executavel
<enter>
 Executar o programa
$ nome_do_executavel <enter>
 Verificar a saída no terminal

Integrate Development Environment
Para facilitar o desenvolvimento de programas:
•
•
•
•
•
•
Netbeans http://netbeans.org/
Eclipse http://www.eclipse.org/
Anjuta
http://www.anjuta.org/
Geany
http://www.geany.org/
Code::Blocks http://www.codeblocks.org/
…
Programas em C




Um programa consiste de funções e variáveis
As funções contêm comandos que especificam
as operações a serem realizadas
As variáveis armazenam os valores usados nas
operações delas resultantes
main () é uma função especial. É o entry-point
de execução do programa. Os programas em C
iniciam aí a sua execução. Todo programa deve
ter uma função main ().
Detalhes do primeiro programa
#include <stdio.h>
informa ao compilador para incluir informações da
biblioteca padrão de E/S.
 Os parênteses após o nome da função (ex. main (...))
delimitam a lista de argumentos.
 Os comandos de uma função são delimitados por
chaves → { statement }
 Invoca-se uma função, indicando-se o nome da
função, seguido da lista de argumentos delimitada
por parênteses. Ex. printf(“helloworld\n”);

prog02-chap01-pg12 (1)


Comentário: quaisquer caracteres situados entre
/* e */ são ignorados pelo compilador
Podem aparecer em qualquer lugar do programa
aonde seja válido um espaço em branco, uma
marca de tabulação ou uma nova linha.
prog02-chap01-pg12 (2)




Em C deve-se declarar todas as variáveis antes
de usá-las;
Normalmente no início das funções e antes de
qualquer comando executável;
A declaração indica o nome e o tipo da variável;
Os valores assumidos por um determinado tipo
(ex. int) depende das características de hardware
da máquina;
prog02-chap01-pg12 (3)
Alguns tipos de dados básicos em C:
 int
-16bits -32768<=valor<=32767
 float
- 32 bits - com pelo menos 6 dígitos
significativos 10-38 <=valor<=10+38
 char
- um único byte - caracter
 short - inteiro curto
 long
- inteiro longo
 double – ponto flutuante com dupla precisão
 A faixa de valores assumidos depende do hw;
prog02-chap01-pg12 (4)
Outros tipos de dados em C:
 Vetores
 Estruturas
 Pointers
 Funções

Em C os comandos individuais são terminados
por ;
prog02-chap01-pg12 (5)
Semântica do loop while
while (fahr <= upper) {
statement
}
 A condição entre parênteses é testada. Se verdadeira, o
corpo do while é executado. A condição é novamente
testada, e se verdadeira, o corpo do while é executado
novamente, e assim por diante... Quando a condição se
tornar falsa o corpo do while não será executado e a
execução continuará no comando que se segue ao loop.

prog02-chap01-pg12 (6)




A organização lógica do programa é enfatizada
pela identação (não faz parte da linguagem);
Facilita o entendimento dos programas;
Recomendações: um comando por linha / deixar
espaços em torno dos operadores;
Na divisão entre inteiros o resultado é truncado.
Assim 2/3 = 0;
prog02-chap01-pg12 (7)
printf é uma função geral de conversão de
formatos. Seu primeiro argumento é uma cadeia
de caracteres a ser impressa, onde cada sinal %
indica aonde um dos outros argumentos (segundo,
terceiro, …) deverá ser substituído, e também
sob que formato deverá ser impresso.

%d – inteiro decimal
 %s – cadeia de caracteres
 %f – ponto flutuante

prog04-chap01-pg14 (1)


O comando for (outra forma de loop)
for (expr1; expr2; expr3)
statement
É equivalente a:
expr1;
while (expr2) {
statement
expr3;
}
prog04-chap01-pg14 (2)



expr1 é executada uma vez, antes do loop ser
iniciado;
expr2 é o teste ou condição para o controle do
loop;
expr3 corresponde ao passo de incremento e
eventalmente altera o valor de expr2, podendo
ocasionar o fim do loop;
prog04-chap01-pg14 (3)
Escolhendo entre os loops while e for:
for é mais apropriado para loops nos quais a
inicialização e incrementos são comandos
simples e logicamente relacionados, pois é mais
compacto que o while e mantémos comandos de
controle do loop juntos e no mesmo local.
prog05-chap01-pg17 (1)




O uso de números mágicos em um programa
não é boa prática de programação (ex. 0, 300,
20, etc.)
Dificultam o entendimento do código
Difíceis de serem alterados de forma
sistemática
Solução: substituí-los por nomes simbólicos ou
constantes simbólicas
prog05-chap01-pg17 (2)
# define nome texto substituto
…
# define LOWER 0
/* lower limit of table */
#define UPPER 300
/* upper limit */
#define STEP
20
/* step size */

LOWER, UPPER e STEP são constantes
simbólicas e não variáveis

Por convenção são escritos em
MAIÚSCULAS para serem facilmente
Entrada e Saída de caracteres (i)




No modelo de E/S suportado pela biblioteca
padrão o texto de E/S é manipulado como um
fluxo de caracteres, não importando a sua origem
ou destino.
Um fluxo de texto é uma seqüência de caracteres
particionada em linhas.
Cada linha consiste em zero ou mais caracteres
seguidos por um caracter de nova linha (\n)
A biblioteca é responsável por fazer com que
cada linha da E/S esteja de acordo com o modelo
Entrada e Saída de caracteres (2)





A biblioteca padrão dispõe de uma série de
funções para E/S
As mais simples são: getchar e putchar
getchar – lê o próximo caracter de entrada do
fluxo de texto e o retorna como seu valor
Após c = getchar (); a variável c contém o
caracter lido
O fluxo de textos de entrada normalmente tem
origem no teclado, mas pode vir de arquivos.
Entrada e Saída de caracteres (3)




putchar (c) imprime um caracter (coloca-o no
fluxo de saída) a cada vez que é invocada
O fluxo de saída é normalmente direcionado
para o terminal
O valor impresso é o conteúdo de c, sob a
forma de um inteiro
Invocações a putchar e a printf podem ser
intercaladas e a saída corresponderá à ordem de
invocação das funções
prog06-chap01-pg18.c (1)

Programa que copia a entrada (teclado) para a
saída (terminal), um caracter por vez
read a character
while (charater is not end-of-file indicator)
output the character just read
read a character
prog06-chap01-pg18.c (2)





O operador != significa não é igual a
O caracter que aparece na tela é armazenado
internamente apenas como um padrão de bits
O tipo char foi desenvolvido para armazenar o
padrão de bits correspondente a um caracter
Em C pode-se usar um tipo inteiro (int) para
esta finalidade
O programa usa int para distingüir quando não
há mais caracteres na entrada. Neste caso,
prog07-chap01-pg19.c





Segunda versão do programa que copia a
entrada (teclado) para a saída (terminal), um
caracter por vez
Entrada centralizada
Mais fácil de se ler (para os programadores em
C)
Os parênteses envolvendo a atribuição
(c = getchar()) são necessários, pois a
precedência de != é superior à de =.
Efeito não desejado de se atribuir a c o valor 0
prog08-chap01-pg19.c





Programa que conta quantos caracteres há no
texto de entrada
Operador ++, que significa incremento de um
++nc é equivalente a nc = nc + 1
++nc é diferente de nc++, embora ambos
incrementem c de um
O tipo long representa inteiros que ocupam
pelo menos 32 bits (em algumas máquinas o
valor de um int é no máximo de 32767)
prog09-chap01-pg20.c




Outra versão do programa que conta quantos
caracteres há no texto de entrada
Possibilita contar muito mais caracteres, por
armazenar o número de caracteres lidos em um
double (ponto flutuante de dupla precisão)
A contagem dos caracteres é realizada na
definição das condições de contorno do for e
não em seu corpo
As regras do C exigem que o comando for
tenha um corpo. No caso, o comando nulo: ;
prog10-chap01-pg20.c (1)




Programa para contar quantas linhas há no
texto de entrada.
Lembra que em C um fluxo de texto é uma
seqüência de caracteres particionada em linhas.
Cada linha consiste em zero ou mais caracteres
seguidos por um caracter de nova linha (\n)
Assim, contar linhas, é equivalente a contar o
numero de caracteres de new line (\n) no texto
de entrada.
prog10-chap01-pg20.c (2)
O comando if
if (condition)
statement

Significado do if
A condição entre parênteses é testada. Se
verdadeira, executa statement (ou grupo de
statements entre chaves)

== é a notação de C para “é igual a”

= é a notação de C para o comando de

prog10-chap01-pg20.c (3)




Um caracter escrito entre aspas simples – 'c' representa um valor inteiro igual ao valor
numérico do caracter no conjunto de caracteres
da máquina (constante de caracter).
'A' é uma constante de caracter. No conjunto de
caracteres ASCII seu valor é 65, a representação
interna do caracter A.
O valor de '\n' é 10 em ASCII.
'\n' representa um único caracter (lembrar da
seqüência de escape).
prog11-chap01-pg21.c (1)





Programa para contar linhas, palavras e
caracteres
Uma palavra é qualquer seqüência de
caracteres que não contém um caracter de
espaço, tabulação ou nova linha.
Versão simplificada do programa wc do unix.
nl = nw = nc = 0; /* atribui às três variáveis o
valor zero */
Uma atribuição tem um valor e é associativa,
da direita para a esquerda.
prog11-chap01-pg21.c (2)
O operador || significa o ou lógico

Analogamente && significa o e lógico

As expressões conectadaspor && ou || são
avaliadas da esquerda para a direita. A avaliação
terminará assim que a veracidade ou falsidade
for conhecida.

Forma geral do comando else
if (expression)
statement1

Vetores em C





Indica uma coleção de variáveis do mesmo
tipo, referenciada por um nome comum.
O acesso a um elemento específico dentro
desta coleção de variáveis se dá através de um
índice.
Ex.: int ndigito[10]; ndigito[i]
Em C, os subscritos (índices) dos vetores
sempre iniciam de 0 (zero).
Um subscrito pode ser qualquer expressão
inteira, variável inteira ou constante inteira.
prog12-chap01-pg24.c




Programa para contar o número de ocorrências
de cada dígito, de caracteres de espaço em
branco (space, tab, new line) e de todos os
outros caracteres.
Usa um vetor – int ndigito[10] - para
armazenar o número de ocorrências de cada
dígito.
O programa usa propriedades da representação
em caracteres dos dígitos.
Se o caracter armazenado em c é um dígito o
Decisões múltiplas em C (1)
if (condition1)
statement1
else if (condition2)
statement2
...
...
else
statementn
Decisões múltiplas em C (2)


As condições são avaliadas em ordem, a partir
do topo, até que uma das condições (conditioni
)seja satisfeita; nesse ponto statementi é
executado e a construção inteira é terminada.
(statementi pode representar vários statements
envolvidos por chaves). Se nenhuma das
condições for satisfeita, o statementn após o else
é executado, se houver. Se o else e statementn
forem omitidos nenhuma ação é tomada.
Alternativa para decisões múltiplas: o comando
prog13-chap01-pg26.c (1)





C não possui operador de exponenciação.
O programa define uma função power(m, n)
que eleva um inteiro positivo m à potència
inteira positiva n.
Biblioteca padrão: pow(x, y)
Protótipo → int power(int m, int n);
parâmetros
prog13-chap01-pg26.c (2)
argumentos
printf("%d %d %d\n", i, power(2,i), power(-3,i));
parâmetros
int power(int base, int n)
{ … }
Funções (1)





Forma de se encapsular alguma computação.
Equivalente a uma sub-rotina ou função em
Fortran e a procedure ou função em Pascal.
Idéia: não se preocupar como uma tarefa é
realizada e sim o que é realizado.
Permite efetuar a decomposição de uma grande
tarefa em várias tarefas menores.
Essencial no desenvolvimento de sistemas
mais complexos.
Funções (2)
Forma geral de definição de uma função:
tipo-retornado nome-da-função (lista de
declarações de parâmetros)
{
declarações
statements
}

As definições de funções podem aparecer em
qualquer ordem em um único arquivo fonte ou

Funções (3)
Protótipo de função: declaração que deve
combinar com a definição da função.

Envolve apenas
tipo-retornado nome-da-função (lista de
declarações de parâmetros);

Parâmetro (argumento formal): variável
nomeada na lista entre parênteses em uma
definição de função.

Argumento (argumento real): variável ou valor
usado na invocação (chamada) de uma função.

Funções (4)




Os nomes dos parâmetros e argumentos não
precisam ser idênticos.
Os nomes dos parâmetros são opcionais no
protótipo da função.
A função retorna o seu valor (que é de um tipo
especificado) por meio de um comando
return expressão;
Uma função não precisa retornar um valor.
Neste caso, o tipo-retornado é void.
Funções (5)



return; faz com que o controle, mas não um
valor, seja retornado ao trecho de código que
invocou a função. Equivalente a chegar a } delimitador de fim da função.
main é uma função e pode possuir um
comando return ao seu final (retorna um valor
ao ambiente em que o programa em C foi
executado.
Código de retorno 0 → término normal.
Funções (6)



Diferenças da definição e declaração de
funções entre o ANSI C e as versões anteriores
de C
(ver prog13a-chap01-pg28.c).
Os parâmetros são nomeados entre parênteses ( ) - e os seus tipos são declarados antes do
abre-chave - { .
No protótipo da função não era permitido a
declaração dos tipos de parâmetros (resultado: o
compilador não tinha como checar se a
Funções - call by value (1)
Chamadas por valor (call by value)
é fornecida à função uma cópia dos argumentos
em variáveis temporárias (os parâmetros), de tal
forma que os valores das variáveis no trecho do
programa que invocou a função não são
alterados.

Logo, em C, uma função chamada não pode
alterar o valor de uma variável na função que a
invoca. Só pode alterar os valores da sua própria
cópia.

Funções - call by value (2)



Call by value é uma vantagem → propicia o
encapsulamento do código da função, evitando
reflexos nas variáveis do código que invoca a
função.
Os parâmetros comportam-se como variáveis
locais à função que foi invocada.
São inicializados com os valores assumidos
pelos argumentos no trecho do código que
invocou a função (ver prog14-chap01-pg28.c).
Funções - call by reference



Em C, quando necessário, é possível a uma
função, alterar o valor de uma variável na
função que a invoca.
Na invocação da função deve-se fornecer,
como argumento, o endereço da variável a ser
alterada (pointer para a variável).
A função invocada deve declarar, como
parâmetro um pointer e deve referenciar
indiretamente o valor da variável.
Funções – vetores como argumentos



Quando o nome do vetor é usado como
argumento, o valor passado à função é o local ou
endereço de início do vetor.
Não há uma cópia para os elementos do vetor.
A função pode ter acesso e alterar qualquer
elemento do vetor com o uso de subscritos.
Constante do tipo cadeia de caracteres

Para armazenar a constante ''dia\n'' o
compilador C cria um vetor com um '\0', ao seu
final.
d
i
a
\n
\0
prog15-chap01-pg30.c (1)
Programa para ilustrar o uso de vetores de
caracteres e funções que o manipulam

Lê um conjunto de linhas e imprime a maior
delas.
while (there's another line)
if (it's longer than the previous longest)
(save it)
(save its length)
print longest line

prog15-chap01-pg30.c (2)




Desenvolver uma função getline para
obter a próxima linha de entrada
getline deve ser útil em outros contextos
getline retorna o tamanho da linha obtida,
ou zero, se for encontrado o fim de arquivo
Lembrar que zero não é um tamanho
válido para uma linha, pois, mesmo uma
linha-vazia possui o caracter de new line \n
prog15-chap01-pg30.c (3)




A maior linha encontrada até o momento deve
ser salva em algum lugar.
Desenvolver a função copy, para copiar a nova
linha (no caso de ser maior que a anterior) para
um local seguro.
Na função main deve-se ter um código para
controlar getline e copy.
Os protótipos das funções getline e copy são
declarados no início do arquivo, anterior à
função main.
prog15-chap01-pg30.c (4)
main e getline trocam informações por
intermédio de um par de argumentos/parâmetros
e pelo valor retornado por getline.

Getline declara os parâmetros em
int getline(char s[], int lim)
o primeiro parâmetro s é um vetor. Seu tamanho
não é necessário em getline, pois já foi definido
em main.

O valor retornado por getline é um int (o
tamanho da linha obtida),

prog15-chap01-pg32.c (5)




O tipo retornado por copy é void, indicando
explicitamente que nenhum valor é retornado.
getline insere o caracter ' \0' ao final do vetor,
para sinalizar o fim da cadeia de caracteres
(mesma convenção utilizada pelo compilador C
nas constantes do tipo cadeia de caracteres).
A especificação de formato %s em printf sinaliza
que o argumento correspondente deve ser uma
cadeia de caracteres.
Testando o tamanho retornado por getline e o
Variáveis externas e escopo (1)





prog16-chap01-pg32.c
As variáveis declaradas em uma função são
privativas ou locais à função.
Outras funções não têm acesso a elas (isto vale
também para as variáveis declaradas em main).
Cada variável local a uma função existe
somente enquanto a função está ativa e deixa de
existir quando a função termina.
Por isso são também conhecidas como
variáveis automáticas.
Variáveis externas e escopo (2)




As variáveis automáticas devem ser
explicitamente inicializadas a cada chamada.
É possível definir-se variáveis externas a todas
as funções – as variáveis globais.
Elas são visíveis a todas as funções e podem
ser por elas alteradas.
As variáveis externas são permanentes e retêm
os seus valores entre as diversas chamadas a
uma função.
Variáveis externas e escopo (3)



Tornam o programa mais acoplado, o que
dificulta alterações futuras e a própria
compreensão do programa (lembrar que o todo é
maior que as partes).
Uma variável externa deve ser definida
exatamente uma vez, fora de qualquer função.
Isto aloca área de armazenamento para ela.
Cada função que desejar ter acesso à variável
externa deve declará-la explicitamente com
extern ou implicitamente pelo contexto.
Variáveis externas e escopo (4)




Antes que uma função possa usar uma variável
externa, o nome da variável deve tornar-se
conhecido pela função.
Uma alternativa é inserir uma declaração
extern na função
extern char line[], longest[];
Em certos casos pode-se omitir a declaração
extern.
Ex.: se a definição da variável extern ocorrer
no arquivo-fonte antes do seu uso na função.
Variáveis externas e escopo (5)



Uma prática comum é inserir a definição de
todas as variáveis externas no início do arquivo
fonte e omitir as declarações extern dentro das
funções.
Se o programa está distribuído por vários
arquivos fontes e uma variável extern é definida
em arquivo1 e usada em arquivo2 e arquivo3,
então as declarações extern em arquivo2 e
arquivo3 são necessárias.
Uma alternativa é concentrar todas as
Variáveis externas e escopo (6)



Definição – refere-se ao local aonde se cria a
variável ou se destina área de armazenamento
para a mesma.
Declaração – refere-se ao local em que a
natureza da variável é estabelecida (seu tipo),
mas não há alocação de área para a mesma.
A keyword void deve ser usada em lista
explicitamente vazias. Tem a ver com a
checagem de argumentos nos compiladores e a
compatibilidade com versões mais antigas do C.
Download

Document