17 Manipulação de dados textuais em C
O uso de variáveis para guardar valores textuais tem sido usado em praticamente todos os programas até o momento e seu uso para leitura está descrito na Seção 4.5.1. Este capítulo apresenta com mais detalhes as cadeias de caracteres e introduz recursos para sua manipulação.
17.1 As cadeias de caracteres em variáveis
Variáveis declaradas como char *
armazenam, como visto na Seção 16.3, apenas uma referência a uma cadeia de caracteres já existentes. Para que se tenha uma variável para guardar dados textuais de forma genérica, é preciso ter espaço para armazenar tanto os caracteres quanto o terminador \0
.
Como C não dispões de um tipo nativo para o armazenamento de textos, a alternativa é o uso de um vetor de caracteres. A declaração seguinte ilustra uma declaração para armazenamento de um valor literal. Ela cria um espaço na memória capaz de armazenar 50 valores do tipo char
, ou seja, 50 caracteres.
char texto[50];
Esse espaço reservado na declaração é fixo a partir da declaração da variável, ou seja, uma vez escolhido um comprimento, não é possível aumentá-lo ou diminuí-lo.
O que se faz nos programas é ter um espaço máximo, que é o tamanho declarado para o vetor de caracteres, porém usá-lo apenas parcialmente. Como exemplo, se na variável texto
declarada com 50 posições estiver armazenado o texto “grandes responsabilidades”, os caracteres do g inicial até o s final ocupam os primeiros 25 char
dela, sendo o 26º caractere necessariamente um \0
. Restam na variável 24 posições sem uso e seu conteúdo é ignorado.
Com essa estratégia de uso, o conteúdo textual pode ser aumentado pelo uso dos caracteres sobressalentes, deslocando-se o \0
mais para o final do vetor, ou encolhido, quando o terminador ocupa uma posição mais para o início. O limite evidente é o espaço total reservado para o armazenamento, sempre se lembrando que deve haver um espaço para o terminador. Assim, a variável texto pode ter comprimento máximo de 49 char
, pois tem que haver espaço para o \0
final.
Desse modo, pelo uso desse mecanismo de armazenamento, mantém-se uma compatibilidade com as constantes usadas no código: se existe uma constante "bom dia!"
ocupando nove bytes no programa, esse mesmo valor pode ser guardado em uma variável, ocupando as nove primeiras posições do vetor de caracteres.
17.2 Manipulação de conteúdo
Uma dificuldade imediata é que os vetores de caracteres não são uma variável simples, mas uma coleção de variáveis individuais tratadas como uma coisa só. Como não são variáveis como as declaradas como int
, double
ou mesmo char
simples, não admitem atribuições ou manipulações diretas. Para tratar as variáveis textuais C provê uma série de funções, as quais podem ser usadas pela importação do cabeçalho string.h
.
O arquivo de cabeçalho é string.h
.
#include <string.h>
Existe, porém, outro arquivo de cabeçalhos chamado strings.h
(no plural) e eles não podem ser confundidos.
Para que se tenha utilidade prática na manipulação de variáveis textuais, é preciso que se possa ver o comprimento do texto e fazer atribuições de valores, realizar concatenações e comparações.
17.2.1 Comprimento de cadeias de caracteres
Uma função que já foi usada anteriormente em diversos programas é a strlen
(string length), que retorna o comprimento da cadeia de caracteres sem o \0
final.
/*
Comprimento de cadeias de caracteres
Assegura: a apresentação de textos e respectivos comprimentos
*/
#include <stdio.h>
#include <string.h>
int main(void) {
char *texto1 = "C: a linguagem";
("\"%s\" tem comprimento %zu.\n", texto1, strlen(texto1));
printf
char *texto2 = "";
("\"%s\" tem comprimento %zu.\n", texto2, strlen(texto2));
printf
char *texto3 = "Programas estruturados";
("\"%s\" tem comprimento %zu.\n", texto3, strlen(texto3));
printf
return 0;
}
"C: a linguagem" tem comprimento 14.
"" tem comprimento 0. "Programas estruturados" tem comprimento 22.
17.2.2 Atribuições de cadeias de caracteres
O programa seguinte foca na questão da atribuição. Porém, esse código serve apenas para mostrar o que não funciona.
/*
Tentativa malsucedida de atribuir um valor a uma variável
Assegura: absolutamente nada (infelizmente)
*/
#include <stdio.h>
int main(void) {
char texto[50];
= "Bom dia!";
texto ("%s\n", texto);
printf
return 0;
}
main.c: In function ‘main’:
main.c:10:11: error: assignment to expression with array type
10 | texto = "Bom dia!"; | ^
O humilde autor desse texto tem convicção que praticamente a totalidade dos programadores C do planeta desejariam que esse programa funcionasse. A realidade, porém, não é essa: o erro principal do código é exatamente a atribuição. Basicamente, texto
é o nome para a coleção de caracteres e, na linguagem, não faz sentido armazenar nela uma constante.
O programa seguinte mostra como a função strncpy
(string copy) pode ser usada para obter o mesmo efeito da atribuição.
/*
Atribuição e apresentação de valor textual
Assegura: apresentação do valor guardado em uma string
*/
#include <stdio.h>
#include <string.h>
int main(void) {
char texto[50];
(texto, "Bom dia!", sizeof texto - 1);
strncpy("%s\n", texto);
printf
return 0;
}
Bom dia!
O processo da atribuição é copiar um dado valor para uma variável.
(texto, "Bom dia!", sizeof texto - 1); strncpy
O primeiro parâmetro de strncpy
é a variável que receberá o valor. O segundo parâmetro é o valor que será atribuído, que pode ser uma constante ou outra variável. Há, ainda, um terceiro parâmetro, que é o tamanho da variável, que é importante para garantir que o limite de espaço reservado para a variável será respeitado. Ultrapassar o tamanho da variável pode trazer consequências imprevisíveis à execução.
Existem funções de manipulação de cadeias de caracteres que não verificam o tamanho da variável destino. É importante nunca usá-las.
17.2.3 Concatenação de cadeias de caracteres
Além da cópia de uma sequência de caracteres para uma variável, é possível estender seu conteúdo, fazendo a concatenação. A função strncat
(string catenation) faz a cópia de uma cadeia anexando-a a outra.
/*
Criação de uma única linha a partir de leituras separadas
Requer: Uma sequência de linhas de texto
Assegura: apresentação da concatenação de todas as linhas em uma só
*/
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int main(void) {
char texto[160];
char linha_unica[5000];
// Inicia uma cadeia vazia
(linha_unica, "", sizeof linha_unica - 1);
strncpy
// Acrescenta cada linha digitada à linha única
("Digite linhas, usando Ctrl-D para encerrar:\n");
printfbool primeira_palavra = true;
while (fgets(texto, sizeof texto, stdin) != NULL) {
[strlen(texto) - 1] = '\0';
textoif (primeira_palavra)
= false;
primeira_palavra else
(linha_unica, " ",
strncatsizeof linha_unica - strlen(linha_unica) - 1);
(linha_unica, texto,
strncatsizeof linha_unica - strlen(linha_unica) - 1);
}
// Texto total
("\n\"%s\"\n", linha_unica);
printf
return 0;
}
Digite linhas, usando Ctrl-D para encerrar:Era
uma
vez
uma linda menina
que possuia uma capa vermelha com
capuz.
"Era uma vez uma linda menina que possuia uma capa vermelha com capuz."
A função de concatenação acrescenta à variável do primeiro parâmetro (linha_unica
) uma cópia dos caracteres contidos no segundo parâmetro (texto
). O terceiro parâmetro é a quantidade máxima de caracteres a serem copiados, a qual é usada para respeitar o tamanho do espaço da variável destino. No código, a quantidade máxima para cada concatenação corresponde ao cálculo do espaço livre existente em linha_unica
, respeitando um byte para ter espaço para o \0
final.
17.2.4 Comparações de cadeias de caracteres
A comparação entre duas cadeias de caracteres é feita no sentido alfabético usual, sempre comparando os primeiros caracteres das duas cadeias e, sendo iguais, passando para os segundos, terceiros e assim por diante. Nas funções de string.h
, a função strncmp
(string comparison) tem a finalidade realizar as comparações.
A função strncmp
retorna sempre um valor inteiro, como apresentado na Tabela 17.1.
strncmp
.
Resultado | Significado |
---|---|
zero | Iguais |
menor que zero | Anterior |
maior que zero | Posterior |
Segue um programa ilustrando o uso de strncmp
.
/*
Comparações de cadeias de caracteres
Requer: a digitação de pares de palavras em cada linha
Assegura: a apresentação da comparação entre as palavras de cada par
*/
#include <stdio.h>
#include <string.h>
int main(void) {
char linha[160];
("Digite duas palavras por linha, usando Ctrl-D para encerrar:\n");
printfwhile (fgets(linha, sizeof linha, stdin) != NULL) {
char palavra1[80], palavra2[80];
(linha, "%79s%79s", palavra1, palavra2); // palavras simples
sscanf
if (strncmp(palavra1, palavra2, sizeof palavra1) == 0)
("%s é igual a %s.\n", palavra1, palavra2);
printfelse if (strncmp(palavra1, palavra2, sizeof palavra1) < 0)
("%s é anterior a %s.\n", palavra1, palavra2);
printfelse
("%s é posterior a %s.\n", palavra1, palavra2);
printf}
return 0;
}
Digite duas palavras por linha, usando Ctrl-D para encerrar:abacaxi abacaxi
abacaxi é igual a abacaxi.marca marcas
marca é anterior a marcas.vermelho azul
vermelho é posterior a azul.azul vermelho
azul é anterior a vermelho.contraponto contraindicado
contraponto é posterior a contraindicado.
Uma discussão sobre comparações de palavras acentuadas é apesentada na Seção 17.5.
17.3 Mais sobre declaração de variáveis textuais
Assim como variáveis aritméticas e lógicas, variáveis literais também podem ser iniciadas na declaração. Há formatos diferentes para essa iniciação.
O programa seguinte ilustra os diferentes formatos, os quais serão abordados individualmente na sequência.
/*
Exemplificação de declaração de cadeias de caracteres juntamente com iniciação
Assegura: apresentação dos textos atribuídos e do tamanho de cada variável
*/
#include <stdio.h>
int main(void) {
// Referência a uma constante
char *texto1 = "Um texto constante e fixo";
("texto1 = '%s'.\n", texto1);
printf
// Variável com comprimento explícito
char texto2[100] = "Uma variável de até 99 posições";
("texto2 = '%s'.\n", texto2);
printf
// Variável com comprimento automático
char texto3[] = "Variável com comprimento dependente do valor atribuído";
("texto3 = '%s'.\n", texto3);
printf
// Comprimentos das variáveis
("\ntexto1: %zu bytes, pois é apenas referência a uma constante.\n",
printfsizeof texto1);
("texto2: %zu bytes, conforme tamanho especificado.\n",
printfsizeof texto2);
("texto3: %zu bytes, pois depende do texto de iniciação.\n",
printfsizeof texto3);
return 0;
}
texto1 = 'Um texto constante e fixo'.
texto2 = 'Uma variável de até 99 posições'.
texto3 = 'Variável com comprimento dependente do valor atribuído'.
texto1: 8 bytes, pois é apenas referência a uma constante.
texto2: 100 bytes, conforme tamanho especificado. texto3: 57 bytes, pois depende do texto de iniciação.
O primeiro formato é o utilizado na Seção 16.3, que declara uma variável que é apenas uma referência a um texto em outro lugar. No caso, esse texto é uma constante que o compilador insere no código fonte. Ao longo do código, a variável texto1
pode ser alterada de forma a apontar para outro texto.
char *texto = "Texto"; // a variável é uma referência à constante "Texto"
Outra possibilidade é a mais usual, criando-se um vetor de caracteres com um tamanho predeterminado e, juntamente a isso, fazer a cópia de um valor para ele. Para o caso da variável texto2
do programa, há a alocação de um espaço total de 100 bytes, permitindo um texto de até 99 bytes. Ao fazer a declaração, um cópia da constante textual é feita para a variável. Como texto2
recebe uma cópia, os dados da variável podem ser alterados.
char *texto[20] = "Texto"; // a variável tem 20 posições, usando as 6
// primeiras para guardar "Texto" e \0
Finalmente, texto3
é uma variável declarada como texto2
, porém omitindo seu comprimento. Neste caso, a variável é criada com capacidade para guardar exatamente o valor atribuído, ou seja, o espaço para os caracteres e para o \0
terminal.
char *texto[] = "Texto"; // a variável tem exatamente as 6 posições
// necessárias para guardar "Texto" e \0
É importante lembrar que as declarações que usam os colchetes, seja com tamanho explícito ou omitido, o espaço reservado para a variável deve sempre ser respeitado.
17.4 Acesso direto ao conteúdo
Uma forma prática de usar cadeias de caracteres é fazendo acesso a cada posição individual do vetor. Para isso, é possível indicar um char
qualquer armazenado especificando sua posição no vetor.
O programa seguinte mostra como cada posição de uma cadeia de caracteres pode ser acessada.
/*
Apresentação de um texto caractere a caractere
Requer: um texto digitado pelo usuário
Assegura: apresentação de cada caractere, posição a posição
*/
#include <stdio.h>
#include <string.h>
int main(void) {
("Digite um texto qualquer:\n");
printfchar texto[160];
(texto, sizeof texto, stdin);
fgets
for (int posicao = 0; posicao < strlen(texto) - 1; posicao++)
("%2d: '%c'\n", posicao, texto[posicao]);
printf
return 0;
}
Digite um texto qualquer:Subi no ombro de gigantes!
0: 'S'
1: 'u'
2: 'b'
3: 'i'
4: ' '
5: 'n'
6: 'o'
7: ' '
8: 'o'
9: 'm'
10: 'b'
11: 'r'
12: 'o'
13: ' '
14: 'd'
15: 'e'
16: ' '
17: 'g'
18: 'i'
19: 'g'
20: 'a'
21: 'n'
22: 't'
23: 'e'
24: 's' 25: '!'
A variável texto
possui um espaço de armazenamento para 160 caracteres simples. Cada uma dessas posições pode ser indica por um índice, que vai de zero a 159. Assim, o primeiro caractere do texto está em texto[0]
, o segundo em texto[1]
e o último em texto[strlen(texto) - 1]
. No programa, o laço de repetição claramente se inicia na posição zero, mas é relevante ressaltar que a última posição apresentada na tela é a strlen(texto) - 2
, o que evita escrever o \n
que está na última posição.
Uma das grandes fontes de erro no acesso aos índices de uma cadeia de caracteres é errar nos limites dos índices. Não é incomum, em uma repetição, faltar uma posição ou passar uma posição.
Atenção é sempre necessária nesse ponto.
Além das funções em string.h
, há algumas interessantes em ctype.h
, que permitem facilmente verificar caracteres. A Tabela 17.2 apresenta uma lista de várias funções interessantes.
ctype.h
). Todas as funções retornam um inteiro não nulo em caso de sucesso ou zero, caso contrário.
Função | Significado |
---|---|
isalpha(c) |
Verifica se c é um caractere alfabético (i.e., uma letra). |
isdigit(c) |
Verifica se c é um dígito de 0 a 9. |
isalnum(c) |
Verifica se c é alfanumérico, ou seja se é alfabético ou dígito. |
isascii(c) |
Verifica se c é um caractere ASCII do escopo de 7 bits. |
iscntrl(c) |
Verifica se c é um caractere de controle. |
islower(c) |
Verifica se c é uma letra minúscula. |
isupper(c) |
Verifica se c é uma letra maiúscula. |
isspace(c) |
Verifica se c é qualquer caractere de “espaço branco” (white-space), ou seja espaço, \f , \n , \r , e \v . |
isblank(c) |
Verifica se c é um caractere “branco” (blank), o seja, se é espaço ou tabulação. |
isprint(c) |
Verifica se c é um caractere imprimível, incluindo o espaço. |
isgraph(c) |
Verifica se c é um caractere imprimível, exceto o espaço. |
ispunct(c) |
Verifica se c é um caractere imprimível que não seja um espaço ou um caractere alfanumérico. |
isxdigit(c) |
Verifica se c for hexadecimal digits, that is, one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F. |
Para exemplificar o uso de algumas funções, segue um programa que conta alguns itens de interesse em um texto digitado pelo usuário.
/*
Contagem de maiúsculas, minúsculas, pontuação, dígitos e caracteres de
controle em um texto
Requer: um texto digitado pelo usuário
Assegura: apresentação das contagens de maiúsculas, minúsculas, pontuação,
dígitos e caracteres de controle presentes no texto
*/
#include <stdio.h>
#include <ctype.h>
int main(void) {
("Digite um texto qualquer:\n");
printfchar texto[160];
(texto, sizeof texto, stdin);
fgets
int contador_minusculas = 0;
int contador_maiusculas = 0;
int contador_pontuacao = 0;
int contador_digitos = 0;
int contador_controle = 0;
int i = 0;
while (texto[i] != '\0') {
if (islower(texto[i]))
++;
contador_minusculaselse if (isupper(texto[i]))
++;
contador_maiusculaselse if (ispunct(texto[i]))
++;
contador_pontuacaoelse if (isdigit(texto[i]))
++;
contador_digitoselse if (iscntrl(texto[i]))
++;
contador_controle
++;
i}
("Maiúsculas: %d.\n", contador_maiusculas);
printf("Minúsculas: %d.\n", contador_minusculas);
printf("Pontuação: %d.\n", contador_pontuacao);
printf("Dígitos: %d.\n", contador_digitos);
printf("Caracteres de controle: %d.\n", contador_controle);
printf
return 0;
}
Digite um texto qualquer:Moro na rua XV de Novembro, 2605
Maiúsculas: 4.
Minúsculas: 17.
Pontuação: 1.
Dígitos: 4. Caracteres de controle: 1.
Esse programa usa algumas das funções da Tabela 17.2 para fazer a contagem de alguns tipos de caracteres. O resultado para o texto Moro na rua XV de Novembro, 2605
pode ser visto diretamente. Um destaque é feito para o número de caracteres de controle, que incluiu o \n
existente no fim do texto de entrada.
17.4.1 A remoção do \n
incluído pelo fgets
Uma ação bastante comum quando a leitura de um valor textual é feito com a função fgets
é a remoção do \n
que ela deixa na cadeia de caracteres lida. Essa remoção é importante para ficar somente com o texto digitado. Em mais detalhes, essa remoção parte de dois princípios: primeiro, que a leitura com o fgets
sempre terá um \n
no seu final e, segundo, que tudo que estiver na variável a partir do \0
é ignorado.
Dessa forma, a eliminação do \n
é feita pela simples atribuição do \0
sobre ele. Como consequência, a cadeia de caracteres contém um novo final.
[strlen(texto) - 1] = '\0'; // elimina o último caractere sobrepondo
texto// a ele um novo terminador de cadeia
O programa seguinte tem o objetivo de apresentar essa remoção em detalhes, mostrando o conteúdo da variável antes e depois da eliminação do \n
.
/*
Apresentação de todos os valores contidos em uma variável literal
Requer: um texto de até 24 caracteres digitados pelo usuário
Assegura: apresentação detalhada do texto posição a posição antes e
depois da remoção do \n remanescente do fgets
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void) {
// Leitura do texto
char texto[25];
("Digite um texto qualquer:\n");
printf(texto, sizeof texto, stdin);
fgets
// Apresentação do vetor inteiro
("\nAntes:\n");
printffor (int i = 0; i < (int)sizeof texto; i++)
("%3d", i);
printf("\n");
printffor (int i = 0; i < (int)sizeof texto; i++) {
if (texto[i] == '\0')
(" \\0");
printfelse if (texto[i] == '\n')
(" \\n");
printfelse if (texto[i] == ' ')
(" ");
printfelse if (isprint(texto[i]))
("%3c", texto[i]);
printfelse
(" ??");
printf}
("\n");
printf
// Remoção do \n final
[strlen(texto) - 1] = '\0'; // remoção do \n
texto
// Reapresentação do vetor depois da alteração
("\nDepois:\n");
printffor (int i = 0; i < (int)sizeof texto; i++)
("%3d", i);
printf("\n");
printffor (int i = 0; i < (int)sizeof texto; i++) {
if (texto[i] == '\0')
(" \\0");
printfelse if (texto[i] == '\n')
(" \\n");
printfelse if (texto[i] == ' ')
(" ");
printfelse if (isprint(texto[i]))
("%3c", texto[i]);
printfelse
(" ??");
printf}
("\n");
printf
return 0;
}
Digite um texto qualquer:Teste
Antes:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
T e s t e \n \0 ~ ) ?? ?? ?? @ ?? ?? \0 | ?? T ?? ?? \0 ?? ?? v
Depois:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 T e s t e \0 \0 ~ ) ?? ?? ?? @ ?? ?? \0 | ?? T ?? ?? \0 ?? ?? v
O objetivo desse programa é apresentar todas as posições da variável, incluindo as inválidas depois do \0
final. Na saída, os valores \n
e \0
são verificados para serem apresentados de forma coerente, enquanto quaisquer caracteres não imprimíveis são apresentados como ??
. Para visualização, o vetor foi definido com tamanho 25. Tudo que está depois do \0
é, naturalmente, lixo.
Pode-se observar que depois da leitura, a posição 5 contém o \n
e a 6 o \0
final. Depois da eliminação do \n
, há um \0
na posição 5, fazendo com que o conteúdo válido seja somente as posições de 0 a 4.
17.5 Acentuações nas cadeias de caracteres
Como abordado na Seção 16.2.1, o uso de Unicode como tabela de caracteres e sua a codificação UTF-8 são bastante comuns nos sistemas computacionais atuais e seu suporte em C é muito limitado. Há, entretanto, uma boa notícia. Da forma em que foi desenvolvido o sistema de representação de caracteres com múltiplos bytes, as funções especificadas em string.h
continuam funcionando a contento. Há, claro, exceções.
A função strncpy
apenas copia todos os bytes até que o terminador \0
seja encontrado. Assim, independentemente da codificação adotada, a cópia é fiel ao original. O mesmo raciocínio se aplica a strncat
. Na comparação por meio de strncmp
, a comparação pela igualdade funciona perfeitamente, pois se o texto é igual, também é sua codificação UTF-8, e a comparação ocorre entre os bytes e não entre os caracteres representados em si.
A comparação por desigualdade com strncmp
, como abordado na Seção 17.2.4, tem suas limitações, uma vez que, por exemplo, Y
vem antes de b
na ordenação das tabelas de caracteres. Com UTF-8, essas limitações são agravadas. Por exemplo, "aí"
é codificado para a sequência de bytes 97, 195 e 173 (a
usa um byte, enquanto í
necessita de dois) e "abc"
tem codificação 97, 98 e 99 (um byte para cada letra), de modo que na comparação, b
é comparado com uma parte de í
e c
é emparelhado com o seu segundo byte. Nada disso é coerente.
A pior situação fica com strlen
, que retorna sempre o número de bytes e não o de caracteres. Ela é prática para determinar o número de caracteres simples do início até o \0
, mas não considera múltiplos bytes por caractere.
Quando o espaço total na variável comporta o conteúdo que está sendo atribuído ou concatenado, o comportamento descrito até agora prevalece. O problema ocorre quando não há espaço e somente parte de um caractere de múltiplos bytes é copiada. O resultado, então, é um caractere inválido.
O programa seguinte ilustra o uso de caracteres acentuados nas strings.
/*
Ilustração do uso de acentuação em cadeias de caracteres e algumas de suas
limitações
Assegura: apresentação de atribuições bem sucedidas, da incoerência no
comprimento da string e falha na atribuição parcial de um caractere
longo
*/
#include <stdio.h>
#include <string.h>
int main(void) {
char texto[160];
// Situação normal
(texto, "Acentuação e Unicode são assim", sizeof texto - 1);
strncpy("%s.\n", texto);
printf(texto, ": hvaða tungumál er þetta?", sizeof texto - strlen(texto) - 1);
strncat("%s\n", texto);
printf
// Comprimento é infiel ao número de caracteres
(texto, "Ímã", sizeof texto - 1);
strncpy("'%s' tem comprimento %zu.\n", texto, strlen(texto));
printf
// Problema com espaço insuficiente
char texto_pequeno[5]; // cabem 4 bytes
(texto_pequeno, texto, sizeof texto_pequeno - 1);
strncpy("Atribuição parcial: '%s'.\n", texto_pequeno);
printf
return 0;
}
Acentuação e Unicode são assim.
Acentuação e Unicode são assim: hvaða tungumál er þetta?
'Ímã' tem comprimento 5. Atribuição parcial: 'Ím�'.
Nesse programa, a atribuição e uso de textos em Unicode funcionam normalmente no geral. O comprimento, como é o número de bytes, pode não corresponder ao número de caracteres. Um problema mais grave ocorre quando um caractere é copiado de forma incompleta, como ocorre quando apenas o primeiro byte que forma o ã
é transferido por não haver espaço na variável texto_pequeno
.
A conclusão é que, havendo espaço suficiente para o armazenamento, a codificação de caracteres pode ser usada com as funções convencionais sem uma implicação negativa significativa. Isso ocorre para a maioria dos casos e, em geral, não é uma preocupação muito grande. Ainda vale apontar que wchar.h
contém funções específicas para trabalhar com caracteres de múltiplos bytes.
Declarar variáveis texto com espaço um pouco superdimensionado ajuda a evitar problemas, principalmente quando se espera uma variabilidade grande no comprimento dos textos. Esse é o caso de uma variável para guardar um nome.
Variáveis mais “apertadas” se justificam quando a variabilidade de comprimento é muito pequena. Para exemplificar, o armazenamento de um CPF pode usar comprimento 15, pois o comprimento é sempre fixo com 14 caracteres (dígitos, pontos e hífen). Neste caso, não há necessidade de folga.