Diferenças
Aqui você vê as diferenças entre duas revisões dessa página.
Ambos lados da revisão anterior Revisão anterior | |||
c:strings_multibyte [2023/08/01 20:09] – edição externa 127.0.0.1 | c:strings_multibyte [2023/08/15 14:48] (atual) – maziero | ||
---|---|---|---|
Linha 1: | Linha 1: | ||
+ | ====== Strings multibyte ====== | ||
+ | |||
+ | {{ progc_strings_multibyte.mkv |Video desta aula}} | ||
+ | |||
+ | ===== Localização ===== | ||
+ | |||
+ | Em computação, | ||
+ | |||
+ | No sistema Linux, por exemplo, o comando '' | ||
+ | |||
+ | < | ||
+ | $ locale | ||
+ | LANG=pt_BR.utf8 | ||
+ | LANGUAGE=pt_BR.utf8 | ||
+ | LC_CTYPE=" | ||
+ | LC_NUMERIC=" | ||
+ | LC_TIME=" | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | O parâmetro de localização mais importante para um programa em C é LC_CTYPE (// | ||
+ | |||
+ | Um programa em C pode consultar ou modificar os parâmetros de //locale// do SO através da função '' | ||
+ | |||
+ | <code c locale.c> | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | char *locale ; | ||
+ | |||
+ | // obtém o LC_CTYPE atual do programa | ||
+ | locale = setlocale (LC_CTYPE, NULL) ; | ||
+ | printf (" | ||
+ | |||
+ | // ajusta o LC_TYPE do programa para o default do SO | ||
+ | locale = setlocale (LC_CTYPE, "" | ||
+ | if (locale) | ||
+ | printf (" | ||
+ | else | ||
+ | fprintf (stderr, " | ||
+ | |||
+ | // ajusta o LC_TYPE do programa para " | ||
+ | locale = setlocale (LC_CTYPE, " | ||
+ | if (locale) | ||
+ | printf (" | ||
+ | else | ||
+ | fprintf (stderr, " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | <note tip> | ||
+ | Se a função '' | ||
+ | </ | ||
+ | |||
+ | ===== Caracteres e strings em C ===== | ||
+ | |||
+ | ==== Caracteres ASCII ==== | ||
+ | |||
+ | A linguagem C manipula caracteres codificados em ASCII sem dificuldade, | ||
+ | |||
+ | ==== Caracteres ISO-8859 ==== | ||
+ | |||
+ | Como as codificações ISO-8859-* usam apenas um byte por caractere, programas em C podem manipular caracteres em ISO sem dificuldade, | ||
+ | |||
+ | Além disso, deve-se definir o //locale// do programa para garantir o funcionamento correto de funções como '' | ||
+ | |||
+ | <code c> | ||
+ | char *locale ; | ||
+ | |||
+ | locale = setlocale (LC_CTYPE, " | ||
+ | </ | ||
+ | |||
+ | Obviamente, o locale ISO-8859-1 deve estar disponível no sistema operacional (essa informação pode ser consultada com o comando '' | ||
+ | |||
+ | ==== Caracteres UTF-8 ==== | ||
+ | |||
+ | As coisas mudam para as codificações multibyte, pois tipo '' | ||
+ | |||
+ | * Ao alocar memória para as strings, lembre-se que alguns caracteres podem ocupar mais de um byte. | ||
+ | |||
+ | * As funções de entrada/ | ||
+ | |||
+ | * O índice não corresponde mais necessariamente à posição de cada caractere na string. Por exemplo, '' | ||
+ | |||
+ | * A função '' | ||
+ | |||
+ | Como regra geral, deve-se sempre consultar o manual para verificar se a função desejada funciona com strings multibyte. | ||
+ | |||
+ | O código abaixo apresenta um exemplo de programa que manipula strings em UTF-8: | ||
+ | |||
+ | <code c char-utf8.c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | char *frase = "Olá ɣ 诶 😃" ; | ||
+ | |||
+ | // ajusta a localização de acordo com o SO | ||
+ | setlocale (LC_ALL, "" | ||
+ | |||
+ | // conteúdos da string | ||
+ | printf (" | ||
+ | |||
+ | // número de caracteres usando strlen() | ||
+ | printf (" | ||
+ | |||
+ | // número de caracteres usando mbstowcs() | ||
+ | printf (" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Saída: | ||
+ | |||
+ | < | ||
+ | Frase : Olá ɣ 诶 😃 | ||
+ | strlen (frase) | ||
+ | mbstowcs (frase): 9 | ||
+ | </ | ||
+ | ==== Caracteres largos ==== | ||
+ | |||
+ | O padrão C 90 introduziu o conceito de caracteres " | ||
+ | |||
+ | Caracteres largos e strings largas são definidos pelo tipo '' | ||
+ | |||
+ | <code c char-wide.c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int main () | ||
+ | { | ||
+ | wchar_t c ; // um caractere largo | ||
+ | wchar_t *s ; // ponteiro para uma string larga | ||
+ | |||
+ | c = L' | ||
+ | s = L" | ||
+ | |||
+ | // ajusta a localização de acordo com o SO | ||
+ | setlocale (LC_ALL,"" | ||
+ | |||
+ | // escrita de caracteres largos | ||
+ | printf ("O caractere [%lc] tem %ld bytes\n", | ||
+ | |||
+ | // escrita de strings largas | ||
+ | printf ("A string [%ls] tem %ld caracteres\n", | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Saída: | ||
+ | |||
+ | < | ||
+ | O caractere [a] tem 4 bytes | ||
+ | A string [equação] tem 7 caracteres | ||
+ | </ | ||
+ | |||
+ | Várias funções são definidas pelo padrão POSIX para [[https:// | ||
+ | |||
+ | Algumas diferenças entre strings largas e strings multibyte UTF-8: | ||
+ | |||
+ | * Uma string larga é terminada pelo caractere largo nulo '' | ||
+ | * Em uma string larga, o número de campos equivale ao número de caracteres, por isso '' | ||
+ | * Uma string larga ocupa mais memória que uma string multibyte, pois todos os seus caracteres ocupam o mesmo número de bytes, independente de seu //code point//. | ||
+ | |||
+ | Caracteres largos são empregados na implementação de aplicações que manipulam muitas strings, como editores de texto. Por exemplo, o ambiente de execução da linguagem Python (que é implementado em C) usa caracteres largos para armazenar strings. | ||
+ | |||
+ | O código abaixo exemplifica e compara algumas operações usando strings largas e strings UTF-8. Ele gera diversos avisos (// | ||
+ | |||
+ | <code c wide-utf8.c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | int i ; | ||
+ | char *frase1 = "Olá ɣ 诶 😃" ; | ||
+ | wchar_t *frase2 = L"Olá ɣ 诶 😃" ; | ||
+ | |||
+ | // ajusta a localização de acordo com o SO | ||
+ | setlocale (LC_ALL,"" | ||
+ | |||
+ | // conteúdos das strings | ||
+ | printf (" | ||
+ | printf (" | ||
+ | |||
+ | // tamanho em bytes | ||
+ | printf (" | ||
+ | printf (" | ||
+ | |||
+ | // número de caracteres usando strlen() | ||
+ | printf (" | ||
+ | printf (" | ||
+ | |||
+ | // número de caracteres usando wcslen() | ||
+ | printf (" | ||
+ | printf (" | ||
+ | |||
+ | // número de caracteres usando mbstowcs() | ||
+ | printf (" | ||
+ | printf (" | ||
+ | |||
+ | // percurso por índice, string estreita (narrow) | ||
+ | printf (" | ||
+ | for (i = 0; i < strlen(frase1); | ||
+ | printf ("[%c] ", frase1[i]) ; | ||
+ | printf (" | ||
+ | |||
+ | // percurso por índice, string larga (wide) | ||
+ | printf (" | ||
+ | for (i = 0; i < wcslen(frase2); | ||
+ | printf (" | ||
+ | printf (" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Ao executar, este programa gera: | ||
+ | |||
+ | < | ||
+ | Current locale is pt_BR.UTF-8 | ||
+ | |||
+ | Frase 1 : Olá ɣ 诶 😃 | ||
+ | Frase 2 : Olá ɣ 诶 😃 | ||
+ | |||
+ | sizeof (char) | ||
+ | sizeof (wchar_t) : 4 | ||
+ | |||
+ | strlen (frase1) | ||
+ | strlen (frase2) | ||
+ | |||
+ | wcslen (frase1) | ||
+ | wcslen (frase2) | ||
+ | |||
+ | mbstowcs (frase1): 9 | ||
+ | mbstowcs (frase2): 1 // incorreto | ||
+ | |||
+ | Frase1: [O] [l] [�] [�] [ ] [�] [�] [ ] [�] [�] [�] [ ] [�] [�] [�] [�] | ||
+ | Frase2: [O] [l] [á] [ ] [ɣ] [ ] [诶] [ ] [😃] | ||
+ | </ | ||
+ | |||
+ | ===== Mais informações ===== | ||
+ | |||
+ | Bibliotecas para UTF-8: | ||
+ | |||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | |||
+ | ===== Exercícios ===== | ||
+ | |||
+ | - escreva um programa em C para converter um texto em ISO-8859-1 para ASCII, substituindo as letras acentuadas e cedilha por seus equivalentes sem acento. | ||
+ | - escreva um programa em C para converter um texto em ISO-8859-1 para UTF-8. | ||
+ | - escreva uma função '' | ||
+ | - escreva um programa C que imprima as tabelas ASCII e ISO-8859-1. | ||