Desafio C

Concatenação segura e verificação de overflow

Enunciado

Escreva um programa que leia dois nomes (máximo 20 caracteres cada) e os concatene em um buffer de 30 caracteres. Use fgets para ler, remova o '\n' e verifique se a concatenação cabe. Se não couber, exiba uma mensagem de erro; caso contrário, mostre o nome completo e seu comprimento.

Requisitos

  • Use fgets para ler cada nome, removendo o caractere de nova linha.
  • Verifique se a soma dos comprimentos + 1 (terminador) é menor ou igual a 30.
  • Use strncat ou snprintf para concatenar com segurança.
  • Imprima Nome completo: <resultado> e Comprimento: <n> ou Erro: nome muito longo.

Código inicial

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

int main(void) {
    char nome1[21], nome2[21];
    char completo[30];
    // Leia, remova '\n', verifique e concatene
    return 0;
}

Saída esperada

Nome completo: Maria Silva
Comprimento: 11
Ver dica

Após fgets, use strcspn(nome, "\n") para encontrar a posição do '\n' e substitua por '\0'.

Mostrar solução
#include <stdio.h>
#include <string.h>

int main(void) {
    char nome1[21], nome2[21];
    char completo[30];

    // Leitura segura com fgets
    fgets(nome1, sizeof(nome1), stdin);
    fgets(nome2, sizeof(nome2), stdin);

    // Remove o '\n' do final, se existir
    nome1[strcspn(nome1, "\n")] = '\0';
    nome2[strcspn(nome2, "\n")] = '\0';

    size_t len1 = strlen(nome1);
    size_t len2 = strlen(nome2);

    // Verifica se cabe no buffer completo (incluindo espaco e terminador)
    if (len1 + 1 + len2 + 1 > sizeof(completo)) {
        printf("Erro: nome muito longo\n");
        return 1;
    }

    // Copia o primeiro nome e concatena com espaco e segundo nome
    strcpy(completo, nome1);
    strcat(completo, " ");
    strcat(completo, nome2);

    printf("Nome completo: %s\n", completo);
    printf("Comprimento: %zu\n", strlen(completo));
    return 0;
}

Passo a passo

  1. Declaramos nome1[21] e nome2[21] para ler até 20 caracteres + '\0'.
  2. fgets lê a linha inteira, incluindo o '\n', e garante o terminador.
  3. strcspn(nome, "\n") retorna o índice do '\n'; substituímos por '\0' para remover a quebra de linha.
  4. Calculamos len1 e len2 com strlen.
  5. Verificamos se len1 + 1 (espaço) + len2 + 1 (terminador) cabe em sizeof(completo). Se não, exibimos erro e saímos.
  6. Copiamos nome1 para completo com strcpy e concatenamos espaço e nome2 com strcat. Como já verificamos o tamanho, é seguro.
  7. Imprimimos o resultado e o comprimento.

Por que funciona

A verificação prévia evita buffer overflow. fgets limita a leitura ao tamanho do buffer, e a remoção do '\n' garante que a string não tenha caracteres indesejados. strcat é seguro porque o destino tem espaço suficiente comprovado pela verificação.

Erros comuns

  • Não remover o '\n': o nome completo teria uma quebra de linha no meio.
  • Esquecer de verificar o tamanho: strcat pode estourar o buffer.
  • Usar scanf("%s", nome) sem limite: risco de overflow se a entrada for maior que o buffer.
  • Não incluir o espaço na conta do tamanho: a verificação pode passar, mas a concatenação falhar.

Outra forma de resolver

Usar snprintf(completo, sizeof(completo), "%s %s", nome1, nome2) é mais direto e já trunca se necessário. Prefira snprintf para concatenações simples.

Saída esperada

Nome completo: Maria Silva
Comprimento: 11