CodeGym /Cursos /C# SELF /Trabalhando avançado com arrays

Trabalhando avançado com arrays

C# SELF
Nível 7, Lição 2
Disponível

1. Array do tipo string

Então, rapidinho queria falar sobre array do tipo string.

Como já falamos, array pode ser de qualquer tipo. Ou seja, dá pra criar um array do tipo string. Olha como seria o código se a gente precisasse fazer um programa que "lê 10 strings do teclado e mostra elas na tela em ordem reversa".

string[] array = new string[10];	// Criando um array de 10 elementos
for (int i = 0; i < 10; i++)		// Loop de 0 até 9
{
   array[i] = Console.ReadLine();	// Lê uma string do teclado e salva no array
}
for (int i = 9; i >= 0; i--)		// Loop de 9 até 0
{
    Console.WriteLine(array[i]);	// Mostra na tela o próximo elemento do array
}

O código praticamente não mudou! Só teve que trocar o tipo int por string na hora de criar o array. O resto é tudo igualzinho!

2. Array do tipo string na memória

E mais uma parada útil. Bora ver 3 imagens:

Imagem 1. Como o objeto string fica na memória:

Array do tipo string na memória

Repara que o texto da string não fica direto na variável: ele ganha um bloco de memória separado. E na variável do tipo string fica só o endereço (referência) pro objeto com o texto.

Imagem 2. Como um array de inteiros fica na memória:

int array in memory

Tu já viu essa imagem também.

Imagem 3. Como um array de strings fica na memória:

How a string array is stored in memory

À esquerda a gente vê a variável-array do tipo string[] (guarda o endereço do objeto-array).
No meio — o objeto-array do tipo string.
E à direita — os objetos-string, que guardam os textos.

Nas células do objeto-array do tipo string não ficam as strings (textos) em si, mas sim os endereços (referências). Igualzinho como nas variáveis do tipo string ficam os endereços das strings (texto).

3. Inicialização rápida de array em C#

Arrays são muito úteis, então o pessoal do C# fez de tudo pra facilitar a vida com eles. E a primeira coisa que fizeram foi simplificar a inicialização do array, colocando valores iniciais direto.

Porque muitas vezes, além dos dados que o programa lê de algum lugar, ele também precisa de dados internos. Por exemplo, a gente precisa guardar no array os dias de cada mês. Como pode ficar esse código:

int[] months = new int[12];
months[0] = 31; // janeiro
months[1] = 28; // fevereiro
months[2] = 31; // março
months[3] = 30; // abril
months[4] = 31; // maio
months[5] = 30; // junho
months[6] = 31; // julho
months[7] = 31; // agosto
months[8] = 30; // setembro
months[9] = 31; // outubro
months[10] = 30; // novembro
months[11] = 31; // dezembro

Mas tem um jeito mais curto de escrever isso — valeu devs do C#:

