Sie sind auf Seite 1von 197

1/197

PROGRAMAO I
UFPEL/IFM/DINFO prof. Marilton Sanchotene de Aguiar marilton@ufpel.edu.br http://marilton.wordpress.com

2/197

Introduo a Linguagem C

Criada por Denis Ritchie em 1972 (Bell Labs, USA) Sua primeira utilizao importante foi a escrita do S.O. Unix Em meados de 1970 ela foi liberada para uso em Universidades Em 1980 j existiam vrias verses de compiladores de diversas empresas (no restritos ao ambiente Unix) C uma linguagem de propsito geral, adequada programao estruturada Juntamente com Fortran, a principal linguagem para uso cientfico (compiladores, analisadores lxicos, bancos de dados, editores de texto...)

3/197

Introduo a Linguagem C

Pertence a um conjunto de linguagens cujas principais caractersticas so: Portabilidade Modularidade Compilao separada Recursos de baixo nvel (tratamento de caracteres) Gerao de cdigo eficiente Confiabilidade Regularidade Simplicidade Facilidade de uso

4/197

A Sintaxe do C

So as regras para cada construo vlida em uma linguagem especfica. Esto relacionadas com:

Tipos: definem as propriedades dos dados Declaraes: expressam as partes de um programa Funes: especificam as aes que um programa executa, quando roda

Determinao e alterao de valores Chamada de funes de I/O

5/197

Funes em C

So os blocos bsicos dos programas em C H funes bsicas, definidas na biblioteca C: printf(), scanf(), getchar(), putchar() H funes definidas pelo programador Todo programa C inicia sua execuo chamando a funo main(), sendo obrigatrio a sua declarao no programa principal.

6/197

Exemplo
#include <stdio.h> /* comentario */ //comentario main() { printf("oi"); }

7/197

Identificadores

So os nomes usados para fazer referncia a Variveis Funes Mdulos Rtulos Demais objetos definidos pelo usurio

8/197

Identificadores (cont.)

Regras de Formao:

O primeiro caracter deve ser uma letra ou sublinhado Os 32 primeiros caracteres so significativos Case sensitive - difere maisculas de minscula
a A Nota nota _nota

Exemplos de identificadores vlidos em C:


9/197

Tipos

O Tipo serve (grosso modo) para determinar Como os valores sero armazenados Quais operaes podero ser realizadas sobre estes valores Tipos para Dados e para Funes Tipos escalares Tipos no-escalares tipo de estrutura, tipo de unio, tipo de matriz

10/197

Tipos Escalares

Tipos Aritmticos Tipos Inteiros char, signed char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long Tipos Flutuantes float, double, long double Tipos Ponteiros para funes para objetos de dados para tipos incompletos

11/197

Tipos Inteiros

12/197

Tipo Flutuante

13/197

Exemplo
#include <stdio.h> //tamanho dos tipos main() { char c; unsigned char uc; int i; unsigned int ui; float f; double d; printf("char %d\n", sizeof(c)); printf("unsigned char %d\n", sizeof(uc)); printf("int %d\n", sizeof(i)); printf("unsigned int %d\n", sizeof(ui)); prinft("float %d\n", sizeof(f)); printf("double %d", sizeof(d)); }

14/197

Operadores

Atribuio (=) Aritmticos (+, -, *, /, %) Outros operadores i += 2; (equivalente: i = i+2;) x *= y+1; (equivalente: x = x*(y+1);) d -= 3; (equivalente: d = d-3;)

15/197

Operadores (cont.)

Relacionais (>, >=, <, <=, ==, !=) Lgicos (&&, ||, !)

Em C, falso 0 (zero); qualquer outro valor considerado verdadeiro (inclusive negativo) Operadores relacionais e lgicos tm menor precedncia do que operadores aritmticos

16/197

{De,In}cremento

++x incrementa x antes de usar o seu valor x++ incrementa x depois de ser usado --y decrementa y antes de usar o seu valor y-decrementa y depois de ser usado

17/197

() [] -> ! ~ ++ -- - (tipo) * & sizeof * / % + << >> < <= > >= == != &^! && || ?: = += -= *= /= etc ,

Sobre a Precedncia
Maior

Menor

18/197

Funes Bsicas

printf()

Sintaxe:
printf("expressao de controle", argumentos);

uma funo de E/S que permite escrever no dispositivo padro (tela) A expresso de controle pode conter: caracteres que sero exibidos na tela cdigos de formatao Cada argumento deve ser separado por vrgulas

19/197

Funes Bsicas

printf() Cdigos de formatao: \n (nova linha); \t (tabulao); \b (retrocesso); \" (aspas); \\ (barra); \f (salta formulrio) e \0 (nulo). %c (caractere simples); %d (decimal); %e (notao cientfica); %f (ponto flutuante); %o (octal); %s (string); %u (decimal sem sinal); e %x (hexadecimal)

20/197

Exemplo - printf()
#include <stdio.h> main() { printf("este eh o numero dois: %d", 2); }

#include <stdio.h> main() { int a, b; float c; a = 2; b = 10; c = 2/( (float) 1/a + (float) 1/b); printf("a= %d b= %d\n", a, b ); printf("a mdia harmnica de a e b : %f", c); }

21/197

Funes Bsicas

scanf()

Sintaxe:
scanf("expressao de controle", argumentos);

uma funo de E/S que permite ler dados formatados da entrada padro (teclado) A lista de argumentos deve consistir dos endereos das variveis na memria do computador. Como obter o endereo de uma varivel?? Colocando um & junto ao nome da varivel. Ex.: &a (fornece o endereo da varivel a)

22/197

Exemplo - scanf()
#include <stdio.h> main() { int a, b; float c; printf("entre com o valor de a\n"); scanf("%d", &a); printf("entre com o valor de b\n"); scanf("%d", &b); c = 2/((float) 1/a + (float) 1/b); printf("a=%d b=%d\n", a, b ); printf("a mdia harmnica de a e b : %f", c); }

23/197

Estruturas de Controle

if(...)

Sintaxe: if (condio) comando1; else comando2; Se condio for verdadeira (qualquer valor diferente de zero), o programa executar o comando1; caso contrrio (condio for falsa), o programa executar o comando2. No lugar de um comando, pode haver uma seqncia de comandos (ou seja, um bloco). Em C, um bloco incia com um abre chaves e termina com um fecha chaves

24/197

Estruturas de Controle

if(...)

Sintaxe: if (condio) { comando1; comando2; comando3; ... } else { comando4; comando5; ... }

25/197

if aninhado
if( x > 0 ) if( y > 0 ) printf("ponto else printf("ponto else if( y > 0 ) printf("ponto else printf("ponto

no 1o quadrante"); no 4o quadrante"); no 2o quadrante"); no 3o quadrante");

26/197

Expresso Condicional
#include <stdio.h> main() { int a, b; printf("digite dois numeros\n"); scanf("%d %d", &a, &b ); if(b) printf("%d\n", a/b ); else printf("nao pode dividir por zero"); }

27/197

Exerccios
(1) Fazer um programa que l as 3 notas de um aluno de Programao I (v1, v2 e MT, onde MT a mdia dos trabalhos). O programa calcula e imprime a mdia do aluno, usando a frmula Mdia=(3*v1+3*v2+4*MT)/10. (2) Utilizando o programa anterior, fazer um novo programa que verifica se o aluno atingiu a mdia 7. Caso positivo, o programa imprime a mensagem "aprovado por mdia". Caso contrrio, o programa calcula e imprime o valor necessrio na optativa, apresentando a mensagem apropriada. (Lembre-se que a mdia dos trabalhos no pode ser substituda pela optativa).

28/197

switch
Sintaxe:
switch(expressao) { case constante1: sequencia_de_comandos1; break; case constante2: sequencia_de_comandos2; break; case constante3: sequencia_de_comandos3; break; ... default: break; }

Seleo Mltipla

29/197

Exemplo - switch
ch=getchar(); switch(ch) { case 'C': case 'c': clio++; break; case 'S': scenic++; break; case 'K': kangoo++; break; case 'M': meganec++; break; default: break; }

30/197

Comandos de Iterao: for


Sintaxe: Caso 1 for( inicializacoes; testes; atualizacoes) comando; Caso 2 for( inicializacoes; testes; atualizacoes) { comando1; comando2; comando3; }

31/197

Comandos de Iterao: for


Funcionamento:
for( inicializacoes; testes; atualizacoes) { 3 comando1; comando2; comando3; }
1 2 4

32/197

Exemplo - for
#include <stdio.h> main() { int i, n; float valor, media; media = 0; printf("entre com o numero de valores\n"); scanf("%d", &n ); for( i=0; i<n; i++ ) { printf("entre com o %d valor\n", i+1 ); scanf("%f", &valor); media+=valor; } media/=n; printf("A media destes valores eh:%f\n", media); }

33/197

Exemplo - for
for( ; ; ) printf("Repita isso...\n");

