Introdução aos caracteres

Nesta seção examinaremos resumidamente como utilizar caracteres tanto em C quanto em Python. Desse modo, se desejar, quem está aprendendo uma das linguagens poderá aprender o funcionamento equivalente na outra, senão pode focar apenas na sua linguagem de interesse.

Representação como caractere

Como citado na seção sobre variáveis, a informação básica nos computadores digitais é uma sequência de bits e o contexto é quem indica como estes bits devem ser interpretados. Por exemplo, a sequência com 6 bits 100001, poderia ser interpretada como um valor inteiro e neste caso seria o valor 33, pois 1*2^5 + 0*2^4 + 0*2^3 + 0*2^2 + 0*2^1 + 1*2^0 = 32+1 = 33. Por outro lado, a mesma sequência poderia ser interpretada como um caractere, no caso o '!' (exclamação).


Fig. 1. Representação da memória, com 3 variáveis usando 1 bytes (8 bits) e outra usando 2 bytes.

Assim, as linguagens de programação possibilitam a interpretação de uma sequência de bits como um caractere (e.g. como uma letra ou um dígito). Deste modo para apresentá-lo é preciso definir uma tabela de conversão, por exemplo, que indique que a sequência 110000 deve ser interpretada como o caracteres '0' ou como decimal 48 (pois 1*2^5 + 1*2^4 + 0*2^3 + 0*2^2 + 0*2^1 + 0*2^0 = 32+16 = 48).

1. Código ASCII

Um primeiro padrão popular para representar os caracteres foi o American Standard Code for Information Interchange. O padrão ASCII é bastante antigo, ainda da década de 1960 e por isso utiliza um número reduzido de bits, somente 8, o que possibilita a codificação de apenas 28=256 símbolos distintos.

Tab. 1. Os 20 primeiros números naturais na base binária (0, 1) e seu correspondente decimal
Binário Decimal
00000000 0
00000001 1
00000010 2
00000011 3
00000100 4
00000101 5
00000110 6
00000111 7
00001000 8
00001001 9
Binário Decimal
00001010 10
00001011 11
00001100 12
00001101 13
00001110 14
00001111 15
00010000 16
00010001 17
00010010 18
00010011 19

Como o padrão ASCII foi criado nos Estados Unidos e a lingua Inglesa não utiliza símbolos especiais, na prática eles utilizavam apenas 7 bits, ou seja, usavam 128 diferentes caracteres.

Como exemplos de códigos ASCII podemos destacar os dígitos 0 a 9, cujos códigos são 48 até 57 e as letras do alfabeto que também seguem uma ordem numérica, a letra 'A' está associada ao natural 65, o 'B' ao 66 e assim por diante. Do mesmo modo para as letras minúsculas, a letra 'a' está associada ao natural 97 e a letra 'z' ao 122.

2. Entrada e saída de caracteres em C e em Python

Como já citado, o contexto deve definir como sequências de bits devem ser tratadas. Para tratar um conjunto bits como caractere deve-se indicar isso ao computador de alguma forma. Por exemplo, as linguagens de programação geralmente dispõem de um tipo de variável especial para caracteres.

Na linguagem C existe o tipo char e tanto para leitura quanto para impressão, utiliza-se o formatador %c. Mas pode-se imprimir uma variável char como se fosse um número inteiro e vice-versa, neste caso usa-se seu código ASCII.

Já em Python 2 é preciso usr uma função especial para leitura de caracteres, a função raw_input(), enquanto no Python 3 toda leitura é feita como leitura de caracteres. Na impressão, se não for usada impressões especiais, não é preciso qualquer diferenciação, pois o Python aplica um filtro para tratar se a variávem sendo impressa é inteira, flutuante ou caractere. Vide tabela abaixo.

Tab. 2. Sobre a leitura de caracteres em C e em Python
C Python 2 Python 3
char x; // declaracao de variavel para armazenar caracteres
scanf("%c", &x); // leia como "caractere"
printf("%c", x); // imprima como "caractere"
#  Vale notar: se o usuario digitar uma "string", como
#  "nome", a variavel x recebera' a "string" toda
x = raw_input(); #  leia como "caractere"
print(x);

#  Vale notar: se o usuario digitar uma "string", como
#  "nome", a variavel x recebera' a "string" toda
x = input(); #  leia como "caractere"
print(x);

