Uma coleção de resumos, para ajudar os que precisam daquele empurrão.
Arrays as estruturas de dados mais simples (a seguir a tipos primitivos) a que temos acesso em C e muitas outras linguagens imperativas.
Consistem numa lista de tamanho estático onde podemos guardar elementos de um determinado tipo.
int array[10];
Acima está declarado um array de inteiros com 10 posições. Tal como as variáveis têm valores aleatórios quando não são inicializadas os arrays seguem o mesmo padrão. Não sabemos portanto que valores estão no array.
Em C
podemos declarar e inicializar um array de inteiros estático (iremos falar de arrays dinâmicos mais à frente) de 3 maneiras:
int array[] = {0,0,0,0};
int array[4] = {0};
int array[4];
int i;
for(i = 0; i < 4; i++){
array[i] = 0;
}
Todos este exemplos produzem um array de 4 posições todas a 0.
De notar que todos estes métodos são equivalentes em termos de eficiência. De qualquer forma o PC tem de ir a todas as células e alterar o valor. Quer esse comportamento seja declarado explícita ou implicitamente
Isto é bastante simples, aliás já fiz uso desta syntax na secção anterior.
int x = array[0];
guarda na variável x
o valor que está na posição 0
do array.
array[0] = x;
guarda na posicão 0
do array o valor do x
Os índices válidos de um array são o conjunto dos números inteiros desde 0
até ao seu tamanho menos 1, ou seja,
para o array da secção anterior (int array[4]
) os índices válidos são 0,1,2,3.
Apesar da simplicidade desta funcionalidade, é no uso desta que acontece a maior parte dos erros! Se acedermos
a um índice maior ou igual ao tamanho do array ou negativo estamos a aceder a memória para a qual não temos autorização
e o programa “crasha” indicando o famoso segmentation fault
.
Passar um array a uma função é relativamente simples
// funcao que recebe um array
void func(int array[], int N){
/* code */
}
int main(){
int array[4] = {0};
func(array,4);
}
Nota que passei também o tamanho do array. Isto é bastante habitual visto que em C não é possível saber o tamanho de um
array apenas percorrendo-o, temos então que “tomar conta” deste valor para evitar incorrer numa segmentation fault
.
Outro promenor importantíssimo é que, ao contrário de variáveis de tipos primitivos, alterar um array dentro de uma função também o altera fora da função.
Por exemplo, o seguinte código,
void func(int array[], int N){
array[0] = 1;
N = 2;
}
int main(){
int array[4] = {0};
int n = 4;
printf("Before: array[0] == %d and n == %d\n", array[0], n);
func(array,n);
printf("After: array[0] == %d and n == %d\n", array[0], n);
return 0;
}
produz o seguinte output
Before: array[0] == 0 and n == 4
After: array[0] == 1 and n == 4
Isto deve-se ao facto de o array ser na verdade um apontador para memória. Conceito que será abordado mais à frente.
As strings em C são um caso particular dos arrays. Têm todas as propriedades de um array mas acrescentam algumas.
char string[] = "Hello\n";
Podem ser declaradas desta forma (similar à primeira que vimos para o array de inteiros) inicializado-o com uma string estática, no entanto, este array (ou string) é null terminated. Ou seja, o último caracter da string é um ‘\0’.
Conteudo da string/array
string[0] == 'H';
string[1] == 'e';
string[2] == 'l';
string[3] == 'l';
string[4] == 'o';
string[5] == '\n';
string[6] == '\0';
Isto permite-nos saber o comprimento da string “apenas olhando para ela”
int strlen(char string[]){
int i = 0;
while(string[i]!='\0'){
i++;
}
return i;
}
Temos então aqui uma definição da strlen
. Uma função que retorna o comprimento de uma string.