Como Converter para Maiúsculas as letras com acentos em C e C++

Melhor do que conversões que só dão 'falha de segmentação' na cabeça dos iniciantes.


Como Converter para Maiúsculas as letras com acentos em C e C++

Alguns programadores C e C++ vivem um drama quando o assunto é ler e imprimir letras acentuadas e principalmente quando precisam converter de minúsculas para MAIÚSCULAS ou vice-versa.

Isso porque as letras acentuadas não fazem parte da tabela ASCII e sim são como um UNICODE, ou seja, apesar de haver acentos na tabela ASCII , um letra acentuada são 2 endereços e não somente 1, algumas até 4, e é aí que entra o problema.

Linguagem C

Suponhamos que você tem esse código em C , um mini programinha que lê os dados informados pelo usuário, converte em MAIÚSCULAS e imprime na tela:

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define TAM 35

int main (int argc, char ** argv){
  // declara a variável que armazenará o nome
  char nome[TAM];

  // Interage com o usuário
  printf("Informe o nome: ");
  
  // limpa a entrada e lê a entrada dos dados digitados
  fflush(stdin);
  fgets(nome, TAM, stdin);

  for (size_t i = 0; i < strlen(nome); ++i) {
    // Convertemos cada caractere para maiúsculo
    nome[i] = toupper( nome[i] );

    // e imprimimos na tela
    printf("%c", nome[i]);
  }

  return 0;
}

Até aí tudo bem, mas tente inserir um nome com acento, vai aparecer assim, ex.: JOSé SILVA, a letra é possui acento e não ficou em MAIÚSCULA! 😞

Saída dos dados

Mas podemos resolver isso. Primeiro, lembre-se desses detalhes antes de iniciar um projeto. Se você sabe que seu programa terá dados inseridos pelo usuário e eles podem ser de qualquer lugar do mundo, logo, você deve utilizar as ferramentas corretas.

Para isso vamos incluir os cabeçalhos:

  • #include <wchar.h> para usarmos o tipo wchar_t(substitui o char), fgetws(substitui o ´fgets), wcslen(substitui strlen) e wint_t(substitui o int);
  • #include <locale.h> para usarmos a função: setlocale, o locale pode ser vazio, mas se você quiser especificar, use: pt_BR.UTF-8, mas isso limita seu código;
  • #include <wctype.h> para towupper substitui o toupper da ctype.h.

Logo, nosso código final ficaria:

#include <stdio.h>
#include <wchar.h>
#include <locale.h>
#include <wctype.h>
#define TAM 100

int main( int argc , char **argv ){
  // usamos o setlocale LC_ALL vazio(para todos)
  setlocale(LC_ALL, "");

  wchar_t nome[TAM];
  printf("Informe o nome: ");
  fflush(stdin);
  fgetws(nome, TAM, stdin);

  for (size_t i = 0; i < wcslen(nome); i++) {
    nome[i] = towupper(nome[i]);
    printf("%lc", (wint_t)nome[i]);
  }

  return 0;
}

Após compilar e testar o resultado é que agora conseguimos converter para MAIÚSCULAS as letras acentudas:

Saída dos dados

Show, né?! Tudo é uma questão de planejamento! 😃


E no C++ ?

Bom, nós sabemos que basta você copiar o arquivo de extensão .c para .cpp ou qualquer outra extensão C++ já funciona, exemplo:

cp main.c main.cpp

Nesse caso específico nem renomear precisaria, lembrando que o inverso nem sempre pode ser verdadeiro! 😎

Mas escrever um arquivo C++ no estilo C é DESELEGANTE!!!

Logo, poderíamos portar nosso código para o C++ e ficaria assim:

Perceba que eu usei std::wcout em vez de std::cout apesar de ser só uma linha de interação com o usuário, ela também é FUNDAMENTAL!!!

#include <iostream> // std::wcout
#include <cwchar>   // wchar_t, fgetws, wcslen, wint_t
#include <clocale>  // setlocale
#include <cwctype>  // towupper

int main( int argc , char **argv ){
  unsigned const int tam {100};
  setlocale(LC_ALL, "");
  wchar_t nome[tam];

  std::wcout << "Informe o texto: ";
  fflush(stdin);
  fgetws(nome, tam, stdin);

  for (size_t i = 0; i < wcslen(nome); ++i) {
    nome[i] = towupper(nome[i]);
    std::wcout << nome[i];
  }

  return 0;
}

Saída dos dados

Apesar disso ser funcional nós sabemos que C++ é um superset(super conjunto) do C, mas possui suas próprias soluções e essas não funcionam no C.

Logo, poderíamos utilizar as seguintes ferramentas do C++:

  • std::locale::global
  • std::wcout.imbue()
  • std::use_facet<std::ctype<wchar_t>>(std::locale())
  • std::wstring
  • std::wcin

Nosso código com soluções nativas do C++ ficaria assim:

#include <iostream>
#include <locale>

int main(){
  std::locale::global(std::locale(""));
  std::wcout.imbue(std::locale());
  auto& f = std::use_facet<std::ctype<wchar_t>>(std::locale());

  std::wstring frase;
  std::wcout << "Informe o texto: ";
  std::getline(std::wcin, frase);

  f.toupper(&frase[0], &frase[0] + frase.size());
  std::wcout << frase << '\n';

  return 0;
}

Saída dos dados

Muito mais Like a BOSS!, né não?! 😃


Por hoje é só, são pequenas doses diárias que farão sempre nos manter antenado com o C++ !

Acompanhe o cpp::daily

Deseja aprender C++ e criar seus programas Gráficos e para Terminal com portabilidade para Linux e Windows?

Então se inscreva nos nossos Cursos de C++ Moderno . Você aprender criar:

Acesse o endereço:

https://terminalroot.com.br/cpp/ e saiba mais!


Referências:


linguagemc cpp


Compartilhe


Nosso canal no Youtube

Inscreva-se


Marcos Oliveira

Marcos Oliveira

Desenvolvedor de software
https://github.com/terroo


Crie Aplicativos Gráficos para Linux e Windows com C++

Aprenda C++ Moderno e crie Games, Programas CLI, GUI e TUI de forma fácil.

Saiba Mais

Receba as novidades no seu e-mail!

Após cadastro e confirmação do e-mail, enviaremos semanalmente resumos e também sempre que houver novidades por aqui para que você mantenha-se atualizado!