char ch; ch='\0'; for( ; ; ) { ch = getchar(); //obtem um caractere if(ch=='A') break; //sai do laco } printf("tu digitaste um A, tche!\n");

34/197

Comandos de Iterao - for

Laos for sem corpo: for( i=0 ; i<tam ; i++ ); Este trecho serve, por exemplo, para posicionar um indexador (i, neste caso) numa dada posio, que pode ser o final de um vetor. Repare no ponto-e-vrgula logo aps o parntesis

35/197

Comandos de Iterao - while


Sintaxe: Caso 1
while( condicao ) comando;

Caso 2
while( condicao ) { comando1; comando2; comando3; }

36/197

Exemplo - while

Exemplo: int i = 0; while ( i <= 100) { printf("%d\n", i); i++; } Primeiro faz a comparao de i depois executa o lao de comandos; Repare na linha i++ incrementando o valor de i.

37/197

Comandos de Iterao do...while


Sintaxe: Caso 1
do comando; while( condicao );

Caso 2
do { comando1; comando2; comando3; } while( condicao );

38/197

Exemplo do...while
do scanf("%d", &num); while( num > 100 );

Este trecho de cdigo l nmeros do teclado at que encontre um nmero menor ou igual a 100.

39/197

Comandos de Desvio: return


usado para retornar de uma funo considerado um comando de desvio porque faz com que a execuo retorne ao ponto em que a chamada funo foi feita. Se return tem um valor associado a ele, este valor o valor de retorno da funo Se no houver valor associado ao return, assume-se que somente lixo retornado. Forma Geral: return expressao;

40/197

Comandos de Desvio: break

Usos: Terminar um case do comando switch; Forar uma terminao imediata de um lao. Quando o comando break encontrado dentro de um lao, o lao imediatamente terminado e o controle do programa retorna no comando seguinte ao lao. Forma Geral:

for( i=0; i<100; i++ ) { printf("%d", i); if( i == 10 ) break; } printf("Valor de i ao sair do laco: %d",i);

41/197

Comandos de Desvio: exit

Da mesma forma que se pode sair de um lao, pode-se sair de um programa usando a funo exit() da biblioteca padro. Esta funo provoca uma terminao imediata do programa inteiro, forando um retorno ao sistema operacional. Forma Geral: void exit(int codigo_de_retorno); O valor de codigo_de_retorno retornado ao processo chamador, que normalmente o sistema operacional O zero geralmente usado como cdigo de retorno que indica uma terminao normal do programa. Outros valores so usados para indicar algum tipo de erro.

42/197

Exerccios
(1) Escreva um programa que l as coordenadas de n pontos no plano cartesiano (x, y) e identifica se estes pontos pertencem: i) ao 1o. quadrante; ii) ao 2o. quadrante; iii) ao 3o. quadrante; iv) ao quarto quadrante; ou esto sobre v) o eixo dos "x"; vi) o eixo dos "y"; ou vii) esto na origem. Feito isso, o programa escrever os totais de pontos em cada uma destas situaes. (2) Considere a seguinte srie 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, e um inteiro positivo n. Deseja-se: i) imprimir os n primeiros termos da srie; e, ii) calcular e imprimir a soma dos n primeiros termos. Desenvolva dois programas utilizando for e do while que resolvam este problema. (3) Dados trs nmeros inteiros correspondentes, respectivamente, ao dia, ms e ano de nascimento de uma pessoa e trs outros nmeros correspondentes ao dia, ms e ano corrente (ex. data de hoje), calcular e imprimir a idade em anos completos. Verificar se as datas so compatveis (nascimento <= corrente).

43/197

Exerccios
(4) Usando o comando for, faa um programa que calcule o fatorial de um nmero inteiro n. (5) Refaa o exerccio anterior usando o comando while. (6) Faa um programa que recebe um nmero inteiro e imprime o somatrio de seus divisores. (7) Faa um programa que recebe um nmero inteiro e verifica se o nmero primo ou no, escrevendo uma mensagem apropriada. (8) Faa um programa que recebe l n conceitos de alunos (n fornecido no incio do programa) e conta quantos conceitos de cada tipo existem. Os conceitos possveis so: A, B, C, D, E e podem ser fornecidos com letras maisculas ou minsculas.

44/197

Matrizes

Uma matriz uma coleo de variveis do mesmo tipo que referenciada por um nome comum Em C todas as matrizes consistem em posies contguas na memria: o endereo mais baixo corresponde ao primeiro elemento o endereo mais alto corresponde ao ltimo elemento Um elemento especfico da matriz pode ser acessado por meio de um ndice Matrizes podem ter de uma a vrias dimenses

45/197

Matrizes Unidimensionais

Forma geral de se declarar uma matriz unidimensional: tipo nome_da_variavel[tamanho]; Como qualquer varivel, as matrizes precisam ser declaradas para que o compilador possa alocar espao na memria para elas tipo declara o tipo de base da matriz tamanho define a quantidade mxima de elementos que a matriz poder armazenar

46/197

Exemplos
Declarao de uma matriz chamada valor de 100 elementos do tipo int. int valor[100]; Para acessar o primeiro elemento da matriz valor: valor[0]=0; Para acessar o ltimo elemento da matriz valor: Valor[99]=0; float notas[100]; double balance[20]; char linha[80]; Em C, uma matriz de N elementos tem ndice que inicia em 0 (zero) e termina em N-1.

47/197

Alocao de Memria
Mas como o compilador calcula a quantidade de memria a ser alocada para uma dada matriz? total (bytes) = sizeof (tipo) * qtde elem da matriz Sizeof um operador unrio, em tempo de compilao, que retorna o tamanho, em bytes, da varivel ou especificador de tipo entre parntesis. O clculo do tamanho feito automaticamente, em tempo de compilao, para cada matriz declarada no programa. No preciso se preocupar com a alocao de memria.

48/197

Exemplo
float nota[50]; int i; for( i=0; i<50; i++) { printf("digite a nota do %d.o aluno\n", i+1); scanf("%f", &nota[i]); }

Ateno: C no tem verificao dos limites de matrizes. Isto significa que se pode escrever valores para alm do final da matriz, sobre outras variveis ou mesmo sobre o prprio cdigo do programa!

49/197

Exemplo
float nota[50]; int i; for( i=0; i<100; i++) { printf("digite a nota do %d.o aluno\n", i+1); scanf("%f", &nota[i]); }

tarefa do programador assegurar que isso no ocorra no programa!!!

50/197

Matrizes Bidimensionais

C suporta matrizes multidimensionais. Uma matriz bidimensional a forma mais simples Exemplo: int d[10][20]; Declara uma matriz do tipo int, com 10 linhas 20 colunas, chamada "d".

51/197

Exemplo
main() { float num[3][4]; int i,j; for( i=0; i<3; i++) for( j=0; j<4; j++) { printf("digite o elemento da linha %d, coluna %d\n", i+1, j+1); scanf("%f", &num[i][j]); } }

Uma matriz bidimensional exige sempre dois laos aninhados para sua manipulao.

52/197

Exemplo

Faa um programa que l n nmeros e calcula a mdia aritmtica destes. Em seguida, o programa conta quantos nmeros esto acima da mdia e imprime esta informao.

53/197

#include <stdio.h> #define TAM 1000 main() { float valor[TAM], media=0.0; int i,n, conta=0; printf("digite o numero de valores\n"); scanf("%d", &n); if (( n > TAM) || ( n < 1)) printf("erro: o tamanho deve estar entre 1 e %d\n", TAM); else { for( i = 0; i < n; i++) { printf("digite o %d .o valor\n", i+1); scanf("%f", &valor[i]); media+=valor[i]; } media/=n; for( i = 0; i < n; i++) if( valor[i] > media ) conta++; printf("media= %f \n%d valores acima da media\n", media, conta); } }

54/197

Matrizes Multidimensionais

C suporta matrizes com mais de 2 dimenses. O limite de dimenses definido pelo compilador usado (alguns compiladores no limitam) Exemplo de declarao: int m[10][20][4][100];

55/197

Inicializao de Matrizes
Forma Geral: Exemplos:

tipo matriz[tam1][tam2][tamN]={lista_de_valores};

int m[10]={1,2,3,4,5,6,7,8,9,10}; float aux[5]={0.0,1.0,2.0,3.0,4.0}; int matriz[10]={0};

Os elementos so inicializados com os valores da lista, seguindo a ordem da esquerda para a direita. Se no houver inicializadores suficientes, os elementos faltantes so inicializados com 0 (zero).

56/197

Outros Exemplos

Muitas vezes possvel inicializar uma matriz dentro de um lao (vantajoso quando o lao j existe):
float aux[1000], i; for( i=0; i<1000; i++) aux[i]=0.0;

int m[100], i; for( i=0; i<100; i++) m[i]=i;

char linha[80] = { 'E','u',' ','g','o','s','t','o',' ','d','e',' ','C','\0'};

char linha[80] = { "Eu gosto de C"};

57/197

Matrizes Unidimensionais de Caracteres

Usadas para armazenar cadeias de caracteres de interesse (strings). C prov uma biblioteca para o tratamento de strings. Conveno: cada string deve terminar com o caractere especial '\0'. O '\0' serve para delimitar o final de uma cadeia de caracteres (strings). Com ele se pode usar as bibliotecas de tratamento de strings. Sua existncia deve sempre ser levada em conta no tamanho de uma matriz de caracteres. Permite que se armazene uma string com nmero de caracteres menor do que o tamanho-1 da matriz.

58/197