// dias dos meses do ano
int[] months = new int[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

É só separar por vírgula todos os valores do array!

Bem prático, né? Mas ainda tem mais.

Pois é, o compilador consegue descobrir o tipo do array pelo tipo da variável. E pra saber o tamanho do array — só contar quantos elementos tem entre as chaves.

Por isso, dá pra escrever ainda mais curto:

// dias dos meses do ano
int[] months = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

Fala sério, ficou bonito, né? 🙂

Esse jeito se chama "inicialização rápida de array". E funciona não só pra int...

// nomes dos meses do ano
string[] months = { "Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"};

4. Loop foreach

Percorrer todos os elementos de um array é tão comum que criaram um loop só pra isso(!). Ele se chama foreach. E fica assim:


foreach (int score in scores)
{
    Console.WriteLine($"Pontos: {score}");
}
        
Percorrendo elementos do array com foreach

Aqui o loop já pega os elementos sozinho ― sem precisar de índice manual. Não dá pra mudar os elementos direto (eles só podem ser lidos no loop), mas é muito prático pra só "passar" pelo array.

O compilador transforma o código do foreach nesse aqui:


for (int i = 0; i < scores.Length; i++)
{
    int score = scores[i];
    Console.WriteLine($"Pontos: {score}");
}
        
Como o foreach funciona "por baixo dos panos"

Ou seja, nada de mágica. Agora dá pra entender porque não dá pra mudar os elementos do array pela variável score.

Bora fazer mais um exemplo: vamos achar a soma de todos os pontos.


int sum = 0;
foreach (int score in scores)
{
    sum += score;
}
Console.WriteLine($"Soma de todos os pontos: {sum}");
        
Somando elementos do array com foreach

Quando usar qual loop?

  • Se precisar do índice ou mudar elementos — usa o for.
  • Se só quiser passar pelos valores — foreach é mais rápido e limpo.

5. Indexação reversa: operador ^

De uns tempos pra cá no C# dá pra pegar elementos do fim do array. Antes, se tu queria o último elemento, tinha que escrever algo tipo:


int lastScore = scores[scores.Length - 1];
        
Pegando o último elemento do array do jeito antigo

Agora ficou bem mais fácil. Só botar o operador ^ antes do índice, e ele conta de trás pra frente:


int lastScore = scores[^1];        // Último elemento
int penultimate = scores[^2];      // Penúltimo elemento
        
Indexação reversa usando ^
  • ^1 — é o primeiro de trás pra frente (último).
  • ^2 — é o segundo de trás pra frente.

Visualização

Índice Valor no array scores Índice normal Índice reverso
0 10 0 ^5
1 15 1 ^4
2 8 2 ^3
3 22 3 ^2
4 17 4 ^1

score[^1] = 17, score[^2] = 22 — fácil e direto.

Importante! Repara que os índices reversos começam do 1, não do zero.

6. Ranges: operador .. (range)

Às vezes tu precisa pegar um subarray do array original. Em C# dá pra usar o operador de range .. — é um jeito curto e muito prático de pegar o "pedaço" que tu quer do array.

Esse subarray às vezes é chamado de slice (do inglês "slice"), e ele é definido por dois limites: início e fim.
Detalhe importante: o limite direito não entra no resultado!

Como fica isso


int[] scores = { 10, 15, 8, 22, 17 };
int[] top3 = scores[0..3]; // Pega os elementos do 0 ao 2: {10, 15, 8}
        
Pegando um slice do array com ..

  • scores[0..3] — pega os elementos do índice 0 (incluindo) até o índice 3 (NÃO incluindo).
  • O array final vai ter os elementos dos índices 0, 1 e 2.

Atalhos

Se não colocar o limite esquerdo, pega desde o começo:


int[] firstTwo = scores[..2]; // igual a scores[0..2], ou seja {10, 15}
        

Se não colocar o limite direito, pega até o fim:


int[] fromThird = scores[2..]; // {8, 22, 17}
        

Índices negativos

Com o símbolo ^ dá pra contar índices de trás pra frente:


int[] lastTwo = scores[^2..]; // {22, 17}
        

Aqui ^2 — é o "segundo elemento de trás pra frente".

Também dá pra pegar um range "de tal a tal", usando índices negativos dos dois lados:


int[] mid = scores[1..^1]; // {15, 8, 22} (do segundo até o penúltimo)
        

O que lembrar

  • O limite direito nunca entra — ou seja, se tu escreve a..b, pega todos os elementos de a até b-1.
  • Se botar limites fora do array, vai dar IndexOutOfRangeException.
  • Slice — é um novo array, o original não muda. Qualquer mudança no novo array não afeta o original.

Exemplos práticos

int[] arr = { 1, 2, 3, 4, 5, 6, 7 };
int[] arr = { 1, 2, 3, 4, 5, 6, 7 };

int[] start = arr[..3];      // {1, 2, 3}
int[] end = arr[^2..];       // {6, 7}
int[] middle = arr[2..5];    // {3, 4, 5}
int[] all = arr[..];         // {1, 2, 3, 4, 5, 6, 7} (cópia completa)
2
Tarefa
C# SELF, nível 7, lição 2
Bloqueado
Usando indexação reversa e ranges
Usando indexação reversa e ranges
2
Tarefa
C# SELF, nível 7, lição 2
Bloqueado
Reverso de array de strings e slices
Reverso de array de strings e slices
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION