Projeto de Algoritmos |Linguagem C |Índice|English
! ? @ + - * / = < > 0 1 2 3 4 5 6 7 8 9 A E I O U C … Á Â Ã É Í Ó Ô Õ Ú Ç … ≡ ≠ ≤ ≥ Γ Δ Π Σ Ω ⋮
Esta página faz uma rápida introdução aos conceitos de Unicode, esquema de codificação, e UTF-8.Para mais informações sobre o assuntoveja os artigos indicados no fim da página.
Sumário:
- Caracteres
- Caracteres ASCII
- Esquemas de codificação
- Código ASCII
- Código UTF-8
- Qual o código usado pelo meu arquivo?
Caracteres
Um caractereé um símbolo tipográfico usado para escrever texto em alguma língua.(Embora imperfeita, essa definição é suficiente para nossas necessidades.)É importante não confundir o conceito de caractere com o tipo-de-dadoschar da linguagemC.Eis alguns exemplos de caracteres:
! " - 9 A B a b ~ À ã ç é ÿ Σ α — “
O número de caracteres usados pelas diferentes línguas do mundoé muito grande.Oportuguês usa apenas127 caracterese o inglês fica satisfeito com94 desses.Mas não podemos nos limitar a essas duas línguasporque estamos expostos a muitas outras línguas,às vezes várias numa mesma sentença.Aisso se somam os caracteres especiais usados por várias áreas da ciência.
Para começar a organizar essa Torre de Babel, é preciso dar nomes a todos os caracteres.O consórcio Unicode de empresas de informáticaatribuiu nomes numéricos(conhecidos como code points)a mais de 1milhão de caracteres.Segue uma minúscula amostra da lista de caracteres e seus números:
número Unicode | caractere |
33 | ! |
34 | " |
45 | - |
57 | 9 |
65 | A |
66 | B |
97 | a |
98 | b |
126 | ~ |
192 | À |
227 | ã |
231 | ç |
233 | é |
255 | ÿ |
931 | Σ |
945 | α |
8212 | — |
8220 | “ |
Nessa amostra, os nomes numéricos dos caracteres estão escritos em notação decimal.Em geral, entretanto,esses nomes são escritos em notação hexadecimal.Além disso, é usual acrescentar o prefixo U+
a cada número:
Unicode | caractere |
U+0021 | ! |
U+0022 | " |
U+002D | - |
U+0039 | 9 |
U+0041 | A |
U+0042 | B |
U+0061 | a |
U+0062 | b |
U+007E | ~ |
U+00C0 | À |
U+00E3 | ã |
U+00E7 | ç |
U+00E9 | é |
U+00FF | ÿ |
U+03A3 | Σ |
U+03B1 | α |
U+2014 | — |
U+201C | “ |
A lista completa de caracteres e seus números Unicode pode ser vista na páginaList of Unicode characters da Wikipediaou na página Unicode/ Character referencedo Wikibooks.
O conjunto de todos os caracteres da lista Unicode pode ser chamado alfabeto Unicodee cada caractere desse alfabeto pode ser chamado caractere Unicode.(Se a pretensão do projeto Unicode for justificada,todos os caracteres de todas as línguas do mundo são caracteres Unicode.)
Caracteres ASCII
Os primeiros 128 caracteres da lista Unicode são os mais usados.Esse conjunto de caracteres vai de U+0000 a U+007Fe é conhecido como alfabeto ASCII.Os elementos desse alfabeto serão chamadoscaracteres ASCII.O alfabeto ASCII contémletras,dígitos decimais,sinais de pontuação,e alguns caracteres especiais.A lista dos 128 caracteres ASCII e seus números Unicodeestá registrada na Tabela ASCII.
Infelizmente o alfabeto ASCIInão é suficiente para escrever texto em português,pois não contém letras com sinais diacríticos.
Esquemas de codificação
Como armazenar os caracteres Unicode em arquivos digitais e na memória?Poderíamos representar cada caracterepelo seu número Unicode escrito emnotação binária.Mas isso exigiria 3 bytes por caractere,o que é muito ineficiente dado que apenas 1 byte é suficiente para os caracteres mais comuns.Épreciso recorrer, então, a representações mais complexas.
Um esquema de codificação(=character encoding)é uma tabela que associa uma sequência de bytescom cada número Unicode,e portanto com cada caractere Unicode.(Em geral, omitimos a palavra esquema
e dizemos apenas codificação
.)Asequência de bytes associada com um caractere é o código do caractere.As próximas seções examinam dois esquemas de codificação:ASCII eUTF-8.
Código ASCII
O código ASCII é muito simples:o número Unicode de cada caractere é escrito em notação binária.Esse código é usado apenas para o alfabeto ASCII.Como o alfabeto tem apenas 128 caracteres,o código ASCII necessita de apenas 1byte por caracteree o primeiro bit desse byte é0.Segue uma amostra da tabela de códigos:
Unicode | ASCII | hexa | |
U+0021 | ! | 00100001 | 0x21 |
U+0022 | " | 00100010 | 0x22 |
U+002D | - | 00101101 | 0x2D |
U+0039 | 9 | 00100111 | 0x39 |
U+0041 | A | 01000001 | 0x41 |
U+0042 | B | 01000010 | 0x42 |
U+0061 | a | 01100001 | 0x61 |
U+0062 | b | 01100010 | 0x62 |
U+007E | ~ | 01111110 | 0x7E |
A última coluna traz o código ASCII escrito em notação hexadecimal.
(Por que não aproveitar todos os 8 bits de um byte?Com isso, poderíamos codificar 128 caracteres adicionaisalém dos 128 do alfabeto ASCII.O código ISO-LATIN-1 faz exatamente isso,mas caiu em desuso.Oconjunto ISO-LATIN-1 de caracteres inclui, entre outros,os caracteres ª± º ¼ ½ ¾ À Á Â Ã Ç È É Ê Ì Í Î Ò Ó Ô × Ù Ú Û à á â ã ç è é ê ì í î ò ó ô õ ÷ ù úû.Os nomes numéricosdesses caracteres são iguaisna tabela ISO-LATIN-1e na tabela Unicode.)
Código UTF-8
Se usássemos um número fixo de bytes por caractere,precisaríamos de 3 bytes.Asolução é recorrer a um código multibyte,que emprega um número variável de bytes por caractere:alguns caracteres usam 1byte,outros usam 2bytes, e assim por diante.
O código multibyte mais usado é conhecido comoUTF-8.Ele associa uma sequência de 1 a 4 bytes (8a 32bits)com cada caractere Unicode.Os primeiros 128 caracteres usam o velho e bom código ASCII de 1bytepor caractere.Os demais caracteres têm um código mais longo.Veja uma minúscula amostra:
Unicode | código UTF-8 | hexa | |
U+0021 | ! | 00100001 | 0x21 |
U+0022 | " | 00100010 | 0x22 |
U+002D | - | 00101101 | 0x2D |
U+0039 | 9 | 00100111 | 0x39 |
U+0041 | A | 01000001 | 0x41 |
U+0042 | B | 01000010 | 0x42 |
U+0061 | a | 01100001 | 0x61 |
U+0062 | b | 01100010 | 0x62 |
U+007E | ~ | 01111110 | 0x7E |
U+00C0 | À | 11000011 01000000 | 0xC380 |
U+00E3 | ã | 11000011 10100011 | 0xC3A3 |
U+00E7 | ç | 11000011 10100111 | 0xC3A7 |
U+00E9 | é | 11000011 10101001 | 0xC3A9 |
U+00FF | ÿ | 11000011 10111111 | 0xC3BF |
U+03A3 | Σ | 11001110 10100011 | 0xCEA3 |
U+03B1 | α | 11001110 10110001 | 0xCEB1 |
U+2014 | — | 11100010 10000000 10010100 | 0xE28094 |
U+201C | “ | 11100010 10000000 10011100 | 0xE2809C |
(A última coluna traz o código UTF-8 escrito em notação hexadecimal.)A lista dos códigos UTF-8de todos os caracteres Unicode pode ser vista emUTF-8 encoding table and Unicode charactersou na páginaUnicode/ Character referencedo Wikibooks.Por exemplo, a cadeia de caracteres açãoé representada em UTF-8 pela seguinte sequência de bytes:
0x61 | 0xC3 | 0xA7 | 0xC3 | 0xA3 | 0x6F |
a | ç | ã | o |
Todas as letras com sinais diacríticos usadas em português são representados em UTF-8 por apenas 2bytes,o primeiro dos quais é0xC3 (195em notação decimal).
Decodificação.Como o número de bytes por caractere não é fixo,a decodificação de uma sequência de bytes não é fácil.Como saber onde termina o código de um caracteree começa o código do caractere seguinte?O esquema de codificação UTF-8foi construído de modo queos primeiros bits do código de um caracteredizem quantos bytes o código ocupa.Assim, se o primeiro bit é0,e portanto o valor do primeiro byte é menor que128,então esse é o único byte do caractere.Se o valor do primeiro byte pertence ao intervalo 192 .. 223 então o código do caractere tem dois bytes.Eassim por diante.
Suporemos UTF-8.A linguagem de programaçãoC não prescreve um esquema de codificação específico.Mas o código mais usado é UTF-8,tanto para entrada e saída quanto para a representação interna de caracteres.Opresente sítio supõe que todos os arquivos de texto,sejam eles programas ou dados,usam código UTF-8.(Mas em muitos exemplos apenas o subconjunto ASCII de UTF-8é usado.)
Exercícios 1
- A seguinte sequência de bytes está em notação decimal.Que cadeia de caracteres esses bytes representamem código UTF-8?
67 195 179 100 105 103 111
- A seguinte sequência de bytes está em notação hexadecimal.Que cadeia de caracteres esses bytes representamem código UTF-8?
0x41 0x74 0x65 0x6E 0xC3 0xA7 0xC3 0xA3 0x6F 0x21
- Consulte a tabela UTF-8 encoding table and Unicode characters(ou outra semelhante)para verificar que todas as letras com sinais diacríticos usadas em português são representados em UTF-8 por apenas 2bytes,o primeiro dos quais é0xC3 (195em notação decimal).
- Escreva uma função que receba um arquivoque contém texto em código UTF-8e decida se cada byte do arquivo representa um único caractere(ou seja, se o alfabeto do arquivo é ASCII).
- Escreva as sequências de bytes que representam,em código UTF-8,cada uma das seguintes cadeias de caracteres:
- ASCII string
- Atenção!
- π = 3.14±0.01
- ⌊9.9⌋ = 9
- v[n] = ∞
(Consulte a páginaUTF-8 encoding table and Unicode characters.Use o botãogo to other blockpara ver as várias partes da tabela.)
Qual o código usado pelo meu arquivo?
Não há como saber, com certeza,qual o esquema de codificação usado por um dado arquivo de texto.O autor do arquivo precisa informar, fora do arquivo,qual código usou.
Há utilitários (como file, por exemplo)que examinam um arquivo etentam adivinhar,com algum grau de confiança,o seu esquema de codificação.
Se souber qual o esquema de codificação usado por seu arquivo,você pode usar o aplicativo iconvpara mudar a codificação(convertendo, por exemplo, um arquivo codificado em ISO-LATIN-1em um arquivo equivalente codificado emUTF-8).
Exercícios 2
- Os programasod e hexdumpimprimem a sequência de bytes de um arquivosem convertê-los em caracteres.Use um desses utilitários para examinar o conteúdo de um arquivoe procure adivinhar o esquema de codificação usado.
- A função isalpha da biblioteca ctypesó reconhece letras do alfabeto ASCII(sem sinais diacríticos, portanto).Escreva uma extensão de isalphaque reconheça letras com diacríticos.Sua função deve receber uma string que contém a codificação UTF-8de um caractere e decidir se o código representa uma letra (com sinal diacrítico ou não).
Character encodings for beginners,W3C Internationalization.
The Absolute Minimum Every Software Developer Must Know About Unicode and Character Sets,por Joel Spolsky
On the Goodness of Unicode,Characters vs. Bytes,On Character Strings,Programming Languages and Text,por TimBray.
Unicode in C and C++: What You Can Do About It Today,por Jeff Bezanson.
Locales and Internationalization,no manual da Gnu.org.
GNU libunistring:bibliotecas de manipulação de strings UTF-8.
Atualizado em 2022-12-31
https://www.ime.usp.br/~pf/algoritmos/
© Paulo Feofiloff
DCC-IME-USP