Exemplos
main() { char c, linha[100]; int i=0; while((c=getchar()) != '\n') { linha[i]=c; i++; } linha[i]='\0'; //final de string printf("%s",linha); } main() { char linha[100] = {"Imprima esta linha."}; int i=0; while( linha[i] != '\0') { putchar(linha[i]); i++; } }

59/197

Outros Exemplos
#include <stdio.h> main() { char s[256] = "",str[256] = ""; scanf("%[aeiou]", s); // le apenas as vogais "aeiou" printf("String (s): %s\n", s); scanf("%[^A-Z]", str); // Nao le caracteres maiusculos de A a Z printf("String (str): %s\n", str); } #include <stdio.h> main() { char str[31]; printf("Digite seu nome: "); fgets(str, 30, stdin); // e o mesmo que scanf("%30s",str); ??? puts(str); // puts imprime na tela uma string }

60/197

Outros Comandos
Para utilizar: strcpy(s1, strcat(s1, strlen(s1) strcmp(s1, se s1 != s2; strchr(s1, de ch em s1. strstr(s1, de s2 em s1. deve-se incluir string.h

s2) - Copia s1 em s2. s2) - Concatena (junta) s2 ao final de s1. - Retorna o tamanho de s1. s2) - Retorna 0 se s1 e s2 so iguais; menor que zero ch) - Retorna um ponteiro para a primeira ocorrncia s2) - Retorna um ponteiro para a primeira ocorrncia

Para limpar o buffer de entrada: int x = getchar(); while (( x != '\n') && (x != EOF)) x = getchar();

61/197

Exerccios
(1) Faa um programa que l n nmeros decimais, armazenando-os em um vetor. Aps, o programa identifica o menor nmero do vetor e imprime sua posio. (2) Faa um programa que l n x m valores decimais, armazenando-os em uma matriz com n linhas e m colunas. Aps, para cada linha da matriz, o algoritmo calcula a mdia e conta quantos elementos esto acima da mdia calculada, imprimindo estas informaes. (3) Fazer um programa que l as 3 notas de n alunos (n fornecido pelo usurio, no incio do programa) de uma turma de Programao I (V1, V2 e MT, onde MT a mdia dos trabalhos). O programa calcula e imprime a mdia de cada aluno, usando a frmula M=(3*v1+3*v2+4*MT)/10. Aps, o programa calula e imprime a mdia da turma em V1, em V2 e em MT. Finalmente, o programa conta quantos alunos obtiveram nota maior que a mdia calculada para V1, imprimindo esta informao.

62/197

Exerccios
(4) Faa um programa que l n nmeros inteiros (cujo valor mximo no ultrapassa 1000). Aps, o programa imprime em ordem crescente os nmeros no duplicados do vetor. (5) Faa um programa que l n nmeros decimais (no mximo 10000 valores), armazenando-os em um vetor. Aps, o programa ordena este vetor usando o mtodo "Bubble Sort". Finalmente, o programa imprime o vetor ordenado. (6) Faa um programa que l duas matrizes de nmeros decimais, M1 e M2, ambas de tamanhos n x m. Aps, o programa cria e imprime a matriz S, resultante da soma de M1 com M2. (7) Faa um programa que l uma matriz de valores decimais e calcula a mdia de sua diagonal secundria. Aps, o programa deve verificar e imprimir a posio de cada elemento cujo valor est abaixo da mdia calculada.

63/197

Exerccios Complementares
(8) Escreva um programa que l n coordenadas x e y de pontos e as armazene em uma matriz. Decida para cada ponto se est ao Norte, Sul, Leste, Oeste, Nordeste, Noroeste, Sudoeste, Sudeste ou sobre o ponto anterior e informe com uma mensagem apropriada. Para o primeiro ponto lido tome a origem (0,0) para sua deciso. (9) Escreva um programa que preenche um vetor de 50 posies com zeros, com exceo da posio central, que deve ter o valor 1. Ainda, o programa l um valor n que representa o nmero de iteraes da aplicao da seguinte regra: o prximo valor da posio v[i] (v[i-1]+v[i+1]) mod 2, usar os valores de v[i-1] e v[i+1] da iterao anterior. Imprima o vetor original e todas as demais atualizaes do vetor.

64/197

Exerccios Complementares
(10) Leia um valor n mpar (3 < n < 50) para preencher e imprimir uma matriz da seguinte forma: n=5 ..x.. .xxx. xxxxx 5 caracteres x .xxx. ..x.. (11) Escreva um programa que embaralha uma matriz de ordem par n (n x n elementos) da seguinte maneira:
M original: 1234 2341 3412 4123 M embaralhada: 3412 4123 1234 3441

65/197

Ponteiros

Conceitos Envolvidos: Um ponteiro o endereo de uma varivel na memria. Uma varivel de ponteiro uma varivel especialmente declarada para guardar um ponteiro para seu tipo especificado.

66/197

Utilidades dos Ponteiros


So uma maneira rpida de referenciar uma varivel em C; So o meio pelo qual as funes em C conseguem modificar seus parmetros de chamada; Provem suporte s listas encadeadas e outras estruturas de dados dinmicas.

67/197

Operadores para Ponteiros

operador & : Operador unrio Devolve o endereo da memria em que se encontra alocado seu operando; Exemplo: m = &count; atribui a m o endereo da memria em que se encontra a varivel count. Esse endereo no tem nenhuma relao com o valor de count. Pode-se imaginar & como significando "o endereo de". Desta forma, a sentena de atribuio anterior significa "m recebe o endereo de count".

68/197

Operador & - Exemplo


endereo 1999 2000 2001 2002 ... memria 100 count

int count; ... count = 100; m = &count; ...

1) Assuma que a varivel count, quando foi declarada, ficou alocada para a posio de memria 2000. 2) Assuma tambm que count tem como valor 100. 3) Ento, aps a setena de atribuio m tem o valor 2000.

69/197

Operadores para Ponteiros

operador unrio * : Devolve o valor da varivel localizada no endereo que o segue. (ou seja, este operador sempre interpreta seu operando como um endereo a partir do exemplo anterior, se m contm o endereo da varivel count, q = *m; coloca o valor de count em q. Agora q tem o valor 100 porque 100 est armazenado na posio 2000, endereo da memria em que est armazenado m. Pode-se pensar no * como significando "o contedo do endereo ". Assim, a sentena anterior poderia ser lida como "q recebe o contedo do endereo m".
de memria!)

70/197

Declarando Ponteiros

Por exemplo, para declarar uma varivel ponteiro ch para char, escreve-se: char *ch; Aqui, ch no um caractere, mas um ponteiro para caractere (so conceitos completamente diferentes). Pode-se misturar diretivas de ponteiro e de no-ponteiro na mesma declarao, como por exemplo: int x, *y, count; Declara x e count como sendo do tipo inteiro e y como sendo um ponteiro para o tipo inteiro.

71/197

Usando Ponteiros
#include <stdio.h> void main(void) { int target, source=10, *m; m = &source; target = *m; printf("%d", target); }

72/197

Atribuio de Ponteiros

Como qualquer varivel, um ponteiro pode ser usado do lado direito de um comando de atribuio para se passar seu valor para outro ponteiro:

#include <stdio.h> void main(void) { int x=0, *p1, *p2; p1 = &x; p2 = p1; printf("%p", p2); }

73/197

Aritmtica de Ponteiros

Existem apenas duas operaes aritmticas que podem ser feitas com ponteiros: Adio Subtrao Regras da aritmtica de ponteiros: 1. Cada vez que um ponteiro incrementado, ele aponta para a posio de memria do prximo elemento do seu tipo base. 2. Cada vez que um ponteiro decrementado, ele aponta para a posio de memria do elemento anterior do seu tipo base

74/197

Aritmtica de Ponteiros - Exemplo

Exemplo: assuma que estamos usando uma mquina na qual um inteiro ocupa 2 bytes. Ento int *p1, x; p1 = &x; p1++;

Se x estava armazenada na posio de memria 2000. Ento, aps p1++, p1 conter o valor 2002.

75/197

Comparao de Ponteiros

possvel comparar dois ponteiros em uma expresso relacional. Exemplo:


if(p<q) printf("p aponta para uma memoria mais baixa que q\n");

Geralmente, comparaes de ponteiros so usadas para verificar se dois ou mais ponteiros apontam para um mesmo objeto (uso em estruturas de dados tais como pilhas, filas etc)

76/197

Ponteiros e Matrizes

H uma estreita relao entre ponteiros e matrizes. De fato, os ndices das matrizes so uma maneira mais confortvel para se acessar um dado elemento de uma matriz. char nome[80], *p1, ch; p1 = nome; P1 foi inicializado com o endereo do primeiro elemento da matriz nome ch = nome[4]; ou ch=*(p1+4) copiam o quinto elemento de nome para ch

77/197

Exemplos
for( i=0; nome[i] != '\0'; i++) putchar(nome[i]);

for( p=nome; *p; p++) putchar(*p);

p=nome; while(*p) putchar(*p++);

78/197

Exemplos
#include <stdio.h> #include <string.h> main() { char *p = "alo mundo"; int t; printf(p); printf("\n"); for (t=strlen(p)-1; t >-1; t--) printf("%c", p[t]); }

79/197

Exemplos
#include <stdio.h> #include <string.h> void main(void) { int i; char *p1, c, s[80]; p1=s; do { i = 0; while((c=getchar()) != '\n') { s[i]=c; i++; } s[i]='\0'; while (*p1) printf(" %c", *p1++); printf("\n"); } while (strcmp(s,"feito!")); }

80/197

Matrizes de Ponteiros

Como qualquer outro tipo bsico, ponteiros podem ser organizados em matrizes: int *listas[100]; Para se atribuir o endereo de uma varivel inteira, chamada var, ao terceiro elemento da matriz de ponteiros, deve-se escrever: listas[2] = &var; Para encontrar o valor de var, escreve-se: *listas[2];

81/197

Indireo Mltipla
Ocorre quando se tem um ponteiro que aponta para outro ponteiro que (finalmente) aponta para o valor. 1. Indireo simples
ponteiro varivel valor valor endereo endereo

