1
Técnicas de Programação:
Técnicas
de Programação:
STRINGS, MATRIZES e PONTEIROS
Prof. Protásio
Prof.
Protásio
DEE‐UFPB
2
String
• É uma coleção de variáveis do tipo char.
• É um vetor de caracteres.
É
• Exemplo:
char nome[80];
char endereco[100];
char CEP[9];
3
Atribuições em STRINGs
• Atribuição na criação:
char S[4] = {'u', 'f', 'p', 'b'};
•Atribuição após a criação:
char
S[0]
S[1]
S[2]
S[3]
S[4];
= 'u';
= 'f';
f
= 'p';
= 'b';
4
Atribuições em STRINGs
• Considere
char S[4] = {'u', 'f', 'p', 'b'};
• Estaria
sta a correto?
co eto?
printf("%s", S);
• É necessário "fechar" (delimitar)
g
a string.
char
h
S[5] = {'
{'u',
' 'f'
'f', '
'p',
' 'b'
'b', '\0'}
'\0'};
printf("%s", S);
5
Atribuições em STRINGs
• Para evitar ter que contar sempre os caracteres, é possível fazer:
possível fazer:
char S[] = "ufpb";
printf("%s", S);
6
Ponteiro para STRINGs
• Criação de um ponteiro para String:
char *P;
•É possível fazer?
•É possível fazer?
P[0] = 'u';
P[0] u;
NÃO
P[1] = 'f';
etc.
•Pois a criação de ponteiros não alocar espaço P i
i ã d
t i
ã l
de memória. •Ocorre erro de execução.
7
Ponteiro para STRINGs
•É possível fazer?
char *P = "Isso eh um teste";
•SIM
SIM
Qual a quantidade de posições
alocadas aqui?
•Mas, em C, NÃO se pode fazer futuras
atribuições.
atribuições
[ ]
;
P[0] = 'i'; 8
Funções que usam Strings (string.h)
• STRCPY – Copia o conteúdo de uma string em outra
Copia o conteúdo de uma string em outra
char * strcpy ( char * destination, char * source );
• Exemplo
#include <stdio.h>
#include <string.h>
int main () {
char str1[]="Sample string";
char str2[40];
char str3[40];
strcpy (str2,str1);
strcpy (str3,"copy successful");
printf ("str1: %s\nstr2: %s\nstr3:%s\n",str1,str2,str3);
return 0;
}
9
Funções que usam Strings (string.h)
• STRCAT – Concatena o conteúdo de uma string em outra
Concatena o conteúdo de uma string em outra
char * strcat ( char * destination, char * source );
• Exemplo
#include <stdio.h>
#include <string.h>
int main () {
char str[80];
strcpy (str,"these ");
strcat (str,"strings ");
strcat (str,"are ");
strcat (str,"concatenated.");
printf (str);
return 0;
}
10
Funções que usam Strings (string.h)
• STRLEN
– Retorna o tamanho de uma string
R
h d
i
size_t strlen (char * str );
• Exemplo
#include <stdio.h>
#include <string.h>
int main () {
char szInput[256];
printf ("Enter a sentence: ");
gets ((szInput);
g
p );
printf ("The sentence entered is %u characters long.\n",strlen(szInput));
return 0;
}
11
Funções que usam Strings (string.h)
• STRCMP – Compara duas strings
Compara duas strings
int strcmp (char * str1, char * str2 );
– Retorna: 0 +1 se str1 == str2
(
(todos os caracteres forem iguais)
g
)
se str1 > str2
(procura até encontrar o primeiro caractere (p
ocu a até e co t a o p e o ca acte e
diferente. Se este for maior, em valor ASCII, então a string é considerada maior)
‐1 1
se str1 < str2
t1 t2
(procura até encontrar o primeiro caractere diferente. Se este for menor, em valor ASCII, então a string é
diferente. Se este for menor, em valor ASCII, então a string é considerada menor)
12
Funções que usam Strings (string.h)
• EXEMPLO char senha[] = "ufpb";
char entrada[] = "ufpb";
int c;
c = strcmp (senha, entrada);
• Resultaria em c = 0;
char senha[] = "ufpb";
char entrada[] = "Ufpb";
int c;
c = strcmp (senha, entrada);
• Resultaria em c = +1;
13
Funções que usam Strings (string.h)
• EXEMPLO
#include <stdio.h>
#include <string.h>
int main () {
char szKey[] = "apple";
char
h szInput[80];
I
t[80]
do {
printf ("Guess my favourite fruit? ");
gets (szInput);
} while (strcmp (szKey,szInput)
(szKey szInput) != 0);
puts ("Correct answer!");
return 0;
}
14
Exercício
• Faça um programa em C que dê entrada a uma senha de 8 caracteres do usuário e verifique se
senha de 8 caracteres do usuário e verifique se contem somente letra minúsculas.
• Faça
Faça um programa em C que dê entrada a 3 um programa em C que dê entrada a 3
nomes de pessoas e os envie para a tela em ordem alfabética.
d
lf bé i
15
Matrizes
• Uma matriz é uma coleção de variáveis do
mesmo tipo que são referenciadas por um nome
comum.
• Matrizes unidimensional
Matrizes unidimensional
tipo
nome_var[tamanho];
• Exemplos:
char nome[80];
i t fluxo[21];
int
fl [21]
16
Tamanho de uma matriz
• Como calcular o tamanho em bytes que uma matriz conterá?
matriz conterá?
total_de_bytes = sizeof(tipo base) * tamanho
• Exemplos:
int tamanho;
char nome[10];
(
)
;
tamanho = sizeof(char)*10;
int fluxo[2];
tamanho = sizeof(int)*2;
17
Gerando um ponteiro para uma matriz int amostra[10];
int *p;
p = amostra;
ou
p = &amostra[0];
18
Matrizes bidimensionais
• É uma matriz de matrizes unidimensionais
tipo nome_da_matriz[quant_linha][quant_coluna];
•Exemplo int d[10][20]
19
Passando Matrizes bidimensionais para Funções
void func1(int d[][20])
{
:
}
– É necessário definir a segunda dimensão (a primeira não!!)
– O compilador precisa conhecer a segunda dimensão para O compilador precisa conhecer a segunda dimensão para
poder trabalhar com comandos como d[2][4].
– Se o número de colunas não for conhecido, é impossível p
saber onde a próxima linha se inicia.
20
Matrizes de Strings
• Declaração de uma matriz de 30 strings:
char
c
a matriz
at
_st
str[30][80];
[30][80];
• Acessar uma string individual
gets(matriz str[2]);
gets(matriz_str[2]);
ou
gets(&matriz_str[2][0]);
21
Matrizes Multidimensionais
• Declaração
tipo nome[tamanho_N]... [tamanho_2] [tamanho_1];
• Exemplo
int m[4][3][6][5];
• Passando uma MM para uma função
int funcao(int m[][3][6][5]){
:
}
22
Indexando Ponteiros
• Ponteiros e matrizes são relacionados em C.
• O nome de uma matriz sem um índice é um O nome de uma matriz sem um índice é um
ponteiro para o primeiro elemento da matriz.
char p[10];
p == &p[0]
•Um
Um ponteiro pode ser indexado como uma matriz ponteiro pode ser indexado como uma matriz
int *p, i[10];
p = i;
•Atribuições podem ser:
p[5]
[5] = 100
100;
OU
Aritmética de *(p+5) = 100;
ponteiros
23
Inicialização de Matrizes
int i[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
char str[4] = "Ola";
Ola ;
OU
char str[4] = {'O', 'l', 'a', '\0'};
24
Inicialização de Matrizes
int qdrs[10][2] = {
1 1
1,
1,
2, 4,
3 9
3,
9,
4, 16,
5, 25,
6, 36,
7, 49,
8 64
8,
64,
9, 81,
10, 100,
};
25
Inicialização de Matrizes
int qdrs[10][2] = {
{1 1}
{1,
1},
{2, 4},
{3 9}
{3,
9},
{4, 16},
{5, 25},
{6, 36},
{7, 49},
{8 64}
{8,
64},
{9, 81},
{10, 100},
};
26
Ponteiros
• Um ponteiro contém um endereço de memória.
• Em geral, o ponteiro contém um endereço de é
uma outra variável na memória
.
.
.
int num = 100;
2000
int *p, *q;
p = #
q = *p;
.
.
.
27
Ponteiros
• Operadores
– &
: operador unário que retorna endereço de d
ái
d
d
uma variável. "endereço de"
p = #
– *
: operador unário que retorna o valor da variável localizada em um ponteiro. "no endereço de".
q = *p;
p;
28
Tipo base
• Define para quais tipos de variável o ponteiro pode apontar
pode apontar.
• Tecnicamente, qualquer tipo de ponteiro pode apontar para qualquer lugar da memória.
• Toda a aritmética de ponteiro é feita com relação Toda a aritmética de ponteiro é feita com relação
ao tipo base.
29
Tipo base
• Qual o retorno do programa abaixo?
#include <stdio.h>
int main () {
double x,y;
int *p;
x = 100.23;
p = &x;
y = *p;
printff ("%f",
(" f" y);
)
return 0;
}
/* isto eh errado*/
30
Expressões com Ponteiros
• Somente duas: adição e subtração.
.
.
.
i t *p;
int
*
p = 2000
Se p = 2000
p++;
.
.
.
Se p = 2000
p ;
p--;
31
Expressões com Ponteiros
• Adição e subtração com inteiros
.
.
.
i t *p;
int
*
p = 2000
Se p = 2000
p = p + 4;
.
.
.
32
Expressões com Ponteiros
• Subtração de ponteiros (adição não pode)
.
.
.
int *p,
*p *q;
S p = 2000
Se
e
q = 2010
int faixa = p - q;
p = 2000
.
.
.
A subtração resulta no número de
elementos do tipo
p base q
que separam
p
os
dois valores ponteiros.
33
Visualização da aritmética X tipo base
char *ch = 3000;
int *i = 3000;
.
.
.
ch
ch+1
ch+2
ch+3
ch+4
ch+5
ch+6
ch+7
i
i+1
i+2
i+3
i+4
i+5
i+6
.
.
.
34
Comparação entre ponteiros
int *p, *q;
if(p<q)
(p q)
p
printf("p
t ( p apo
aponta
ta pa
para
a u
um
endereço menor que q\n");
35
Ponteiros const
• const = qualificador usado para criar variáveis que não podem ser alteradas
não podem ser alteradas.
• Ponteiros especificados como const não podem ter os dados apontados modificados
ter os dados apontados modificados.
• Exemplo:
36
#include <stdio.h>
void espaço_para_traco(const char *str);
int main () {
espaço_para_traco("Isto eh um teste");
return 0;
}
void espaço
espaço_para_traco(const
para traco(const char *str)
{
while(*str){
if(* t == ' ')
if(*str
*str = '-';
printf("%c", *str);
str++;
}
}
Ops!
37
#include <stdio.h>
void espaço_para_traco(const char *str);
int main () {
espaço_para_traco("Isto eh um teste");
return 0;
}
void espaço
espaço_para_traco(const
para traco(const char *str)
{
while(*str){
if(* t == ' ')
if(*str
printf("%c", '-');
else
printf("%c", *str);
str++;
}
}
OK!
38
Matrizes de Ponteiros
• Ponteiros podem ser alocados em matrizes como qualquer outro tipo de dado
qualquer outro tipo de dado.
• Exemplo
int *x[10];
int var = 21;
– Para atribuir o endereço de var ao terceiro elemento d
da matriz:
ti
x[2] = &var;
– Para retornar o valor de var:
temp
p = *x[2];
[ ];
39
Passando matrizes de ponteiros a uma função
void exibe_matriz(int *q[]){
int t;
for (t=0; t<10; t++)
printf("%d ",
" *q[t])
}
40
Uso comum: matriz de ponteiro para armazenar mensagem de erros
void
id saierro(int
i
(i t num){
){
static char *erro[] = {
" ã f
"não
foi
i possivel
i l abrir
b i o arquivo\n",
i \ "
"Erro de leitura\n",
"Erro de escrita\n",
\
"Erro na Midia\n"
};
printf("%s", erro[num]);
return;
}
41
Ponteiro para ponteiro
float *x;
Ponteiro
Variável
endereço
valor
float **x;
x;
Ponteiro
Ponteiro
Variável
endereço
endereço
valor
42
Exemplo
#include <stdio.h>
int main () {
i x, *p,
int
* **q;
**
x = 10;
p = &x;
q = &p;
p;
printf("%d", **q);
}
return 0;
43
Inicializando ponteiros
• Ponteiros não‐inicializados podem causar sérios problemas (travamento etc )
problemas (travamento, etc.)
• Por convenção, um ponteiro que não está inicializado pode receber o valor null
inicializado pode receber o valor null.
44
Inicializando ponteiros
• Exemplos de inicialização
char *p
p = "Oi,
, tudo bem ai?\n";
\ ;
int *q = &x;
45
Exercício 1
• Faça um programa em C que leia um vetor de inteiros positivos e envie para a tela quantas
inteiros positivos e envie para a tela quantas vezes aparecem números pares. – Obs: • o vetor terá no máximo 100 posições. • Sair do programa quando for digitado ‐1.
• Imprimir o vetor ao final.
p
46
Exercício 2
• Faça um programa em C que leia um vetor de floats e envie para a tela os valores e envie para a tela os valores
correspondentes em inteiro.
– Obs: • o vetor terá no máximo 100 posições. • Sair do programa quando for digitado ‐1.
• Imprimir o vetor ao final.
p
47
Ponteiros para função
• Toda função tem um uma posição física de memória que pode ser atribuída a um ponteiro
memória que pode ser atribuída a um ponteiro.
• Assim, um ponteiro de função pode ser usado para chamar a função.
48
Ponteiros para função
• Em C, pode‐se declarar um ponteiro para função com a sintaxe
void (*f)();
• f é um ponteiro para uma função sem parâmetros.
• Suponha que se tenha uma função como abaixo
S
h
h
f ã
b i
void teste() {
printf("Prestem atencao!\n");
}
• f = &teste;
• Forma de chamar a função teste
(*f)();
/* chama teste*/
49
Ponteiros para função com parâmetros
int (*calc)(int x);
• f é um ponteiro para uma função.
f é um ponteiro para uma função
• Suponha que se tenha uma função como abaixo
int inc(int x) {
return x++;
;
}
• calc = &inc;
• Formas
Formas de chamar a função teste
de chamar a função teste
(*calc)(3);
/* chama inc*/
50
#include
#include
#include
#include
<stdlib.h>
<stdio.h>
<conio.h>
<strings.h>
void inserir(void), excluir(void), revisar(void), sair(void);
void (*opcoes[])(void) = {&inserir, &excluir, &revisar, &sair};
int main(void) {
int i;
i = getche(); /* Le a escolha do usuario */
(*opcoes[i])();
}
return 0;
/* Executa-a */
51
#include <stdlib.h>
#include <stdio.h>
void mais(void), menos(void);
void (*opcoes[])(void) = {&mais, &menos};
void (*calc)();
int main(void) {
int i;
i = getche()-48; /* Le a escolha do usuario */
(opcoes[i])();
/* Executa-a */
calc = mais;
(*calc)();
system("PAUSE");
return 0;
}
void mais(void){
printf("mais\n");
}
void menos(void){
printf("menos\n");
}
/* Executa-a */
52
Problemas com ponteiros
• Exemplo clássico 1
int main () {
int x, *p;
x = 10;
*p = x;
return 0;
}
/* Ponteiro não-inicializado */
53
Problemas com ponteiros
• Exemplo clássico 2
int main () {
int x, *p;
x = 10;
p = x;
return 0;
}
/* Operação inadequada */
54
Alocação Dinâmica de Matrizes
• Existem programas que não se pode saber antecipadamente o tamanho necessário de uma
antecipadamente o tamanho necessário de uma matriz.
– Exemplos: banco de dados, editores de textos, etc.
• O
O que se pode fazer?
que se pode fazer?
1. Alocar um número muito grande de elementos. l
2.Alocar memória na execução do programa ou ç
p g
alocar dinamicamente memória.
55
Alocação Dinâmica de Matrizes
• Para alocar dinamicamente matrizes usam‐se:
– malloc()
• Aloca memória e retorna um ponteiro para o início dela
– free()
• Libera a memória anteriormente alocada.
• P
Protótipos
tóti
void *malloc(size_t num_bytes);
void free(void *p);
Em
stdlib.h
56
Alocação Dinâmica de Matrizes
• Exemplo
– Alocando 1000 bytes de memória
Al
d 1000 b
d
ói
char *p;
p = malloc(1000);
malloc(1000)
– Se p não for alocado, é retornado NULL
– Liberando
free(p);
57
#include <stdio.h>
#i l d <stdlib.h>
#include
tdlib h
int main () {
int i,n;
char * buffer;
printf (("How long
p
g do y
you want the string?
g ");
);
scanf ("%d", &i);
buffer = (char*) malloc (i+1);
if (buffer==NULL) exit (1);
for (n=0; n<i; n++)
buffer[n]=rand()%26+'a';
buffer[i]='\0';
}
printf ("Random string: %s\n",buffer);
free (buffer);
return 0;
58
Exercícios
• Faça um programa que utilize uma matriz de ponteiro de função para executar as funções:
ponteiro de função para executar as funções:
– Soma
– Subtração
– Multiplicação
– Divisão