Manipulação de Arrays e Strings em C: Memória, Algoritmos e Conversões

A compreensão de como a linguagem C gerencia arrays e strings na memória é fundamental para o desenvolvimento de software eficiente. Este artigo explora a organização de dados em memória, técnicas de manipulação de strings e algoritmos clássicos aplicados a estruturas unidimensionais e multidimensionais.

1. Organização de Arrays na Memória

Arrays em C são armazenados em blocos contíguos de memória. Em um array unidimensional, os elementos seguem uma sequência linear. Já em arrays multidimensionais, o C utiliza a ordem row-major (armazenamento por linhas).

#include <stdio.h>

#define TAMANHO 4

void analisar_vetor_int() {
    int numeros[TAMANHO] = {10, 20, 30, 40};
    printf("Bytes ocupados pelo array: %zu\n", sizeof(numeros));

    for (int i = 0; i < TAMANHO; ++i) {
        printf("Endereco: %p | Valor: %d\n", (void*)&numeros[i], numeros[i]);
    }
    printf("Endereco base (nome do array): %p\n", (void*)numeros);
}

void analisar_vetor_char() {
    char letras[TAMANHO] = {'A', 'B', 'C', 'D'};
    printf("Bytes ocupados pelo array: %zu\n", sizeof(letras));

    for (int i = 0; i < TAMANHO; ++i) {
        printf("Endereco: %p | Valor: %c\n", (void*)&letras[i], letras[i]);
    }
}

int main() {
    analisar_vetor_int();
    analisar_vetor_char();
    return 0;
}

Ao observar os endereços de memória, nota-se que para int (geralmente 4 bytes), os endereços saltam de 4 em 4. Para char (1 byte), a sequência é unitária. O nome do array atua como um ponteiro para o primeiro elemento.

2. Arrays Bidimensionais e Aritmética de Endereços

Em matrizes, a memória continua sendo linear. O endereço de matriz[1][0] segue imediatamente o último elemento da primeira linha matriz[0][M-1].

#include <stdio.h>

#define LINHAS 2
#define COLUNAS 3

void explorar_matriz() {
    int grade[LINHAS][COLUNAS] = {{1, 2, 3}, {4, 5, 6}};
    
    for (int i = 0; i < LINHAS; i++) {
        for (int j = 0; j < COLUNAS; j++) {
            printf("[%d][%d] em %p\n", i, j, (void*)&grade[i][j]);
        }
    }
    
    printf("grade: %p\ngrade[0]: %p\ngrade[1]: %p\n", (void*)grade, (void*)grade[0], (void*)grade[1]);
}

3. Permutação de Strings

Para trocar o conteúdo de duas strings, é necessário utilizar uma área de armazenamento temporária, já que strings em C são arrays de caracteres e não podem ser atribuídas diretamente com o operador =.

#include <stdio.h>
#include <string.h>

void trocar_strings(char str_a[], char str_b[]) {
    char buffer[100];
    strcpy(buffer, str_a);
    strcpy(str_a, str_b);
    strcpy(str_b, buffer);
}

int main() {
    char s1[100] = "Texto Alpha";
    char s2[100] = "Texto Beta";
    
    trocar_strings(s1, s2);
    printf("S1: %s\nS2: %s\n", s1, s2);
    return 0;
}

4. Processamento de Texto: Contagem e Busca

Abaixo, um exemplo de como processar uma string para contar palavras e identificar a maior delas com base em delimitadores de espaço.

#include <stdio.h>
#include <string.h>

void identificar_maior_palavra(char texto[]) {
    int i = 0, atual_len = 0, max_len = 0, pos_final = 0;
    
    while (1) {
        if (texto[i] == ' ' || texto[i] == '\0') {
            if (atual_len > max_len) {
                max_len = atual_len;
                pos_final = i;
            }
            atual_len = 0;
            if (texto[i] == '\0') break;
        } else {
            atual_len++;
        }
        i++;
    }

    printf("Maior comprimento: %d. Palavra: ", max_len);
    for (int j = pos_final - max_len; j < pos_final; j++) {
        putchar(texto[j]);
    }
    putchar('\n');
}

5. Conversão de Base Numérica

Utilizando arrays para armazenar restos de divisões sucessivas, podemos converter números decimais para outras bases (binária, octal ou hexadecimal).

#include <stdio.h>

void converter_base(int decimal, int base) {
    char simbolos[] = "0123456789ABCDEF";
    char resultado[64];
    int indice = 0;

    if (decimal == 0) {
        printf("0\n");
        return;
    }

    while (decimal > 0) {
        resultado[indice++] = simbolos[decimal % base];
        decimal /= base;
    }

    for (int i = indice - 1; i >= 0; i--) {
        putchar(resultado[i]);
    }
    putchar('\n');
}

6. Ordenação e Estatística em Vetores

O algoritmo Bubble Sort é uma técnica comum para ordenar elementos. Combinado com funções de entrada e saída, permite gerenciar cnojuntos de dados numéricos.

#include <stdio.h>

void ordenar_decrescente(int dados[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (dados[j] < dados[j + 1]) {
                int temp = dados[j];
                dados[j] = dados[j + 1];
                dados[j + 1] = temp;
            }
        }
    }
}

float calcular_media(int dados[], int n) {
    float soma = 0;
    for (int i = 0; i < n; i++) soma += dados[i];
    return soma / n;
}

7. Rotação de Matrizes

Operações em matrizes podem incluir transformações geométricas ou deslocamentos. O exemplo a seguir demonstra o deslocamento cíclico das colunas de uma matriz para a direita.

#include <stdio.h>
#define N 4

void rotacionar_colunas(int mat[N][N]) {
    for (int i = 0; i < N; i++) {
        int ultimo = mat[i][N - 1];
        for (int j = N - 1; j > 0; j--) {
            mat[i][j] = mat[i][j - 1];
        }
        mat[i][0] = ultimo;
    }
}

void exibir_matriz(int mat[N][N]) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            printf("%3d ", mat[i][j]);
        }
        printf("\n");
    }
}

Tags: linguagem C Gestão de Memória Algoritmos Estruturas de Dados manipulação de strings

Publicado em 8-4 00:32