Solução: Imprimir o Meio da String

por Fabio A. Mazzarino

Há alguns meses apareceu na lista cppbrasil uma dúvida, como retornar o(s) caracteres do meio de uma string. Por exemplo:

  • AMARELO -> R
  • VERMELHO -> ME
  • AZUL -> ZU
  • VERDE -> R

Na verdade houve uma discussão em torno do enunciado de fato, e o pessoal chegou a conclusão que o enunciado estava errado. Assim vamos considerar os exemplos acima:

Solução em C

#include <stdio.h>
#include <string.h>
void middle(const char *s, char *m) {
    if (!s || !m)
        return;
    if (strlen(s) % 2 == 0) {
        // even
        strncpy(m, &s[strlen(s)/2] - 1, 2);
        m[2] = '\x0';
    } else {
        strncpy(m, &s[strlen(s)/2], 1);
        m[1] = '\x0';
    }
}
int main() {
    char s1[] = "AMARELO";
    char s2[] = "VERMELHO";
    char m[3] = "";
    middle(s1, m);
    printf("middle(%s): %s\n", s1, m);
    middle(s2, m);
    printf("middle(%s): %s\n", s2, m);
}

A chamada da função recebe dois parâmetros, o primeiro é a string de entrada, e o segundo é o buffer de saída, que deve ter no mínimo 3 caracteres, As melhores práticas da linguagem C indicam que os buffers devem ser alocados pela função que faz a chamada, por isso a saída é um parâmetro da função.

O código acima gera a seguinte saída:

middle(AMARELO): R
middle(VERMELHO): ME

Conforme esperado.

Solução em C++

Em C++ a solução é um pouco mais simples, pois não precisamos nos preocupar com o gerenciamento dos ponteiros. Assim:

#include <stdio.h>
#include <string.h>
d
void middle(const char *s, char *m) {
    if (!s || !m)
        return;
    if (strlen(s) >= 0 && strlen(s) <= 2)
        strcpy(m, s);
    if (strlen(s) % 2 == 0) {
        // even
        strncpy(m, &s[strlen(s)/2] - 1, 2);
        m[2] = '\x0';
    } else {
        strncpy(m, &s[strlen(s)/2], 1);
        m[1] = '\x0';
    }
}
int main() {
    char s1[] = "AMARELO";
    char s2[] = "VERMELHO";
    char m[3] = "";
    middle(s1, m);
    printf("middle(%s): %s\n", s1, m);
    middle(s2, m);
    printf("middle(%s): %s\n", s2, m);
}

E a saída idêntica ao exemplo em C:

middle(AMARELO): R
middle(VERMELHO): ME

Desafio

Para dificultar que tal dividir a string em três partes? A parte do meio, a da esquerda e da direita. E pra deixar ainda mais difícil a versão C++ tem que retornar três strings de uma vez e utilizar um único argumento.