Programação II Strings e Vetores de Ponteiros · Vetor (array) de caracteres • Exemplo de um...
-
Upload
truongxuyen -
Category
Documents
-
view
218 -
download
0
Transcript of Programação II Strings e Vetores de Ponteiros · Vetor (array) de caracteres • Exemplo de um...
Programação II
Strings e Vetores de Ponteiros
Bruno Feijó
Dept. de Informática, PUC-Rio
Vetor (array) de caracteres
• Exemplo de um vetor de 3 caracteres
• Os elementos do vetor estão em endereços contíguos de memória
• Podemos definir um ponteiro para um vetor
• Note que *p, *(p+1) e *(p+2) são os valores ‘p’, ‘u’ e ‘c’
• Note que são equivalentes: *(p+2) p[2] *(a+2)
• p++; está correto, mas a++; e a = p; não !! (pois nome de
vetor não é variável). Array não é ponteiro !!!
• Defina void f(char * a) ao invés de void f(char a[])
char a[3];
a[0] = 'p';
a[1] = 'u';
a[2] = 'c';
char a[3] = {'p','u','c'}; ou
p
a
endereços
u c
101 102 103
p
a
u c
101 102 103 char * p;
p = &a[0];
char * p;
p = a;
p ou
a é o mesmo que
&a[0], i.e. o endereço
do 1o. elemento
String (Cadeia de Caracteres)
• Um string é um vetor de caracteres com um terminador
– o terminador é o caractere '\0' cujo valor numérico é 0
– maneiras de definir um string:
– Na memória:
• Escrever funções que manipulam strings é basicamente passear
com o ponteiro e interromper quando o terminador é encontrado.
Veja o exemplo a seguir.
char * a = "puc";
char a[] = "puc";
char a[4] = {'p','u','c','\0'};
usando ponteiro:
ou
p
a
u c
201 202 203 204
\0
OBS: se você usar printf("abcdef\0gh\n"); a impressão ignora g, h e \n:
abcdef
como array:
p
a
u c
201 202 203 204
\0
usando ponteiro: como array:
Array (Vetor) Bidimensional
Array Bidimensional
Quando o array é de uma unica dimensão, as facilidades são muitas e
terminam fazendo a gente se esquecer de que são entidades diferentes e
de que o compilador as trata de maneira diferente.
Aritmética de ponteiro e indexação de array são equivalentes em C, mas
ponteiros e arrays são diferentes !
Quando a gente tem um ARRAY BIDIMENSIONAL b como argumento de uma
funcao g, por exemplo:
char b[3][15] = {"abc","a","cd"};
g(b,3);
A função g deve ser:
void g(char b[][15], int n) {...}
ou
void g(char (*b)[15], int n) {...}
Ou seja, temos que saber o numero de colunas (fazer uma função que
independa de saber o numero de colunas é complicado !)
Vetor de Ponteiros
Array Bidimensional
Quando a gente não quer desperdicar memória (no caso acima, "abc" gastou apenas 4
dos 15 que tinha direito) usamos um VETOR DE PONTEIROS para strings. Neste caso, o
vetor de ponteiros b como argumento de uma função g poderia ser o seguinte:
char * b[] = {"abc","a","cd"};
g(b,3);
Neste caso, a função g deve ser:
void g(char ** b, int n) {...}
A diferença é que agora temos "ponteiro" e não "array"!
Melhor mesmo é quando a gente tem tudo como ponteiros ("melhor" no sentido de que
fica tudo dinâmico e sob total controle nosso):
char ** b;
b = (char **)malloc(3*sizeof(char *));
b[0] = (char *)malloc(strlen("abc")+1);
strcpy(b[0],"abc");
b[1] = (char *)malloc(strlen("a")+1);
strcpy(b[1],"a");
...
g(b,3);
E, neste caso, a função g é igual à anterior:
void g(char ** b, int n) {...}
Toda a Matriz como Vetor de Ponteiros
Exercício
Crie um projeto chamado senhas, dentro de uma solução (solution) chamada
vetorDePonteiros, contendo os arquivos main.c, senhas.c e senha.h (ver Fig. 1). Na função
main(), você deve:
[1] criar estaticamente (i.e. sem usar malloc) um vetor de ponteiros para strings char *
senhas1[] onde senhas1[0] é “12345” e senhas1[1] é “67890”;
[2] criar dinamicamente (usando malloc) um vetor de ponteiros do tipo char ** senhas2 onde
senhas2[0] é “a3;fre” e senhas2[1] é “asf35tWh” e de maneira que estes strings também são
alocados dinamicamente.
[3] imprimir senhas1 e senhas2 usando a função printsenhas que recebe string senhas e seu
tamanho;
[4] liberar todas as memórias (usando free).
Atenção: primeiro libere as memórias que contem os strings e depois a memória do vetor de
ponteiros.
Gabarito do Exercício
Vetores de Ponteiros de Estrutura
Arrays (vetores) de Ponteiros para Estruturas
...
#define N 3
int main(void)
{
Aluno * v[N];
...
for (i=0;i<N;i++)
lê matrícula, ano, semestre, nome
chama função que cria aluno e retorna valor para v
imprime v
libera memória (e exibe mensagem) return 0;
}
Aluno v[N];
Gastaria os bytes relativos a mat,
nome e AnoRef
Ponteiros são mais eficientes !
mat
nome
AnoRef ano
semestre
Aluno ** v;
Requereria alocação dinâmica
Como ficaria a liberação de memória ?
... faça depois esta opção