Manipulação de Strings em C: Funções com Limite, Busca e Tratamento de Erros

strncpy

char *strncpy(char *destination, const char *source, size_t num);

Objetivo: Copia os primeiros num caracteres da string apontada por source para o bloco de memória indicado por destination.

Parâmetros:

  • destination: Ponteiro para o espaço que receberá a cópia.
  • source: Ponteiro para a string de origem.
  • num: Quantidade máxima de caracteres a serem copiados.

Retorno: O endereço inicial do espaço de destino.

Diferença em relação ao strcpy: A função strcpy copia até encontrar o caractere nulo (\0), o que pode causar estouros de buffer se o destino for pequeno. Já strncpy limita a operação ao número especificado, sendo mais seguro e não exigindo obrigatoriamente que a origem possua o terminador nulo.

Exemplo de Uso

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

int main(void) {
    char destino[20] = {0};
    char origem[] = "programador";
    char* resultado = strncpy(destino, origem, 4);
    printf("Destino: %s\n", destino);
    printf("Resultado: %s\n", resultado);
    return 0;
}

strcmp

int strcmp(const char *str1, const char *str2);

Objetivo: Avalia lexicograficamente as strings str1 e str2. A verificação ocorre caractere por caractere, avançando enquanto os valores ASCII forem iguais, até encontrar uma divergência ou o fim das strings.

Parâmetros:

  • str1: Ponteiro para a primeira string.
  • str2: Ponteiro para a segunda string.

Retorno:

  • Valor positivo se str1 for maior que str2.
  • Zero se forem idênticas.
  • Valor negativo se str1 for menor que str2.

Exemplo de Uso

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

int main(void) {
    char texto_a[] = "linux";
    char texto_b[] = "linus";
    int comparacao = strcmp(texto_a, texto_b);
    
    if (comparacao > 0) {
        printf("texto_a é maior que texto_b\n");
    } else if (comparacao == 0) {
        printf("Os textos são iguais\n");
    } else {
        printf("texto_a é menor que texto_b\n");
    }
    return 0;
}

Implementação Simulada

#include <assert.h>

int comparar_strings(const char *s1, const char *s2) {
    assert(s1 != NULL && s2 != NULL);
    while (*s1 == *s2) {
        if (*s1 == '\0') {
            return 0;
        }
        s1++;
        s2++;
    }
    return *(const unsigned char *)s1 - *(const unsigned char *)s2;
}

strncat

char *strncat(char *destination, const char *source, size_t num);

Objetivo: Anexa os primeiros num caracteres da string source ao final de destination, adicionando o caractere nulo ao término da concatenação.

Parâmetros:

  • destination: Ponteiro para a string base que receberá a anexação.
  • source: Ponteiro para os dados a serem anexados.
  • num: Limite máximo de caracteres acrescentados.

Retorno: O endereço de início da string de destino.

Contraste com strcat: A função strcat anexa a totalidade da origem, incluindo seu terminador nulo. A variante strncat limita a cópia, oferecendo maior controle e evitando sobrescrita acidental de memória adjacente.

Exemplo de Uso

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

int main(void) {
    char base[30] = "Olá, ";
    char sufixo[] = "mundo virtual";
    char* ptr = strncat(base, sufixo, 5);
    printf("Concatenado: %s\n", base);
    printf("Ponteiro: %s\n", ptr);
    return 0;
}

strncmp

int strncmp(const char *str1, const char *str2, size_t num);

Objetivo: Realiza a comparação lexicográfica entre str1 e str2, mas avalia apenas os primeiros num caracteres.

Parâmetros:

  • str1 e str2: Ponteiros para as strings sob análise.
  • num: Número máximo de caracteres a verificar.

Retorno: Segue a mesma convenção de strcmp (positivo, zero ou negativo).

Vantagem sobre strcmp: Permite comparar trechos específicos das strings, aumentando a flexibilidade e a segurança da lógica de validação.

Exemplo de Uso

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

int main(void) {
    char seq1[] = "desenvolvimento";
    char seq2[] = "design";
    int res1 = strncmp(seq1, seq2, 3);
    printf("Comparando 3 chars: %d\n", res1);
    int res2 = strncmp(seq1, seq2, 4);
    printf("Comparando 4 chars: %d\n", res2);
    return 0;
}

strstr

char *strstr(const char *str1, const char *str2);