2. Indireo mltipla
ponteiro endereo endereo ponteiro endereo endereo varivel valor valor

82/197

Exemplo
#include <stdio.h> void main(void) { int x, *p, **q; x = 10; p = &x; q = &p; printf("%d", **q); }

83/197

Exerccios
(1) Seja o seguinte trecho de programa: int i=3,j=5; int *p, *q; p = &i; q = &j; Qual o valor das seguintes expresses ? a) p = &i b) *p - *q c) **&p d) 3* - *p/(*q)+7 (2) Qual ser a sada deste programa supondo que i ocupa o endereo 1000 na memria? main() { int i=5, *p; p = &i; printf("%p %d **&p+4); }

%d

%d

%d \n", p, *p+2, **&p, 3**p,

84/197

Exerccios
(3) Se i e j so variveis inteiras e p e q ponteiros para int, quais das seguintes expresses de atribuio so ilegais? a) p = &i; b) *q = &j; c) p = &*&i; d) i = (*&)j; e) i = *&j; f) i = *&*&j; g) q = *p; h) i = (*p)++ + *q (4) Qual o resultado do seguinte programa?
#include <stdio.h> void main(){ float vet[5] = {1.1,2.2,3.3,4.4,5.5}; float *f; int i; f = vet; printf("contador/valor/valor/endereco/endereco"); for(i = 0 ; i <= 4 ; i++){ printf("\ni = %d",i); printf(" vet[%d] = %.1f",i, vet[i]); printf(" *(f + %d) = %.1f",i, *(f+i)); printf(" &vet[%d] = %p",i, &vet[i]); printf(" (f + %d) = %p",i, f+i); } }

85/197

Exerccios
(5) Quais sero as sadas do seguinte programa?
#include <stdio.h> main () { int valor; int *p1; float temp; float *p2; char aux; char *nome = "Algoritmos"; char *p3; int idade; int vetor[3]; int *p4; int *p5; /* (a) */ valor = 10; p1 = &valor; *p1 = 20; printf ("(a) %d \n", valor); /* (b) */ temp = 26.5; p2 = &temp; *p2 = 29.0; printf ("(b) %.1f \n", temp); /* (c) */ p3 = &nome[0]; aux = *p3; printf ("(c) %c \n", aux); /* (d) */ p3 = &nome[4]; aux = *p3; printf ("(d) %c \n", aux);

86/197

/* (e) */ p3 = nome; printf ("(e) %c \n", *p3); /* (f) */ p3 = p3 + 4; printf ("(f) %c \n", *p3); /* (g) */ p3--; printf ("(g) %c \n", *p3); /* <h> */ vetor[0] = 31; vetor[1] = 45; vetor[2] = 27; p4 = vetor; idade = *p4; printf ("(h) %d \n", idade); /* (i) */ p5 = p4 + 1; idade = *p5; printf ("(i) %d \n", idade); /* (j) */ p4 = p5 + 1; idade = *p4; printf ("(j) %d \n", idade); /* (l) */ p4 = p4 - 2; idade = *p4; printf ("(l) %d \n", idade); /* (m) */ p5 = &vetor[2] - 1; printf ("(m) %d \n", *p5); /* (n) */ p5++; printf ("(n) %d \n", *p5); }

87/197

Exerccios
(6) Assumindo que pulo[] um vetor do tipo int, quais das seguintes expresses referenciam o valor do terceiro elemento da matriz? a) *(pulo + 2) b) *(pulo + 4) c) pulo + 4 d) pulo + 2 (7) Supor as declaraes: int mat[4], *p, x; Quais expresses so vlidas? Justifique: a) p= mat + 1; b) p= mat++; c) p= ++mat; d) x=(*mat)++; (8) O que fazem os seguintes programas?
#include <stdio.h> void main(){ int vet[] = {4,9,13}; int i; for(i=0;i<3;i++){ printf("%d ",*(vet+i)); } } } #include <stdio.h> void main(){ int vet[] = {4,9,13}; int i; for(i=0;i<3;i++){ printf("%p ",vet+i); }

88/197

Exerccios
(9) O que fazem os seguintes programas quando executados?

#include <stdio.h> void main() { int vet[] = {4,9,12}; int i,*ptr; ptr = vet; for(i = 0 ; i < 3 ; i++) { printf("%d ",*ptr++); } }

#include <stdio.h> void main(){ int vet[] = {4,9,12}; int i,*ptr; ptr = vet; for(i = 0 ; i < 3 ; i++) { printf("%d ",(*ptr)++); } }

89/197

Exerccios
(10) Seja vet um vetor de 4 elementos: TIPO vet[4]. Supor que depois da declarao, vet esteja armazenado no endereo de memria 1000 (ou seja, o endereo de vet[0]). Supor tambm que na mquina usada uma varivel do tipo char ocupa 1 byte, do tipo int ocupa 4 bytes, do tipo float ocupa 4 bytes e do tipo double ocupa 8 bytes. Qual o valor de vet+1, vet+2 e vet+3 se: a) vet for declarado como char? b) vet for declarado como int? c) vet for declarado como float? d) vet for declarado como double?

90/197

Funes

Conceitos: Funes so os blocos de construo de C e o local onde toda a atividade do programa ocorre. Qualquer programa C possui ao menos uma funo (main).

91/197

Forma Geral
tipo nome_da_funo(lista de parmetros) { corpo da funo } tipo especifica o tipo de valor que o comando return da funo devolve, podendo ser qualquer tipo vlido. Se nenhum tipo especificado, o compilador assume que a funo devolve um resultado inteiro.

92/197

Forma Geral
tipo nome_da_funo(lista de parmetros) { corpo da funo } lista de parmetros uma lista de nomes de variveis separados por vrgulas e seus tipos associados que recebem os valores dos argumentos quando a funo chamada. Uma funo pode no ter parmetros, neste caso a lista de parmetros vazia. Ainda assim os parntesis so necessrios. f(tipo nomevar1, tipo nomevar2, , tipo nomevarN)

93/197

Regras de Escopo

As regras de escopo de uma linguagem so as regras que determinam se uma poro de cdigo conhece ou tem acesso a outra poro de cdigo ou dados. Em C, cada funo um bloco discreto de cdigo. Um cdigo de uma funo privativo quela funo e no pode ser acessado por nenhum comando em outra funo, exceto por meio de uma chamada funo O cdigo que constitui o corpo de uma funo escondido do resto do programa e, a menos que use variveis ou dados globais, no pode afetar ou ser afetado por outras partes do programa O cdigo e os dados que so definidos internamente a uma funo no podem interagir com o cdigo ou dados definidos em outra funo porque as duas funes tm escopos diferentes.

94/197

Regras de Escopo

Variveis locais: So as variveis definidas internamente a uma funo Existem somente durante a execuo da funo que as definiu No podem manter seus dados entre chamadas da funo, exceto se se usa o especificador de tipo de armazenamento static Em C, todas as funes esto no mesmo nvel de escopo Por este motivo, C no considerada uma linguagem estruturada em blocos

95/197

Argumentos

Se uma funo usa argumentos, ento ela deve declarar variveis que aceitem os valores dos argumentos. Essas variveis so chamadas parmetros formais da funo. Parmetros formais comportam-se como variveis locais dentro da funo: so criadas na entrada e destrudas na sada. A declarao ocorre aps o nome da funo (e segundo o padro ANSI, entre os parntesis)

96/197

Comando return

Possui dois usos: Invoca uma sada imediata da funo que o contm (faz com que a execuo do programa retorne ao cdigo chamador) usado para devolver um valor H duas maneiras pelas quais uma funo termina sua execuo (e retorna ao cdigo qua a chamou): Ao executar o ltimo comando da funo (e o } ) Quando o comando return encontrado

97/197

Exemplo

is_in(char *s, char c) { while(*s) if(*s==c) return 1; else s++; return 0; }

98/197

Argumentos

Os argumentos usados para chamar a funo devem ser compatveis com os tipos de seus parmetros. C robusta: se os tipos forem incompatveis, o compilador no gera uma mensagem de erro, mas ocorrem resultados inesperados. O uso de prottipos de funes pode ajudar a achar esses tipos de erros. Tal como as variveis locais da funo, os parmetros formais podem ser usados em qualquer expresso permitida em C

99/197

Argumentos

Em C, podem ser passados argumentos para subrotinas de duas maneiras: Chamada por valor Chamada por referncia

100/197

Chamada por Valor

Parmetro formal da funo recebe uma cpia do valor do argumento. Conseqncia: As alteraes feitas nos parmetros formais da funo no tm nenhum efeito nas variveis usadas para cham-la.

101/197

Chamada por Referncia

O parmetro formal da funo recebe uma cpia do endereo do argumento (ponteiro). Conseqncias: Dentro da funo, o endereo usado para acessar o argumento real usado na chamada. Alteraes feitas no parmetro afetam a variveis usada para chamar a funo.

102/197

Exemplo
#include <stdio.h> int pot(int n, int e); void main(void) { int t=10; printf("%d %d", t, pot(t,2)); } int pot(int n, int e) { int total=n; for(e; e>1; e--) total = total*n; return(total); }

Note que o valor da varivel t, usada como argumento na chamada de pot, permanece inalterado, de modo que a sada deste programa ser ''10 100''.

103/197

Exemplo
#include <stdio.h> void troca(int *x, int *y); void main( void ) { int a, b; scanf("%d %d", &a, &b); printf("a=%d b=%d\n", a, b); troca(&a, &b); printf("a=%d b=%d\n", a, b); } void troca(int *x, int *y) { int temp; temp = *x; *x = *y; *y = temp; }

