Escolar Documentos
Profissional Documentos
Cultura Documentos
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
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
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
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
31/197
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
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
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
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
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
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
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", ¬a[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", ¬a[i]); }
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};
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;
57/197
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
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
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
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
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
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
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]);
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
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
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
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
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.
108/197
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
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)); }
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
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)
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
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
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
#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
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)
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;
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);