3. Constantes do tipo caractere em C e em Python

Com o exposto até pode-se imaginar um potencial problema: como distinguir a latra (caracter) A da variável de nome A?
Várias linguagens adotam a mesma solução, para indicar tratar-se de caractere deve-se cercá-lo por apóstrofe, tanto a linguagem C quanto a linguagem Python adotam esse padrão de uso de apóstrofes para indicar caracteres. Por exemplo, para atribuir a constante 'a' à uma variável do tipo caractere, de nome varc, deve-se usar

varc = 'a'; (o finalizador ';' é opcional em Python).

A necessidade de um marcador pode ser facilmente entendida ao escrevermos o código varc = a;, que corresponde a guardar o valor atual da variável a na variável varc.

Abaixo um exemplo de código que são impressos o caractere e seu código ASCII e vice-versa. Isso é feito para os caracteres '0', '1', 'a', 'b', 'A' e 'B' e seus respectivos códigos ASCII 48, 49, 97, 98, 65 e 66. Experimente copiar o código em seu editor preferido e teste-os.

Tab. 3. Sobre conversão entre o caractere ASCII e seu código inteiro
C Python
#include <stdio.h>
int main (void) {
  int          // Criando 6 variaveis como (implicitamente) do tipo "int"
    val1 = 48, // Cada variavel recebera um valor inteiro que depois sera'
    val2 = 49, // interpretado como caractere.
    num1 = 97, //
    num2 = 98, //
    Num1 = 65, //
    Num2 = 66; //
  char            // Declarando variaveis tipo caractere
    charN1 = '0', // NOTE que para constantes do tipo
    charN2 = '1', // caractere, deve-se usar aspa simples
    Char1  = 'A', //
    Char2  = 'B', //
    char1  = 'a', //
    char2  = 'b'; //
  printf(" int | codigo\n"); // '\n' usado para forcar quebra de linha na impressao
  printf("  %d | %c\n", val1, val1);
  printf("  %d | %c\n", val2, val2);
  printf("  %d | %c\n", num1, num1);
  printf("  %d | %c\n", num2, num2);
  printf("  %d | %c\n", Num1, Num1);
  printf("  %d | %c\n", Num2, Num2);
  printf(" int | codigo\n");
  printf(" %c | %d\n", charN1, charN1);
  printf(" %c | %d\n", charN2, charN2);
  printf(" %c | %d\n", char1,  char1);
  printf(" %c | %d\n", char2,  char2);
  printf(" %c | %d\n", Char1,  Char1);
  printf(" %c | %d\n", Char2,  Char2);
  return 0;
  }
def main():
  val1 = 48 #  Criando 6 variaveis como (implicitamente) do tipo "int"
  val2 = 49 #  Cada variavel recebera um valor inteiro que depois sera'
  num1 = 97 #  interpretado como caractere.
  num2 = 98 #
  Num1 = 65 #
  Num2 = 66 #
  print(" int | codigo")
  print("  %d | %c\n", val1, val1); #  A funcao chr(...) devolve
  print("  %d | %c\n", val2, val2); #  o caractere associado ao
  print("  %d | %c\n", num1, num1); #  codigo ASCII dado
  print("  %d | %c\n", num2, num2);
  print("  %d | %c\n", Num1, Num1);
  print("  %d | %c\n", Num2, Num2);
  charN1 = '0' #  NOTE que para constantes do tipo
  charN2 = '1' #  caractere, deve-se usar aspa simples
  Char1 = 'A' #
  Char2 = 'B' #
  char1 = 'a' #
  char2 = 'b' #
  print(" int | codigo")
  print(" %c | %d\n", charN1, charN1); #  A funcao ord(...) devolve
  print(" %c | %d\n", charN2, charN2); #  o codigo ASCII do caractere dado
  print(" %c | %d\n", char1,  char1);
  print(" %c | %d\n", char2,  char2);
  print(" %c | %d\n", Char1,  Char1);
  print(" %c | %d\n", Char2,  Char2);
main()

4. Como gerar uma tabelas ASCII em C e em Python