Para a chamada por referncia, deve-se passar para a funo um ponteiro para cada argumento que se deseja modificar

104/197

Funes e Matrizes

Em C, um nome de matriz sem qualquer ndice um ponteiro para o primeiro elemento da matriz. H 3 maneiras de se declarar um parmetro que ir receber um ponteiro para matriz.

105/197

Exemplos
#include <stdio.h> void imprime(int num[10]); void main(void) { int t[10], i; for(i=0; i<10; i++) t[i]=i; imprime(t); } void imprime(int num[10]) { int i; for(i=0; i<10; i++) printf("%d ", num[i]); }

Caso 1) Declarando como uma matriz apesar de num ter sido declarado como uma matriz, o compilador C o converte automaticamente para um ponteiro de inteiros.

isto ocorre porque nenhum parmetro pode realmente receber uma matriz completa.

106/197

Exemplos
#include <stdio.h> void imprime(int num[]); void main(void) { int t[10], i; for(i=0; i<10; i++) t[i]=i; imprime(t); } void imprime(int num[]) { int i; for(i=0; i<10; i++) printf("%d ", num[i]); }

Caso 2) Especificando uma matriz sem dimenso Neste caso, num declarado como uma matriz de inteiros de tamanho desconhecido.

Os limites da matriz precisam ser respeitados, o que fica por conta do programador, pois C no testa tais limites. (Este mtodo realmente define num como um ponteiro para inteiros).

107/197

Exemplos
#include <stdio.h> void imprime(int *num); void main(void) { int t[10], i; for(i=0; i<10; i++) t[i]=i; imprime(t); } void imprime(int *num) { int i; for(i=0; i<10; i++) printf("%d ", num[i]); }

Caso 3) Usando Ponteiros Isto permitido porque qualquer ponteiro pode ser indexado usando [], como se fosse uma matriz.

Esta a forma mais comum em programas profissionais.

108/197

Argumentos para main()

Freqentemente, necessrio passar informaes para um programa antes que ele inicie a executar Isto feito mediante os argumentos da linha de comando. Exemplo: marilton@redbull:~$ ./prog -p arq.txt Neste exemplo, prog poderia ser o programa, -p poderia ser uma opo para imprimir os dados do arquivo arq.txt Todo programa C executa a partir da funo main Existem 2 argumentos internos especiais que so usados para receber os argumentos da linha de comando: argc e argv

109/197

Argumentos para main()

argc

Contm o nmero de argumentos de linha de comando digitados pelo usurio Obviamente, um inteiro argc sempre vale ao menos 1 porque o prprio nome do programa considerado como primeiro argumento. um ponteiro para uma matriz de ponteiros para caractere (char *argv[]); Cada elemento nessa matriz aponta para um argumento da linha de comando Todos os argumentos da linha de comando so strings (quaisquer nmeros tero que ser convertidos pelo programa para o formato adequado)

argv

110/197

Exemplo

Este programa imprime a string que vier aps o nome usado para invoc-lo (cham-lo):

#include <stdio.h> #include <stdlib.h> //por causa de exit() void main(int argc, char *argv[]) { if(argc!=2) { printf("Erro: Informe seu nome como parmetro!\n"); exit(1); } printf("Ol, %s!\n", argv[1]); }

111/197

Outros Exemplos
#include <stdio.h> #include <string.h> void inverte(char *s); void main(void) { char *msg="Eu gosto de C"; inverte(msg); } void inverte(char *s) { int i; for(i=strlen(s)-1; i>=0; i--) putchar(s[i]); }

112/197

#include <stdio.h> int substring(char *string1, char *string2); void main(void) { if(substring("C eh legal", "eh")) printf(" substring!\n"); else printf("No substring!\n"); } int substring(char *string1, char *string2) { int i; char *p1, *p2; for(i=0; string1[i]; i++) { p1=&string1[i]; p2=string2; while(*p2 && *p2==*p1) { p1++; p2++; } if(!*p2) return 1; } return 0; }

113/197

Funes

Todas as funes, exceto as do tipo void, retornam um valor Este valor explicitamente especificado pelo comando return Se no houver um comando return na funo, ento o valor de retorno ser tecnicamente indefinido Neste caso, geralmente os compiladores C devolvem o valor zero (mas no se pode contar com isso) Desde que uma funo no seja void, ela pode ser usada como operando em qualquer expresso vlida em C

114/197

Biblioteca de Rotinas
bib.h int fatorial (int n); bib.c #include "bib.h" int fatorial (int n) { if ((n==1)||(n==0)) return 1; else return n*fatorial(n-1); } principal.c #include <stdio.h> #include "bib.h" main() { int n; printf("Informe n para o fatorial: "); scanf("%d", &n); printf("fat(%d) = %d", n, fatorial(n)); }

gcc principal.c bib.c -o teste

115/197

Exerccios
(1) Modifique o programa do exerccio 1 do slide 27, de modo a fazer o clculo da mdia das notas utilizando uma funo, que recebe como parmetros as notas N1, N2 e MT, e devolve a mdia M. O programa verifica se o aluno atingiu a mdia 7 e em caso positivo, o programa imprime a mensagem ''aprovado por mdia''. Caso contrrio, o programa chama uma outra funo que calcula e retorna o valor necessrio na optativa, que ser impresso no programa principal. (2) Faa um programa que calcule e imprima o fatorial de um nmero N. Este programa deve usar uma funo, a qual calcula o fatorial do nmero lido. No esquea de testar as restries cabveis a N.

116/197

Exerccios
(3) Faa um programa utilizando uma funo que l um nmero inteiro e verifica se este nmero primo ou no, imprimindo uma mensagem condizente. (4) Faa um programa que l dois nmeros inteiros, A e B, e, com uma funo, testa se estes nmeros so amigos. Dizemos que dois nmeros so amigos se cada um deles igual a soma dos divisores prprios do outro. Os divisores prprios de um nmero positivo N so todos os divisores inteiros positivos de N exceto o prprio N. (5) Modifique o programa do exerccio 2, de modo que o nmero N seja passado como parmetro na linha de comando. (6) Modifique o programa do exerccio anterior, transformando a funo "fatorial" em uma funo recursiva.

117/197

Exerccios
(7) Faa um programa que l n nmeros decimais (n fornecido pelo usurio), armazenando-os em um vetor. Logo aps, uma funo deve retirar os nmeros duplicados que eventualmente possam existir neste vetor, deixando apenas uma ocorrncia de cada nmero. Ao final, o vetor resultante deve ser impresso na tela. (8) Faa um programa que leia uma string (de 80 caracteres) chamada linha e, com uma funo, identifique cada palavra (substring) desta linha copiando-a para um novo vetor. Ao final, o programa deve imprimir as palavras separadas, uma palavra por linha. Dicas: i) faa uma funo para identificar o fim e/ou o incio de cada substring em linha; e, ii) utilize o modo de leitura apresentado no slide 58.

118/197

Estruturas

A linguagem C permite ao usurio criar tipos de dados de 5 formas diferentes: Estrutura (chamado tipo de dado agregado) Campo de Bit Unio Enumerao Usando typedef

119/197

Uma estrutura uma coleo de variveis referenciadas por um nome til quando se deseja agrupar informaes ("registros") Uma definio de estrutura forma um modelo que pode ser usado para criar variveis de estrutura As variveis que formam a estrutura so chamados membros (ou campos ou elementos ou registros). Geralmente, todos os membros de uma estrutura so relacionados

120/197

Criando uma Estrutura


struct end { char nome[30]; char rua[40]; char cidade[20]; char estado[3]; unsigned long int cep; };

No trecho acima, nenhuma varivel foi de fato declarada. Apenas a forma dos dados foi definida. Para declarar uma varivel do tipo end deve-se escrever: struct end info;

121/197

Quando uma varivel de estrutura (como end) declarada, o compilador C aloca automaticamente memria suficiente para acomodar todos os seus membros. Exemplo (assumindo caracteres com 1 byte e inteiros longos com 4 bytes): nome (30 bytes) rua (40 bytes) cidade (20 bytes) estado (3 bytes) cep (4 bytes)

122/197

Declaraes de Variveis

struct { char nome[30]; char rua[40]; char cidade[20]; char estado[3]; unsigned long int cep; } info;

struct end { char nome[30]; char rua[40]; char cidade[20]; char estado[3]; unsigned long int cep; } info, info2, info3;

123/197

Forma Geral

struct identificador { tipo varivel-registro; tipo varivel-registro; tipo varivel-registro; ... } variveis-estutura;

124/197

Referenciando Elementos

A forma geral para se acessar um elemento de estrutura : nome_da_estrutura.nome_do_elemento Elementos individuais de estruturas so referenciados por meio do operador ponto. info.cep = 96010; Atribui o valor 96010 ao campo cep da varivel estrutura info. Exemplos: printf("%d", info.cep); scanf("%d", &info.cep);

125/197

Referenciando Elementos
int i; char c; while((c=getchar()) != '\n') { info.nome[i]=c; i++; } info.nome[i]='\0'; gets(info.nome)