Objetivo: Procura a primeira ocorrência exata da substring str2 dentro da string str1. Requer a inclusão do cabeçalho <string.h>.

Parâmetros:

  • str1: Ponteiro para o texto onde a busca é realizada.
  • str2: Ponteiro para o padrão procurado.

Retorno:

  • Ponteiro indicando a posição inicial da primeira correspondência.
  • NULL se o padrão não for localizado.

Exemplo de Uso

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

int main(void) {
    char frase[] = "Aprendendo C com eficiência";
    char *ocorrencia = strstr(frase, "C com");
    if (ocorrencia != NULL) {
        printf("Encontrado: %s\n", ocorrencia);
    } else {
        printf("Subtexto não localizado\n");
    }
    return 0;
}

Implementação Simulada

char *buscar_substring(const char *texto, const char *padrao) {
    char *pos = (char *)texto;
    char *t, *p;

    if (!*padrao) {
        return (char *)texto;
    }

    while (*pos) {
        t = pos;
        p = (char *)padrao;
        while (*t && *p && (*t == *p)) {
            t++;
            p++;
        }
        if (!*p) {
            return pos;
        }
        pos++;
    }
    return NULL;
}

Nota: A lógica acima representa uma busca por força bruta. Algoritmos mais avançados como KMP podem ser aplicados para obter maior desempenho em cenários específicos.

strtok

char *strtok(char *str, const char *delim);

Objetivo: Divide uma string em múltiplos tokens com base em delimitadores. Modifica a string original inserindo \0 no lugar dos separadores ancontrados.

Parâmetros:

  • str: Na primeira execução, aponta para o texto a ser dividido. Nas seguintes, deve ser NULL para continuar o processo.
  • delim: Conjunto de caracteres que definem os separadores.

Retorno: Potneiro para o token atual ou NULL quando o texto está totalmente processado.

Procedimento de utilização:

  1. Chamada inicial: forneça a string e os delimitadores.
  2. Chamadas subsequentes: forneça NULL e os mesmos delimitadores.
  3. Conclusão: a iteração termina ao receber NULL.

Atenção: Como a operação destrói a string original, recomenda-se copiar os dados antes caso o conteúdo precise ser preservado. Delimitadores consecutivos são ignorados como tokens vazios.

Exemplo de Uso

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

int main(void) {
    char ip_addr[] = "10.0.0.1";
    const char *delimitador = ".";
    char *token = NULL;
    char buffer[30] = {0};
    
    strcpy(buffer, ip_addr);
    
    for (token = strtok(buffer, delimitador); token != NULL; token = strtok(NULL, delimitador)) {
        printf("%s\n", token);
    }
    return 0;
}

strerror

char *strerror(int errnum);

Objetivo: Traduz um código de erro numérico em uma mensagem de texto legível. É empregado para interpretar falhas geradas pelas funções da biblioteca padrão, utilizando o cabeçalho <string.h>.

Parâmetros:

  • errnum: Código de erro, normalmente o valor da variável global errno.

Retorno: Ponteiro para a string descritiva do erro.

O mecanismo de errno: Declarada em <errno.h>, a variável global errno armazena o código numérico do último erro. Seu valor é zerado no início do programa. Quando uma função da biblioteca falha, ela define errno com um valor diferente de zero. A função strerror converte esse inteiro em uma descrição textual compreensível.

Exemplo de Uso - Listagem de Erros

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

int main(void) {
    for (int codigo = 0; codigo <= 10; codigo++) {
        printf("Código %d: %s\n", codigo, strerror(codigo));
    }
    return 0;
}

Exemplo de Uso - Falha em Arquivo

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

int main(void) {
    FILE *arquivo = fopen("arquivo_inexistente.txt", "r");
    if (arquivo == NULL) {
        printf("Erro detectado: %s\n", strerror(errno));
        return 1;
    }
    return 0;
}

perror

Uma alternativa direta ao uso conjunto de printf e strerror é a função perror. Ela imprime o argumento fornecido, seguido de dois pontos, um espaço e a mensagem de erro corrrespondente ao valor atual de errno.

Exemplo de Uso

#include <stdio.h>
#include <errno.h>

int main(void) {
    FILE *arquivo = fopen("arquivo_ausente.dat", "r");
    if (arquivo == NULL) {
        perror("Falha ao abrir o arquivo");
        return 1;
    }
    return 0;
}

Tags: C string.h manipulação de strings Tratamento de Erros errno

Publicado em 8-31 05:16