Introdução aos caracteres

[ Erros | Código ASCII | Entrada/saída ]

Nesta seção examinaremos resumidamente como utilizar caracteres tanto em C quanto em Python.

Interpretando sequência de bits como número ou 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. exemplo, a sequência `1000001` poderia ser interpretada como um valor inteiro (neste caso seria o valor 65 = 1*26+1*20) ou como um caractere (nesse caso a letra A, vide abaixo explicação sobre código ASCII). De modo semelhante, se a sequência `110000` deve ser interpretada como caractere, seria o dígito 0, por outro lado, se for interpretada como inteiro (desconsiderando a questão do sinal), seria o 48 = 1*25+1*24 = 32 + 16). Ou seja, existe uma tabela associando valor numérico e caractere, como explicado na seção abaixo.

Resumidamente o tratamento de dados em um computador digital, se resume à processar sequências de digitos. Assim, ao tentar examinar determinado dado em memória, deve-se saber em que posição da memória o dado está em um quanto bits tem tal dado. A figura ilustra isso, com 3 variáveis de tamanho 1 bytes (a, b e c) e uma ocupando 2 bytes (x). No caso de caracteres (símbolos que devem ser apresentados, como é o caso dos dígitos e das letras), basta existir uma associação (ou mapeamento) entre os bits e o símbolo a ser mostrado. Claro que está associação depende também do tamanho, quanto bits são usados para representar cada símbolo. Na seção seguinte apresento a primeira tabela de associação entre bits e símbolos, a tabela ASCII.

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

Mas o tratamento de números reais apresentam questões mais difíceis, para começar não existem valores que, por maior que seja a precisão do equipamento, seria impossível representá-los. Um exemplo simples é o valor correspondente à fração 1/3, que é uma dízima periódica, portanto com dígitos (0.3333...). Além disso existe a dificuldade de representar número grande e número muito próximos de zero. O truque usual para simular reais (representação em ponto flutuante), estude esse assunto no texto sobre representação em ponto flutuante.

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 apenas 8 bits para representar todos os possíveis caracteres, o que resultava em um número reduzidíssimo de 512 códigos/símbolos distintos.

Como o código ASCII foi baseado no alfabeto em lingua Inglesa, eles presentam apenas caracteres sem acentos. Usualmente associamos um natural a cada símbolo, assim no ASCII pode-se associar caracteres aos códigos ASCII 0 até 512.

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 como caractere deve-se indicar isso ao computador de alguma forma. Tanto a linguagem C como a linguagem Python dispõe um tipo especial variável para tratar com caracteres.

Na linguagem C tem o tipo `char`, que precisa do formatador `%c`, mas pode-se imprimir uma variável `char` como inteiro e vice-versa, neste caso usa-se seu código ASCII. Já em Python 2 é preciso de uma função especial para leitura (a `raw_input()`) e na impressão não é preciso qualquer diferenciação, pois Python aplica um filtro para tratar se a variávem sendo impressa é inteira, flutuante ou caractere. Vide tabela 1 abaixo.

Tab. 1. Sobre a leitura de caracteres em C e em Python

C | Python 2 | Python 3
--- | --- | ---

    char x; // declaracao de variavel em "ponto flutuante"
    scanf("%c", &x); // leia como "caractere"
    <verd>printf</verd>("%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"
    <verd>print</verd>(x);

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

Vale notar que para atribuir constantes do tipo caractere, é necessário que um único caractere esteja cercado por aspas simples. 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).

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. 2. Sobre conversão entre o caractere ASCII e seu código inteiro

C | Python 2
--- | ---

    #include <stdio.h>
    <verm>int</verm> main (void) {
      <verm>int</verm>          <cyan>// Criando 6 variaveis como (implicitamente) do tipo "int".</cyan>
        val1 = 48, <cyan>// Cada variavel recebera um valor inteiro que depois sera'</cyan>
        val2 = 49, <cyan>// interpretado como caractere.</cyan>
        num1 = 97,
        num2 = 98,
        Num1 = 65,
        Num2 = 66;
      <verm>char</verm>            <cyan>// Declarando variaveis tipo caractere</cyan>
        charN1 = '0', <cyan>// NOTE que para constantes do tipo</cyan>
        charN2 = '1', <cyan>// caractere, deve-se usar aspa simples</cyan>
        Char1  = 'A',
        Char2  = 'B',
        char1  = 'a',
        char2  = 'b';
      <verd>printf</verd>(" int | codigo\n"); <cyan>// '\n' usado para forcar quebra de linha na impressao</cyan>
      <verd>printf</verd>("  %d | %c\n", val1, val1);
      <verd>printf</verd>("  %d | %c\n", val2, val2);
      <verd>printf</verd>("  %d | %c\n", num1, num1);
      <verd>printf</verd>("  %d | %c\n", num2, num2);
      <verd>printf</verd>("  %d | %c\n", Num1, Num1);
      <verd>printf</verd>("  %d | %c\n", Num2, Num2);
      <verd>printf</verd>(" int | codigo\n");
      <verd>printf</verd>(" %c | %d\n", charN1, charN1);
      <verd>printf</verd>(" %c | %d\n", charN2, charN2);
      <verd>printf</verd>(" %c | %d\n", char1,  char1);
      <verd>printf</verd>(" %c | %d\n", char2,  char2);
      <verd>printf</verd>(" %c | %d\n", Char1,  Char1);
      <verd>printf</verd>(" %c | %d\n", Char2,  Char2);
      return 0;
      }

    <verm>def</verm> main():
      val1 = 48 <cyan># Criando 6 variaveis como (implicitamente) do tipo "int".</cyan>
      val2 = 49 <cyan># Cada variavel recebera um valor inteiro que depois sera'</cyan>
      num1 = 97 <cyan># interpretado como caractere.</cyan>
      num2 = 98
      Num1 = 65
      Num2 = 66
      <verd>print</verd>(" int | codigo")
      <verd>print</verd>(" ", val1, " | ", chr(val1)) <cyan># A funcao chr(...) devolve</cyan>
      <verd>print</verd>(" ", val2, " | ", chr(val2)) <cyan># o caractere associado ao</cyan>
      <verd>print</verd>(" ", num1, " | ", chr(num1)) <cyan># codigo ASCII dado</cyan>
      <verd>print</verd>(" ", num2, " | ", chr(num2))
      <verd>print</verd>(" ", Num1, " | ", chr(Num1))
      <verd>print</verd>(" ", Num2, " | ", chr(Num2))
      charN1 = '0' <cyan># NOTE que para constantes do tipo</cyan>
      charN2 = '1' <cyan># caractere, deve-se usar aspa simples</cyan>
      Char1 = 'A'
      Char2 = 'B'
      char1 = 'a'
      char2 = 'b'
      <verd>print</verd>(" int | codigo")
      <verd>print</verd>("  ", charN1, " | ", ord(charN1)) <cyan>#</cyan> A funcao ord(...) devolve</cyan>
      <verd>print</verd>("  ", charN2, " | ", ord(charN2)) <cyan>#</cyan> o codigo ASCII do caractere dado</cyan>
      <verd>print</verd>("  ", char1, " | ", ord(char1))
      <verd>print</verd>("  ", char2, " | ", ord(char2))
      <verd>print</verd>("  ", Char1, " | ", ord(Char1))
      <verd>print</verd>("  ", Char2, " | ", ord(Char2))
    main()

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

Alterações:
2020/08/10: nova versão, sem a parte de "float";
2019/07/31: acerto no formato da página e em várias frases;
2017/05/01: versão inicial