paulo1205
(usa Ubuntu)
Enviado em 09/06/2017 - 13:45h
listeiro_037 escreveu:
Eu vi isso aí feito dentro dos fontes do Kanatest. Dá algum problema de codificação de texto dependendo do editor ou do sistema? Tipo, se estiver em UTF-8, ISO-8859-1 outra codificação?
Pode dar. Veja algumas variáveis envolvidas:
1) O editor do código fonte pode gravar conteúdo
ipsis litteris num conjunto de caracteres default do sistema ou do próprio editor, mas também existem editores que fazem conversão entre o que exibem na tela e o que vai para arquivo.
2) Compiladores
geralmente tratam strings
ipsis litteris (principalmente em C). Algumas linguagens (Java, Python etc.) podem optar por converter strings do código fonte para uma representação interna com outra codificação em tempo de compilação, mas como esta comunidade é sobre C e C++, não vou me ocupar com elas.
3) No momento da execução do programa, funções como
printf() e
putchar() vão fazer exatamente aquilo que sabem fazer: enviar para o dispositivo de saída (que pode ser a tela, mas pode também, graças a redirecionamentos, ser um arquivo, um
pipe, um
socket etc.) simplesmente os bytes que tiverem sido instruídas a enviar. Assim sendo, se você tem no código algo como
putchar(251), o
byte com valor 251 será jogado na saída, independentemente do caráter a que ele esteja (ou
não esteja, no caso de codificações que usam sequências de bytes, como UTF-8) associado no ambiente em que o programa estiver sendo executado. Por outro lado, algo como
printf("√"), que também vai enviar bytes (um ou mais, dependendo das condições listadas acima para o código fonte e para a etapa de compilação), cuja interpretação em tempo de execução também não é totalmente previsível.
4) O ambiente de execução é mutável. É possível ter abertos no Linux, ao mesmo tempo, dois ou três terminais de texto, e cada um estar com uma codificação diferente (por exemplo: um com UTF-8, um com ISO-8859-1 e outro com KOI8-R), todos funcionando “bem”, para aplicações que suportem internacionalização (você também pode ter configuração semelhante no Windows, e até o MS-DOS, embora não tenha terminais simultâneos, pode reconfigurar seu terminal com diferentes conjuntos de caracteres e codificações). Se você fizer seu programa de modo a enviar bytes fixos, a saída visual em cada um deles pode ser radicalmente diferente dos demais.
5) Mesmo a situação acima, para aplicações que procurem levar internacionalização a sério (i.e. em vez de enviar bytes fixos, procuram adequar a informação a ser apresentada às características do meio que em que se fará a apresentação), depende de condições relativamente instáveis. Para que funcione, cada terminal term de ter sido configurado para suportar o respectivo conjunto de caracteres, e o ambiente que está sendo executado dentro de cada terminal
também tem de estar configurado (no mundo UNIX, isso geralmente se faz através de variáveis de ambiente), e de um modo compatível com o terminal que o contém. Um eventual descompasso entre a configuração do terminal e a do ambiente de execução pode deixar a comunicação (tanto a exibição quanto a entrada de dados) deficiente, ou mesmo imprestável.
Um princípio de solução seria usar internamente strings em Unicode, ou pelo menos o caráter que você quiser, e fazer a conversão para o caráter (ou sequência de caracteres) correspondente na hora de imprimir. Abaixo segue um exemplo.
#include <wchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <locale.h>
wchar_t SQRT_WC=L'\u221a'; // Sinal de raiz quadrada no Unicode. Aqui, não depende do editor de textos.
int main(void){
// Vai conter string capaz de guardar a sequência de bytes do símbolo SQRT_WC.
char sqrt_str[MB_LEN_MAX];
int sqrt_str_len; // Comprimento de sqrt_str;
// IMPORTANTE: Ajusta locale do programa de acordo com o que estiver nas variáveis de ambiente.
setlocale(LC_ALL, "");
// Se o tamanho for -1, não existe representação possível na locale selecionada.
sqrt_str_len=wctomb(sqrt_str, SQRT_WC);
// Imprime string retratando a ideia de “raiz quadrada de a+b”.
if(sqrt_str_len>0)
printf("%.*s(a+b)\n", sqrt_str_len, sqrt_str); // Envia o símbolo de raiz quadrada como string de múltiplos caracteres.
else
printf("(a+b)^(1/2)\n"); // Representação em ASCII puro, valendo-se de que a raiz índice n de x é igual a x elevado a 1/n.
// ALTERNATIVA:
// Uma vez que eu já sei que o caráter é representável, posso deixar a
// própria printf() convertê-lo (potencialmente economiza memória, mas
// tem de refazer a conversão de wchar_t para string a cada impressão).
if(sqrt_str_len>0)
printf("%lc(a+b)\n", SQRT_WC);
}
Como eu usei apenas recursos padronizados pelo C99, é possível que esse programa funcione em Windows (pelo menos, deveria), e com qualquer
code page que possua um símbolo de raiz quadrada. Infelizmente, não tenho como testar, pois não uso Windows.
Note, porém, que esse programa depende das mesmas condições possivelmente problemas descritas acima, confiando que seu sistema está configurado adequadamente. Erros de configuração podem induzir ao uso da representação que depende de um caráter que o terminal não consiga exibir adequadamente, ou, por outro lado, a não usar o caráter especial, mesmo que o terminal seja capaz de exibi-lo.