int i; while((info.nome[i] != '\0') { putchar(info.nome[i]); i++; }

printf("%s",info.nome)

126/197

Atribuio de Estruturas
Em C padro ANSI o contedo de uma estrutura pode ser atribudo a outra estrutura do mesmo tipo.
#include <stdio.h> void main(void) { struct { int a; int b; } x,y; x.a = 10; y=x; printf("%d", y.a); }

127/197

Matrizes de Estruturas

o uso mais comum para estruturas... Primeiro definir uma estrutura Depois, declarar uma varivel matriz desse tipo struct end info[100]; Cria 100 conjuntos de variveis, onde cada varivel est organizada conforme definido na estrutura end.

128/197

Exemplo
#include <stdio.h> #include <stdlib.h> #define MAX 100 struct end { char nome[31]; char rua[41]; char cidade[21]; char estado[3]; unsigned long int cep; } info[MAX]; void cria_lista(void); void insere(void); void apaga(void); void imprime(void); int menu(void); int livre(void); void ler_string(char palavra[100], int tamanho);

129/197

int main(void) { int escolha; cria_lista(); for( ; ; ) { escolha = menu(); switch(escolha) { case 1: insere(); break; case 2: apaga(); break; case 3: imprime(); break; case 4: exit(0); break; } } }

130/197

void cria_lista(void) { int i; for( i=0; i<MAX; i++) info[i].nome[0]='\0'; } int menu(void) { int c=0; do { printf("-- MENU:\n"); printf("\t 1. Inserir um nome\n"); printf("\t 2. Excluir um nome\n"); printf("\t 3. Listar o arquivo\n"); printf("\t 4. Sair\n"); printf("-- Digite sua escolha: "); scanf("%d", &c); } while(c<=0 || c>4); getchar(); return c; }

131/197

void ler_string(char palavra[100], int tamanho) { int i = 0; char c; c = getchar(); while ((c != '\n') && (i < tamanho)) { palavra[i++] = c; c = getchar(); } palavra[i] = '\0'; if (c != '\n') { c = getchar(); while((c != '\n') && (c != EOF)) { c = getchar(); } } }

132/197

void insere(void) { int posicao; posicao=livre(); if(posicao == -1) { printf("\nEstrutura Cheia!!"); return; } printf("-- Registro %d:\n", posicao); printf("\t Nome: "); ler_string(info[posicao].nome, 30); printf("\t Rua: "); ler_string(info[posicao].rua, 40); printf("\t Cidade: "); ler_string(info[posicao].cidade, 20); printf("\t Estado: "); ler_string(info[posicao].estado, 2); printf("\t CEP: "); scanf("%d", &info[posicao].cep); }

133/197

int livre(void) { int i; for( i=0; info[i].nome[0] && i< MAX; i++); if( i == MAX ) return -1; return i; } void apaga(void) { int posicao; printf("Nmero do Registro: "); scanf("%d",&posicao); if(posicao >=0 && posicao < MAX) info[posicao].nome[0]='\0'; }

134/197

void imprime(void) { int i; for( i=0; i < MAX; i++) if(info[i].nome[0] != '\0') { printf("-- Registro %d:\n", i); printf("\t Nome: %s", info[i].nome); printf("\t Rua: %s", info[i].rua); printf("\t Cidade: %s", info[i].cidade); printf("\t Estado: %s\n", info[i].estado); printf("\t CEP: %lu\n", info[i].cep); } }

135/197

typedef

C permite que sejam definidos explicitamente novos nomes aos tipos de dados utilizando a palavra-chave typedef No se est criando uma nova classe de dados, mas apenas definindo um novo nome para tipos j existentes. Exemplo: typedef float nota; nota prova01;

136/197

#include <stdio.h> typedef struct { int dia; int mes; int ano; } data; void main(void) { data aniversario; aniversario.dia = 14; aniversario.mes = 1; aniversario.ano = 1975; printf("%d / %d / %d.", aniversario.dia, aniversario.mes, aniversario.ano); }

137/197

Exemplo 2
#include <stdio.h> #include <math.h> typedef struct { int x; int y; } ponto; typedef struct { ponto cie; ponto csd; } retangulo; typedef struct { ponto centro; float raio; } circulo; float distancia(int x1, int y1, int x2, int y2) { return sqrt(pow(fabs(x2 - x1), 2) + pow(fabs(y2 - y1), 2)); } //canto inferior esquerdo //canto superior direito

138/197

int main(void) { ponto A; ponto B; circulo C; retangulo R; float dist; printf("Informe as coordenadas do ponto A: "); scanf("%d %d", &A.x, &A.y); printf("Informe as coordenadas do ponto B: "); scanf("%d %d", &B.x, &B.y); R.cie = A; R.csd = B; printf("Coordenada do CIE de R: (%d,%d)\n", R.cie.x, R.cie.y); printf("Coordenada do CSD de R: (%d,%d)\n\n", R.csd.x, R.csd.y); C.centro = B; C.raio = 10.0; printf("Coordenada do centro de C: (%d,%d)\n", C.centro.x, C.centro.y); printf("Raio de C: %f\n", C.raio); dist = distancia(C.centro.x, C.centro.y, A.x, A.y); if (dist <= C.raio) printf("O ponto A est DENTRO do crculo C.\n"); else printf("O ponto A est FORA do crculo C.\n"); printf("Distncia do ponto A ao centro de C: %f", dist); return 0; }

139/197

Exerccios
(1) Compile o programa do slide 128. Teste-o. (2) Modifique o programa do slide 128, de modo que ele permita apagar somente os dados de uma pessoa com Nome e Sobrenome fornecidos pelo usurio do programa. Porm, antes de apagar os dados, o programa deve perguntar se o usurio deseja mesmo apagar... Sugesto: fazer uma funo que busca na lista a posio (ndice) onde se encontram armazenados os dados de uma pessoa de Nome e Sobrenome (ex: Joao Silva). (3) Modifique o programa do slide 128, de modo que ele permita tambm a impresso de todos os dados de uma pessoa com Nome e Sobrenome. Sugesto: usar a funo de busca feita na questo 2. (4) Modifique o programa do slide 128, de modo que antes de inserir um novo nome, ele teste se o referido nome j est presente na lista (testar ambos Nome e Sobrenome). Sugesto: usar a funo de busca feita na questo 2.

140/197

Arquivos

Streams e Arquivos O sistema de E/S da linguagem C fornece uma interface consistente ao programador, independentemente do dispositivo real que acessado. Este sistema (que uma abstrao) chamado de stream e o dispositivo real chamado de arquivo. Da decorre que, em C, todos os dispositivos so encarados como arquivos

141/197

Streams

O sistema de arquivos de C projetado para trabalhar com uma ampla variedade de dispositivos, incluindo: terminais, acionadores de disco, e acionadores de fita. Embora cada um dos dispositivos seja muito diferente, o sistema de arquivo com buffer transforma-os em um dispositivo lgico chamado de stream.

142/197

Streams

Todas as streams comportam-se de forma semelhante. Pelo fato de as streams serem totalmente independentes do dispositivo, a mesma funo pode escrever em um arquivo em disco ou em algum outro dispositivo, como o console. Existem dois tipos de streams: texto e binria.

143/197

Streams de Texto

Um stream de texto uma seqncia de caracteres. O padro C ANSI permite (mas no exige) que uma stream de texto seja organizada em linhas terminadas por um caractere de nova linha. Porm, o caractere de nova linha opcional na ltima linha e determinado pela implementao.

144/197

Streams Binrias

Uma stream binria uma seqncia de bytes com uma correspondncia de um para um com aqueles encontrados no dispositivo externo. O nmero de bytes escritos (ou lidos) o mesmo que o encontrado no dispositivo externo. Porm, um nmero definido pela implementao de bytes nulos pode ser acrescentado a um stream binrio. Esse bytes nulos poderiam ser usados para aumentar a informao para que ela preenchesse um setor de um disco, por exemplo.

145/197

Arquivos

Em C, um arquivo pode ser qualquer coisa, desde um arquivo em disco at um terminal ou uma impressora. Associa-se um stream com um arquivo especfico realizando uma operao de abertura. Uma vez o arquivo aberto, informaes podem ser trocadas entre ele e o seu programa.

146/197

Arquivos

Nem todos os arquivos apresentam os mesmos recursos. Por exemplo, um arquivo em disco pode suportar acesso aleatrio (sequencial), enquanto um teclado no pode. Isso releva um ponto importante sobre o sistema de E/S de C: todas as streams so iguais, mas no todos os arquivos.

147/197

Arquivos

Se o arquivo pode suportar acesso aleatrio Abrir este arquivo inicializa o indicador de posio no arquivo para o comeo do arquivo Quando cada caractere lido ou escrito no arquivo, o indicador de posio incrementado, garantindo progresso atravs do arquivo.

148/197

Arquivos

Um arquivo desassociado de uma stream especfica por meio de uma operao de fechamento. Se um arquivo aberto para sada for fechado, o contedo, da sua stream associada ser escrito no dispositivo externo. Este processo geralmente referido como descarga (flushing) da stream e garante que nenhuma informao seja acidentalmente deixada no buffer do disco.

149/197

Arquivos

Todos os arquivos so fechados automaticamente quando o programa termina normalmente, com main() retornando ao sistema operacional ou uma chamada a exit() Os arquivos no so fechados quando um programa quebra (crash) ou quando ele chama abort().

150/197

Fundamentos do Sistema de Arquivos

Cada stream associada a um arquivo tem uma estrutura de controle de arquivo do tipo FILE. Esta estrutura definida no cabealho stdio.h. O sistema de arquivos C ANSI composto de diversas funes interrelacionadas. Estas funes exigem o cabealho stdio.h. A maioria das funes comea com a letra "f".

151/197

Nome fopen() fclose() puts() fputs() gets() fgets() fseek() fprintf() fscanf() feof() ferror() rewind() remove() fflush()

Funo abre um arquivo fecha um arquivo escreve um caractere em um arquivo idem l um caracteres de um arquivo idem posiciona um arquivo em um byte especfico o mesmo que printf() para console o mesmo que scanf() para console devolve verdadeiro para fim de arquivo devolve verdadeiro se ocorreu algum erro recoloca o indicador de posio para o incio do arquivo apaga um arquivo descarrega um arquivo

152/197

arquivo de cabealho stdio.h fornece os prottipos para as funes de E/S e define estes trs tipos: size_t, fpos_t e FILE Os tipos size_t e fpos_t so essencialmente o mesmo que um unsigned. O tipo FILE ser discutido logo adiante stdio.h tambm define vrias macros. As mais relevantes so: NULL, EOF, FOPEN_MAX, SEEK_SET, SEEK_CUR e SEEK_END.

153/197

A macro NULL define um ponteiro nulo A macro EOF geralmente definida como 1 e o valor devolvido quando uma funo de entrada tenta ler alm do final do arquivo FOPEN_MAX, define um valor inteiro que determina o nmero de arquivos que podem estar abertos ao mesmo tempo As outras macros so usadas com fseek(), que uma funo que executa acesso aleatrio em um arquivo.

154/197

Ponteiro de Arquivo

Um ponteiro de arquivo um ponteiro para informaes que definem vrias coisas sobre o arquivo: nome, status e a posio atual do arquivo Um ponteiro de arquivo uma varivel ponteiro do tipo FILE. Para ler ou escrever arquivos, seu programa precisa usar ponteiros de arquivo. Para obter uma varivel ponteiro de arquivo, use o comando: FILE *fp;

155/197

Abrindo um Arquivo

A funo fopen() abre uma stream para uso e associa um arquivo a ela Ela retorna o ponteiro de arquivo associado a este arquivo
FILE fopen(const char* nomearq, const char* modo*);

onde nomearq um ponteiro para uma cadeia de caracteres que forma um nome vlido de arquivo e pode incluir uma especificao de caminho de pesquisa (path).

156/197

Abrindo um Arquivo
Modo r w a rb wb ab r+ w+ a+ r+b w+b a+b Significado abre arquivo texto para leitura cria arquivo texto para escrita anexa ao arquivo texto abre arquivo binrio para leitura cria arquivo binrio para escrita anexa ao arquivo binrio abre arquivo texto para leitura/escrita cria arquivo texto para leitura/escrita anexa ao arquivo texto para leitura/escrita abre arquivo binrio para leitura/escrita cria arquivo binrio para leitura/escrita anexa ao arquivo binrio para leitura/escrita

157/197

Abrindo um Arquivo
FILE *fp; if((fp = fopen( "arquivo.txt", "w")) == NULL ) { printf("nao foi possivel criar o arquivo\n"); exit(1); }

Neste caso, qualquer erro na abertura do arquivo ser detectado (e.g., disco cheio ou protegido contra gravao).

158/197

Algumas Consideraes

Confirmar o sucesso de fopen() antes de tentar qualquer outra operao sobre o arquivo! Se voc usar fopen() para abrir um arquivo com permisso para escrita, qualquer arquivo j existente com esse nome ser apagado e um novo arquivo ser iniciado Se nenhum arquivo com este nome existe, ento o arquivo ser criado.

159/197

Se voc deseja adicionar ao final do arquivo, deve usar o modo "a". Arquivos j existentes s podem ser abertos para operaes de leitura. Se o arquivo no existe, um erro devolvido. Se um arquivo aberto para operaes de leitura/escrita, ele no ser apagado caso j exista e, seno existir, ele ser criado.

160/197

Fechando um Arquivo

A funo fclose() fecha uma stream que foi aberta por meio de uma chamada a fopen() Ela escreve qualquer dado que ainda permanece no buffer de disco no arquivo e, ento, fecha normalmente o arquivo em nvel de sistema operacional Se um arquivo aberto para operaes de leitura/escrita, ele no ser apagado caso j exista e, seno existir, ele ser criado.

161/197

Fechando um Arquivo

Um fclose() tambm libera o bloco de controle de arquivo associado stream, deixando-o disponvel para reutilizao. Em muitos casos, h um limite do sistema operacional para o nmero de arquivos abertos simultaneamente, assim, voc deve fechar um arquivo antes de abrir outro.

162/197

Fechando um Arquivo

A funo fclose() tem o seguinte prottipo: int fclose(FILE *fp); onde fp o ponteiro de arquivo devolvido pela chamada a fopen(). Um valor de retorno zero significa uma operao de fechamento bem sucedida. Qualquer outro valor indica um erro. A funo padro ferror() pode ser utilizada para determinar e informar qualquer problema. Geralmente, fclose() falhar quando um disco tiver sido retirado prematuramente do acionador ou no houver mais espao no disco.

163/197

Exemplo

Abrindo um Arquivo com Nome Fornecido

FILE *fp; char nome_arq[50]; printf("entre com o nome do arquivo\n"); scanf("%s", nome_arq); if((fp = fopen( nome_arq, "r")) == NULL ) { printf("Erro ao abrir o arquivo %s", nome_arq); exit(1); }

164/197

Exemplo

Lendo e Imprimindo um Arquivo Texto

#include <stdio.h> #define MAX 120 main() { FILE *fp; char nome_arq[50], linha[120]; printf("entre com o nome do arquivo\n"); scanf("%s",nome_arq); if((fp = fopen( nome_arq, "r")) == NULL ) { printf("Erro ao abrir o arquivo %s\n", nome_arq); exit(1); } while ( fgets(linha,MAX,fp) != NULL ) { printf("%s", linha ); } }

165/197

#include <stdio.h> main () { FILE *fp; char nome_arquivo[32]; double a; printf ("Informe o nome do arquivo: "); scanf ("%s", nome_arquivo); fp = fopen (nome_arquivo, "w"); printf ("Informe um numero (-999 para sair): "); scanf ("%lf", &a); while (a != -999) { fprintf (fp, "%10.4lf", a); printf ("Informe um numero (-999 para sair): "); scanf ("%lf", &a); } fclose (fp); fp = fopen (nome_arquivo, "r"); printf ("\n***** conteudo do arquivo criado ******\n"); while (fscanf (fp, "%lf", &a) != EOF) printf ("\n\t %lf", a); fclose (fp); }

166/197

#include <stdio.h> #include <stdlib.h> int main (void ) { int inum=10; float fnum=2.5; double pi=3.141516; char c='Z'; FILE *pa; char *nome = "texto.txt"; if (( pa = fopen(nome, "w+b")) == NULL) { printf("\n\nNao foi possivel abrir o arquivo para escrita.\n"); exit(1); } fwrite(&inum, sizeof(int), 1, pa); fwrite(&fnum, sizeof(float), 1, pa); fwrite(&pi, sizeof(double), 1, pa); fwrite(&c, sizeof(char), 1, pa); rewind(pa); fread(&inum, sizeof(int), 1, pa); fread(&fnum, sizeof(float), 1, pa); fread(&pi, sizeof(double), 1, pa); fread(&c, sizeof(char), 1, pa); printf("%d, %f, %lf, %c\n", inum, fnum, pi, c); fclose(pa); exit(0); }

167/197

Exemplos
#include <stdio.h> /* descrio de registro aleatrio - pode ser qualquer uma */ struct rec { int x,y,z; }; /* grava e depois l 10 registros arbitrrios do arquivo "junk". */ int main() { int i,j; FILE *f; struct rec r; /* cria o arquivo de 10 registros */ f=fopen("junk","w"); if (!f) return 1; for (i=1;i<=10; i++) { r.x=i; fwrite(&r,sizeof(struct rec),1,f); } fclose(f); //segue no prximo slide

168/197

/* l os 10 registros */ f=fopen("junk","r"); if (!f) return 1; for (i=1;i<=10; i++) { fread(&r,sizeof(struct rec),1,f); printf("%d\n",r.x); } fclose(f); printf("\n"); /* usa fseek para ler os 10 registros em ordem inversa */ f=fopen("junk","r"); if (!f) return 1; for (i=9; i>=0; i--) { fseek(f,sizeof(struct rec)*i,SEEK_SET); fread(&r,sizeof(struct rec),1,f); printf("%d\n",r.x); } fclose(f); printf("\n"); //segue no prximo slide

169/197

/* usa fseek para ler todo os outros registros */ f=fopen("junk","r"); if (!f) return 1; fseek(f,0,SEEK_SET); for (i=0;i<5; i++) { fread(&r,sizeof(struct rec),1,f); printf("%d\n",r.x); fseek(f,sizeof(struct rec),SEEK_CUR); } fclose(f); printf("\n"); /* usa fseek para ler o 4 registro, altere-o e escreva-o de volta */ f=fopen("junk","r+"); if (!f) return 1; fseek(f,sizeof(struct rec)*3,SEEK_SET); fread(&r,sizeof(struct rec),1,f); r.x=100; fseek(f,sizeof(struct rec)*3,SEEK_SET); fwrite(&r,sizeof(struct rec),1,f); fclose(f); printf("\n"); //segue no prximo slide

170/197

/* l os 10 registros para garantir que o 4 arquivo foi alterado */ f=fopen("junk","r"); if (!f) return 1; for (i=1;i<=10; i++) { fread(&r,sizeof(struct rec),1,f); printf("%d\n",r.x); } fclose(f); return 0; } //FIM

