Introdução aos caracteres

Nesta seção examinaremos resumidamente como utilizar caracteres tanto em C quanto em Python. Desse modo, quem está aprendendo uma das linguagens poderá aprender o funcionamento equivalente na outra.

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^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).

Assim as linguagens de programação possibilita 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 estabelecer uma tabela de conversão, por exemplo, que indique que a sequência `110000` deve ser interpretada como o caracteres `'0'`, que corresponde ao decimal `1*2^5 + 1*2^4 + 0*2^3 + 0*2^3 + 0*2^2 + 0*2^1 + 0*2^0 = 32+16 = 48`.

Código ASCII

Um primeiro padrão para representar os caracteres é 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 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 pratica eles utilizavam apenas 7 bits, ou seja, usavam 128 diferentes caracteres.

Como exemplos de código ASCII a letra 'A' é associada ao natural 65, o 'B' ao 66 e assim por diante. Do mesmo modo, o 'a' é associada ao natural 97 e o caractere 'z' ao 122. Já o natural 48 é associado do dígito '0', o 49 ao '1' e assim por diante até o 57 associado '9'.

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

Como já citado nas outras seções, 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 de uma função especial para leitura de caracteres, a função `raw_input()`. 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_intput(); # leia como "caractere"
    print(x);

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

Constantes do tipo caractere em C e em Python

Assim como várias outras linguagens, C e Python, adotam o uso de apóstrofes para indicar que deve pegar o caractere entre os apóstrofes. 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 imprime primeiro o caractere associado ao código ASCII dado e depois o contrário. Ao rodar este código será impresso os caracteres de código 48, 49, 97, 98, 65 e 66, respectivamente '0', '1', 'a', 'b', 'A' e 'B'.

Tab. 3. Sobre conversão entre o caractere ASCII e seu código inteiro

C | Python 2
--- | ---

    #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(" ", val1, " | ", chr(val1)) # A funcao chr(...) devolve
      print(" ", val2, " | ", chr(val2)) # o caractere associado ao
      print(" ", num1, " | ", chr(num1)) # codigo ASCII dado
      print(" ", num2, " | ", chr(num2))
      print(" ", Num1, " | ", chr(Num1))
      print(" ", Num2, " | ", chr(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("  ", charN1, " | ", ord(charN1)) # A funcao ord(...) devolve
      print("  ", charN2, " | ", ord(charN2)) # o codigo ASCII do caractere dado
      print("  ", char1, " | ", ord(char1))
      print("  ", char2, " | ", ord(char2))
      print("  ", Char1, " | ", ord(Char1))
      print("  ", Char2, " | ", ord(Char2))
    main()

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 é o 48, então o 49 é para o 1 e assim por diante. Do mesmo modo, sendo 65 o código do caractere A, 66 é o caractere B e assim por diante.

Assim, podemos fazer um código para gerar tabelas dos caracteres e seu código ASCII, como ilustrado abaixo. Experimente alterar os limites do controle do laço, mas cuidado com os caracteres especiais, alguns podem "quebrar" linhas ou corresponder a outros caracteres de controle que podom deixar a tela "suja".

Em C a converçã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 2
--- | ---

    #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, com eventuais valores a serem substituidos, deve vir uma lista de variáveis/valores compatíveis. No exemplo, a cadeia era formada por `" %3d : %3c"`, portanto deveria vir a seguir 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:
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) e cortada a parte sobre numero em ponto flutuante
2017/05/01: primeira versão