Contagem de caracteres | CSharp
- Contagem de caracteres | CSharp
Cada letra pode ser representado por um número (varia de acordo com as tabelas de codificaçäo) e cada número representa uma sequência de bits
- O processo de converter de texto -> número -> bits chama se
encodinge o processo reverso chama-sedecoding
Tabelas de codificação | ASCII e Unicode
🧮 1. Tabela ASCII
📖 O que é
ASCII (American Standard Code for Information Interchange) é o padrão mais antigo de codificação de caracteres — criado nos anos 1960. Ele define 128 símbolos básicos (números de 0 a 127), cada um associado a um caractere.
🔢 Estrutura
-
Cada caractere é representado por 1 byte (8 bits), mas apenas 7 bits são usados (o 8º era reservado para controle).
-
Exemplo:
Decimal Hex Caractere Descrição 65 0x41 ALetra maiúscula A 97 0x61 aLetra minúscula a 48 0x30 0Dígito zero 32 0x20 Espaço 10 0x0A \nQuebra de linha
⚙️ Limitação
- Representa apenas o alfabeto inglês, dígitos e alguns símbolos básicos.
- Não suporta acentos (é, ç, ñ, etc.) nem caracteres de outros idiomas.
👉 Por isso surgiram extensões como ISO-8859-1 (Latin-1) e, mais tarde, o Unicode.
🌍 2. Tabela Unicode
📖 O que é
Unicode é o padrão moderno e universal que busca representar todos os caracteres de todas as línguas, símbolos matemáticos, emojis, etc. Cada caractere recebe um código numérico único, chamado code point.
- Intervalo total:
U+0000atéU+10FFFF(mais de 1 milhão de posições possíveis) - Atualmente cobre mais de 149.000 caracteres (letras, ideogramas, símbolos, emojis...)
🔢 Exemplo de mapeamento
| Caractere | Nome | Code Point (Unicode) |
|---|---|---|
A | Latin Capital Letter A | U+0041 |
é | Latin Small Letter e with acute | U+00E9 |
中 | Chinese character “zhong” | U+4E2D |
😀 | Grinning Face Emoji | U+1F600 |
💾 Unicode não é uma codificação
Unicode é uma tabela de referência — uma lista de todos os símbolos e seus números (code points).
Para armazenar/transmitir esses números em bytes, usamos codificações Unicode, como:
- UTF-8
- UTF-16
- UTF-32
🔗 3. Relação entre ASCII e Unicode
- Os 128 primeiros caracteres de Unicode (U+0000 a U+007F) são idênticos ao ASCII.
- Isso garante retrocompatibilidade — qualquer texto ASCII é automaticamente válido em Unicode.
| ASCII | Unicode | Caractere |
|---|---|---|
| 65 | U+0041 | A |
| 97 | U+0061 | a |
| 32 | U+0020 | espaço |
| 10 | U+000A | nova linha |
✅ Resumo rápido
| Propriedade | ASCII | Unicode |
|---|---|---|
| Criado em | 1963 | 1991 |
| Capacidade | 128 símbolos | +1.1 milhão de símbolos possíveis |
| Tamanho por caractere | 1 byte (7 bits usados) | variável (1–4 bytes) |
| Suporte a idiomas | Apenas inglês | Todos os idiomas do mundo |
| Compatível com Unicode? | Sim (Unicode inclui ASCII) | — |
Dentro do C#
Bytes
- Um byte é composto por 8 bits — essa é uma convenção universal adotada na computação moderna.
- Um bit (binary digit) é a menor unidade de informação:
Pode ter apenas dois valores →
0ou1.
Exemplo:
1 bit → 0 ou 1
- Um byte é formado por 8 bits.
- Ele pode representar 256 valores diferentes (2⁸ = 256). → De 0 a 255 em decimal, → Ou 00 a FF em hexadecimal.
Exemplo:
1 byte = 8 bits = 01000001 = 65 decimal = letra 'A' em ASCII
🔤 1. C# usa UTF-16 internamente
Em C#, uma string é uma sequência de char, e cada char tem 16 bits (2 bytes).
Ou seja, o C# representa strings em UTF-16.
Exemplo simples:
string texto = "ABC";
Console.WriteLine(texto.Length); // 3
✅ Cada caractere (A, B, C) cabe em 1 char.
Portanto, Length = 3.
🧩 2. Emojis e caracteres “grandes” ocupam 2 chars
Alguns caracteres (como emojis ou letras raras) estão fora do BMP (Basic Multilingual Plane). Eles exigem 2 unidades UTF-16 — chamadas pares substitutos (surrogate pairs).
string emoji = "😀"; // U+1F600
Console.WriteLine(emoji.Length); // 2
➡️ Mesmo sendo um único símbolo visível, ele ocupa 2 chars internamente.
Cada char contém metade do emoji (\uD83D e \uDE00).
📏 3. Comparando Length, Rune e StringInfo
Vamos comparar três formas de contagem no C# moderno (.NET 5+):
using System;
using System.Globalization;
using System.Linq;
using System.Text;
class Program
{
static void Main()
{
string texto = "A😀👩❤️💋👩";
Console.WriteLine($"String: {texto}");
Console.WriteLine($"Length (chars): {texto.Length}");
// 1️⃣ Contando code points (Rune)
int codePoints = texto.EnumerateRunes().Count();
Console.WriteLine($"Code points: {codePoints}");
// 2️⃣ Contando elementos visuais (grapheme clusters)
int textElements = new StringInfo(texto).LengthInTextElements;
Console.WriteLine($"Text elements (visuais): {textElements}");
}
}
Saída:
String: String: A😀👩❤️💋👩
Length (chars): 11
Code points: 7
Text elements (visuais): 6
String no console:
Explicando:
| Tipo de contagem | O que mede | Valor |
|---|---|---|
Length | Unidades UTF-16 (chars) | 11 |
EnumerateRunes() | Pontos de código Unicode | 7 |
StringInfo.LengthInTextElements | Elementos visuais que o usuário vê | 6 |
👉 O usuário vê 3 símbolos: “A”, “😀”, e “👩❤️💋👩”, mas internamente há muitos code units para representar cada um.
🔍 4. Quando usar cada um
| Método | Uso indicado |
|---|---|
texto.Length | Quando só importa o número de chars (UTF-16) — ex: manipulação interna |
texto.EnumerateRunes().Count() | Quando você quer contar code points Unicode (cada símbolo atômico) |
new StringInfo(texto).LengthInTextElements | Quando você quer contar caracteres visuais (o que o usuário enxerga) |
🧠 5. Visualizando internamente
Você pode inspecionar os valores UTF-16 que formam uma string:
string s = "😀";
foreach (char c in s)
{
Console.WriteLine($"U+{(int)c:X4}");
}
Saída:
U+D83D
U+DE00
➡️ Esses são os dois chars que, juntos, formam o emoji 😀 (U+1F600).
✅ Resumo final
| Conceito | Método | Mede o quê | Emoji “😀” retorna |
|---|---|---|---|
| Code units (UTF-16) | texto.Length | Número de chars | 2 |
| Code points (Unicode) | texto.EnumerateRunes().Count() | Pontos de código | 1 |
| Elementos visuais (graphemes) | new StringInfo(texto).LengthInTextElements | O que o usuário vê | 1 |