171/197

Exerccios
(1) Modifique o programa do slide 128, de modo a incluir duas novas opes no menu principal. Gravar Lista de Endereos em Arquivo e Recuperar Lista de Endereos de Arquivo. Implemente estas novas rotinas, sempre solicitando ao usurio que informe o nome do arquivo para cada operao. Faa testes manipulando tanto com arquivos binrios quanto com arquivos texto.

172/197

Alocao de Memria

"Alocao de memria" diz respeito a como a memria (necessria para o armazenamento dos dados) reservada em um programa Existem 2 formas de um programa em C alocar memria: Esttica Dinmica

173/197

Alocao Esttica

Ocorre na declarao de variveis globais e variveis locais; No caso de variveis globais e variveis locais estticas, o armazenamento fixo durante todo o tempo de execuo do programa; Variveis globais so alocadas em tempo de compilao; No caso de variveis locais, o armazenamento dura o tempo de vida da varivel.

174/197

Mapa de Memria
Memria do Sistema alta Pilha Memria Livre heap Variveis Globais Variveis Locais

Programa baixa

175/197

Alocao Dinmica

Para a alocao esttica, necessrio que se saiba de antemo (antes do incio do programa) a quantidade de memria que ser necessria; Estimativas podem ser feitas, porm h o risco de sub ou superestimar; Assim, muitas vezes necessrio que um programa possa ir ajustando a memria a ser usada durante sua execuo; "Ajustar" = alocar ou desalocar