Vale destacar que a codificação dos caracteres segue uma organização lógica, uma vez que o código para o caractere 0 (dígito "zero") é o 48, então o 49 é o código do dígito 1 e assim por diante. Do mesmo modo, sendo 65 o código do caractere A, 66 é o caractere B e assim por diante.

Portanto podemos generalizar o código da tabela 3, examinando os caracteres correspondente à um intevalo de valores numéricos. Faremos isso organizando por meio de um código imprimindo os caracteres e seus códigos ASCII na forma de uma tabela, como ilustrado abaixo. Experimente alterar os limites do controle do laço, mas atenção com os caracteres especiais, alguns podem "quebrar" linhas, outros podem corresponder à caracteres de controle que podem deixar a tela "suja" (aparecer símbolos estranhos, mudar a cor da tela, dentre outras possibilidades).

Em C a conversão entre inteiro ou caractere é praticamente direta, bastando usar o formatador correto (%d para inteiro ou %c para caractere). Entretanto em Python é necessário usar duas funções pré-definidas para isso, ord(inteiro) e chr(caractere): sendo i inteiro, chr(i) fornece o caractere cujo código é i; sendo c caractere, ord(c) fornece o código do caractere c.

Tab. 4. Como imprimir uma tabela código ASCII e o correspondente caractere
C Python
#include <stdio.h>
int main (void) {
  int i, ini = 48, fim = 58;
  printf("cod. : car.\n");
  for (i=ini; i<fim; i++)
    printf(" %3d :  %3c\n", i, i);
  printf("------------\n");
  ini = 65; fim = 91;
  for (i=ini; i<fim; i++)
    printf(" %3d :  %3c\n", i, i);
  printf("------------\n");
  ini = 97; fim = 123;
  for (i=ini; i<fim; i++)
    printf(" %3d :  %3c\n", i, i);
  printf("------------\n");   
  return 0;
  }
def main () :
  ini = 48; fim = 58;
  print("cod. : car.\n");
  for i in range(ini, fim) :
    print(" %3d :  %3c" % (i, chr(i)));
  print("------------\n");
  ini = 65; fim = 91;
  for i in range(ini, fim) :
    print(" %3d :  %3c" % (i, chr(i)));
  print("------------");
  ini = 97; fim = 123;
  for i in range(ini, fim) :
    print(" %3d :  %3c" % (i, chr(i)));
  print("------------");
     
main();

Primeiro notem que usamos os formatadores %3d e %3c para ajustar 3 colunas à direita, o que é bastante útil para imprimir tabelas. O %d é utilizado para imprimir inteiro, enquanto %c para caractere, tanto em C, quanto em Python. Logo após a cadeia de caracteres (o que está entre aspas dupla no printf ou print), deve vir uma sequência de valores/variáveis compatíveis com os formatadores (e.g., para "a=%d, b=%d, c=%c, d=%d" deve ser seguido por uma lista com duas variáveis inteiras seguida por variável caractere e por último nova variável inteira). Nos códigos, a cadeia era formada por " %3d : %3c", portanto precisa ser seguida 2 valores, o primeiro inteiro e o segundo caractere.

Entretanto existe uma diferença na sintaxe das duas linguagens, em C a lista de parâmetros vem separadas por vírgula simples, mas em Python precisa do símbolo de percentagem (%) após a cadeia de caracteres (" %3d : %3c") e, havendo mais de um valor a substituir, deve-se usar a sintaxe de lista ((i, chr(i))).

Note que o Python precisa de uma função especial para conveter inteiro em caractere, chr(i), que devolve o caractere cujo código seja o valor armazenado na variável i (que deve ser inteira). Para fazer o oposto deve-se usar a função ord(varc) que é a função que devolve o código ASCII (ordenado) do caractere armazenado na variável varc (que neste caso deve ser para caractere - char).

Leônidas de Oliveira Brandão
http://line.ime.usp.br

Alterações:

Alterações :
2022/06/05: mudanca no exemplo tab. 3 Python: usando agora %d e %c;
2021/05/24: numeração das seções, algumas correções e novas frases;
2020/08/19: novo formato, pequenas correções
2019/04/18: acerto '0010'=4 para '100001'=33, explicita funções ord e chr)
2018/04/28: acertos no texto (valor 2^8 - que estava 512...) e cortada a parte sobre numero em ponto flutuante
2017/05/01: primeira versão