176/197

Alocao Dinmica

Alocao dinmica o mtodo pelo qual um programa ajusta dinamicamente a quantidade de memria a ser usada durante sua execuo; Permite otimizar o uso da memria implementado mediante funes de alocao/liberao da memria, as quais o programador precisa usar de maneira coerente

177/197

Mapa de Memria
Memria do Sistema alta Pilha Memria Livre heap Variveis Globais Variveis Locais Variveis Alocadas Dinamicamente

Programa baixa

178/197

Alocao Dinmica

Principais funes C para alocao dinmica de memria: malloc e free; Implementadas na biblioteca stdlib.h H diversas outras funes mais especficas, as quais normalmente esto implementadas em stdlib.h

179/197

Exemplo - malloc

Serve para alocar memria; Devolve um ponteiro para o incio da quantidade de memria alocada; Exemplo: char *p; p=malloc(1000); O trecho acima aloca 1000 bytes de memria para o armazenamento de caracteres.

180/197

Porm: A memria ocupada por um determinado tipo pode variar de mquina para mquina! As implementaes devem ser independentes da mquina! Soluo: usar o operador sizeof

181/197

sizeof retorna o tamanho de uma varivel ou de um tipo sizeof funciona em tempo de compilao Exemplo de uso de sizeof:

float x; printf("um float ocupa %d bytes nesta maquina",sizeof(x)); printf("um int ocupa %d bytes nesta maquina", sizeof(int)); Para mais detalhes, veja o programa do slide 13.

182/197

int *p; p=malloc(50*sizeof(int)); Aloca memria suficiente para armazenar 50 inteiros (de maneira contgua na memria)

183/197

Porm, pode ser que o programa tenha alocado muita memria, a ponto de no restar espao na rea de heap (efetivamente, isto pode ocorrer); Se malloc no conseguir alocar memria, ele retornar um ponteiro nulo; Logo, preciso testar o resultado de malloc:
char *p; if( (p=malloc( 50*sizeof(char) ) ) == NULL ) { printf("No foi possivel alocar memoria\n"); exit(1); }

184/197

Exemplo - free

Libera memria previamente alocada de maneira dinmica, por meio de uma das funes de alocao dinmica (devolve memria ao "heap") Recebe como argumento um ponteiro para a poro de memria que se deseja liberar Jamais use free com um argumento invlido, pois isto destri a lista de memria livre!! free(p);

185/197

Exemplo - malloc
#include <stdio.h> #include <stdlib.h> main () { int n, i, *p, *inicio; printf ("Entre com o numero de elementos: \n"); scanf ("%d", &n); if ((p = malloc (n * sizeof (int))) == NULL) { printf ("No foi possvel alocar memria\n"); exit (1); } inicio = p; for (i = 0; i < n; i++, p++) { printf ("Entre com o %d valor: \n", i + 1); scanf ("%d", p); } p = inicio; for (i = 0; i < n; i++, p++) { printf ("%do. valor: %d\n", i + 1, *p); } }

186/197

Exemplo - realloc
#include <stdio.h> #include <stdlib.h> main() { int n, novo_n, adic, i, *p, *inicio; printf("Entre com o numero de elementos: \n"); scanf("%d", &n); if ((p = malloc(n * sizeof(int))) == NULL) { printf("No foi possvel alocar memria\n"); exit(1); } inicio = p; for (i = 0; i < n; i++, p++) { printf("Entre com o %d valor: \n", i + 1); scanf("%d", p); } p = inicio; for (i = 0; i < n; i++, p++) { printf("%do. valor: %d\n", i + 1, *p); }

187/197

printf("Entre com a quantidade de elementos adicionais: \n"); scanf("%d", &adic); novo_n = adic + n; p = inicio; p = realloc(p, (novo_n)); inicio = p; for (i = n; i < novo_n; i++) { printf("Entre com o %d valor: \n", i + 1); scanf("%d", &p[i]); } p = inicio; for (i = 0; i < novo_n; i++, p++) { printf("%do. valor: %d\n", i + 1, *p); } }

188/197

Operaes bit a bit


Operador & ! ^ ~ >> << AND OR XOR Complemento Deslocamento a esquerda Deslocamento a direita Ao

11000001 01111111 & 01000001 !

10000000 00000011 ^ 10000011

01111111 01111000 00000111

189/197

Exemplo
#include <stdio.h> main () { unsigned char x; x = 7; printf ("%d", x); x = x << 1; printf ("\n%d", x); x = x << 3; printf ("\n%d", x); x = x << 2; printf ("\n%d", x); x = x >> 1; printf ("\n%d", x); x = x >> 2; printf ("\n%d", x); x = ~x; printf ("\n%d", x); }
Sada: 7 14 112 192 96 24 231 (00000111) (00001110) (01110000) (11000000) (01100000) (00011000) (11100111)

x = x << 1; (multiplica x por 2) x = x >> 1; (divide x por 2)

190/197

Exemplo
#include <stdio.h> void main(void) { unsigned int i; int j; i=1; for (j=0; j<4; j++) { i = i << 1; printf("%d : %d\n", j, i); } for (j=0; j<4; j++) { i = i >> 1; printf("%d : %d\n", j, i); } }

191/197

Unies

Uma unio um tipo de dado que pode ser usado de muitas maneiras diferentes. Por exemplo, uma unio pode ser interpretada como sendo inteiro em uma operao e um float ou double em outra. Embora as unies possam tomar a aparncia de uma estrutura, elas so muito diferentes. Uma unio pode conter um grupo de muitos tipos de dados, todos eles compartilhando a mesma localizao na memria.

192/197

No entanto, uma unio s pode conter informaes de um tipo de dados de cada vez. Sintaxe: union nome_tipo { tipo var1; tipo var2; tipo var3; };

193/197

union varios_tipos { char c; int i; float f; double d; } tdata; Faz-se referncia aos membros da unio usando o operador ponto: tdata.d = 1.3;

194/197

Exemplo
#include <stdio.h> union varios_tipos { char c; int i; float f; double d; } tdata; void main(void) { tdata.c='b'; printf("%c\n", tdata.c); tdata.i=1234; printf("%d\n", tdata.i); tdata.f=12.34; printf("%f\n", tdata.f); tdata.d=123456.78E+12; printf("%lf\n", tdata.d); printf("\n%c\n", tdata.c); printf("%d\n", tdata.i); printf("%f\n", tdata.f); printf("%lf\n", tdata.d); printf("\nO tamanho desta unio : %d bytes.", sizeof(union varios_tipos)); }

195/197

Exemplo
#include <stdio.h> union varios_tipos { char c; int i; float f; double d; } tdata;

b 1234 12.340000 123456780000000000.000000

void main(void) { -1731184768 tdata.c='b'; printf("%c\n", tdata.c); -0.000000 tdata.i=1234; 123456780000000000.000000 printf("%d\n", tdata.i); tdata.f=12.34; O tamanho desta unio : 8 bytes. printf("%f\n", tdata.f); tdata.d=123456.78E+12; printf("%lf\n", tdata.d); printf("\n%c\n", tdata.c); printf("%d\n", tdata.i); printf("%f\n", tdata.f); printf("%lf\n", tdata.d); printf("\nO tamanho desta unio : %d bytes.", sizeof(union varios_tipos)); }

196/197

enum

Um tipo de dado enum permite criar um tipo de dado de sua escolha em itens. enum til quando a informao pode ser mais bem representada por uma lista, como por exemplo, de valores inteiros indicando o nmero de meses do ano ou o nmero de dias da semana.

197/197

Exemplo
#include <stdio.h> enum meses { janeiro = 1, fevereiro, marco, abril, maio, junho, julho, agosto, setembro, outubro, novembro, dezembro }; void main (void) { int mes_corrente; int soma, dif; enum meses fim; printf ("Digite o ms corrente (1 a 12): "); scanf ("%d", &mes_corrente); fim = dezembro; soma = (int) mes_corrente; dif = (int) fim - (int) mes_corrente; printf ("\n%d meses a menos, pois faltam %d para acabar este ano.\n", soma, dif);

Das könnte Ihnen auch gefallen