<!-- Introdução aos caracteres Prof. Leônidas de Oliveira Brandão Material didático para apoio aos cursos de Introdução à Programação Direitos reservados Pode ser usado mediante citação de autoria (Prof. Leônidas de Oliveira Brandão) e origem (https://www.ime.usp.br/~leo/mac2166/introducao/) Versao 2 [2018/04/28] Revisao, acerto no 2^8 (que estava 512...) Versao 1 [2017/05/01] --> <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'> <meta name='keywords' content='mac0122, material, professores, leonidas de oliveira brandao'> <link rel='stylesheet' type='text/css' href='css_img_js_conf/all.css'> <link rel='stylesheet' type='text/css' href='css_img_js_conf/line_introducao_programacao.css'> <script src="css_img_js_conf/defineLInE.js"></script> <!-- para referencias 'a documentos internos --> <div class="pagina"> <p class="secao">Introdução aos caracteres</p> <!-- <center><p>[ <a href="#erro">Erros</a> | <a href="#pontoflutuante">Ponto flutuante</a> | <a href="#exemplo">Exemplo</a> | <a href="#io">Entrada/saída</a></a> ]</p> </center> --> <p> Nesta seção examinaremos resumidamente como utilizar caracteres tanto em <em>C</em> quanto em <em>Python</em>. Desse modo, quem está aprendendo uma das linguagens poderá aprender o funcionamento equivalente na outra. </p> <a name="caracteres"><span style="color: #0050A0">Representação como caractere</span></a> <p> Como citado na seção sobre <a href="#" onclick="trocaPagina('introducao_var.html')" title="variaveis">variáveis</a>, a informação básica nos computadores digitais é uma sequência de <i>bits</i> e o contexto é quem indica como estes <i>bits</i> devem ser interpretados. Por exemplo, a sequência com 6 <i>bits</i> <tt>100001</tt>, poderia ser interpretada como um valor inteiro e neste caso seria o valor 33, pois <tt>1*2^5 + 0*2^4 + 0*2^3 + 0*2^3 + 0*2^2 + 0*2^1 + 1*2^0 = 32+1 = 33</tt>. Por outro lado, a mesma sequência poderia ser interpretada como um caractere, no caso o <tt>'!'</tt> (exclamação). </p> <p> <!-- Um exemplo do problema numérico está ilustrado no exemplo abaixo, quando tentamos imprimir as somas de <tt>0.1</tt> --> Assim as linguagens de programação possibilita a interpretação de uma sequência de <i>bits</i> 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 <tt>110000</tt> deve ser interpretada como o caracteres <tt>'0'</tt>, que corresponde ao decimal <tt>1*2^5 + 1*2^4 + 0*2^3 + 0*2^3 + 0*2^2 + 0*2^1 + 0*2^0 = 32+16 = 48</tt>. </p> <a name="ascii"> <p class="subsecao">Código ASCII</p> </a> <p> Um primeiro padrão para representar os caracteres é o <a href="https://en.wikipedia.org/wiki/ASCII" title="ver detalhes na WikiPedia" target="_blank"><b>American Standard Code for Information Interchange</b></a>. O padrão ASCII é bastante antigo, ainda da década de 1960 e por isso utiliza um número reduzido de <i>bits</i>, somente 8, o que possibilita a codificação de apenas <i>2<sup>8</sup>=256</i> símbolos distintos. <!-- codigos/ --> </p> <center> <a name="tab1"> <i>Tab. 1. Os 20 primeiros números naturais na base binária (0, 1) e correspondente decimal</i> </a> <br/> <table><tr><td> <table class="tbCodeLinCol"> <tr><th>Binário</th> <th>Decimal</th></tr> <tr><td><tt>00000000</tt></td><td align="right"><tt> 0</tt></td></tr> <tr><td><tt>00000001</tt></td><td align="right"><tt> 1</tt></td></tr> <tr><td><tt>00000010</tt></td><td align="right"><tt> 2</tt></td></tr> <tr><td><tt>00000011</tt></td><td align="right"><tt> 3</tt></td></tr> <tr><td><tt>00000100</tt></td><td align="right"><tt> 4</tt></td></tr> <tr><td><tt>00000101</tt></td><td align="right"><tt> 5</tt></td></tr> <tr><td><tt>00000110</tt></td><td align="right"><tt> 6</tt></td></tr> <tr><td><tt>00000111</tt></td><td align="right"><tt> 7</tt></td></tr> <tr><td><tt>00001000</tt></td><td align="right"><tt> 8</tt></td></tr> <tr><td><tt>00001001</tt></td><td align="right"><tt> 9</tt></td></tr> </table></td> <td> <table class="tbCodeLinCol"> <tr><th>Binário</th> <th>Decimal</th></tr> <tr><td><tt>00001010</tt></td><td align="right"><tt> 10</tt></td></tr> <tr><td><tt>00001011</tt></td><td align="right"><tt> 11</tt></td></tr> <tr><td><tt>00001100</tt></td><td align="right"><tt> 12</tt></td></tr> <tr><td><tt>00001101</tt></td><td align="right"><tt> 13</tt></td></tr> <tr><td><tt>00001110</tt></td><td align="right"><tt> 14</tt></td></tr> <tr><td><tt>00001111</tt></td><td align="right"><tt> 15</tt></td></tr> <tr><td><tt>00010000</tt></td><td align="right"><tt> 16</tt></td></tr> <tr><td><tt>00010001</tt></td><td align="right"><tt> 17</tt></td></tr> <tr><td><tt>00010010</tt></td><td align="right"><tt> 18</tt></td></tr> <tr><td><tt>00010011</tt></td><td align="right"><tt> 19</tt></td></tr> </table></td></tr> </table></center> </p> <p> Como o padrão <i>ASCII</i> foi criado nos Estados Unidos e a lingua Inglesa não utiliza símbolos especiais, na pratica eles utilizavam apenas 7 <i>bits</i>, ou seja, usavam 128 diferentes caracteres. <!-- 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 <b>códigos ASCII</b> 0 até 256. --> </p> <p> 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'. </p> <a name="io"> <p class="subsecao">Entrada e saída de caracteres em <i>C</i> e em <i>Python</i></p> </a> <p> Como já citado nas outras seções, o contexto deve definir como sequências de <i>bits</i> devem ser tratadas. Para tratar um conjunto <i>bits</i> 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. <!-- Tanto a linguagem <i>C</i> como a linguagem <i>Python</i> dispõe um tipo especial variável para tratar com caracteres. --> </p> <p> Na linguagem <i>C</i> existe o tipo <tt>char</tt> e tanto para leitura quanto para impressão, utiliza-se o formatador <tt>%c</tt>. Mas pode-se imprimir uma variável <tt>char</tt> como se fosse um número inteiro e vice-versa, neste caso usa-se seu código ASCII. </p> <p> Já em <i>Python 2</i> é preciso de uma função especial para leitura de caracteres, a função <tt>raw_input()</tt>. Na impressão, se não for usada impressões especiais, não é preciso qualquer diferenciação, pois o <i>Python</i> aplica um filtro para tratar se a variávem sendo impressa é inteira, flutuante ou caractere. Vide <a href="#tab2">tabela</a> abaixo. </p> <center> <a name="tab2"> <i>Tab. 2. Sobre a leitura de caracteres em <i>C</i> e em <i>Python</i></i> </a> <br/> <table class="tbCodeLinCol"> <tr><th>C </th> <th>Python 2</th> <th>Python 3</th></tr> <tr valign="top"><td><table class="tbCode"> <tr><td><pre>char x; // declaracao de variavel para armazenar caracteres scanf("%c", &x); // leia como "caractere" printf("%c", x); // imprima como "caractere" </pre></td></tr> </table></td> <td><table class="tbCode"><pre># 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); </pre></td></tr> </table></td> <td><table class="tbCode"><pre># Vale notar: se o usuario digitar uma "string", como # "nome", a variavel x recebera' a "string" toda x = intput(); # leia como "caractere" print(x); </pre></td></tr> </table></td> </tr> </table></center> </p> <a name="constantes"> <p class="subsecao">Constantes do tipo caractere em <i>C</i> e em <i>Python</p> </a> <p> Assim como várias outras linguagens, <i>C</i> e <i>Python</i>, 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 <tt>varc</tt>, deve-se usar <center><tt>varc = 'a';</tt> (o finalizador ';' é opcional em <i>Python</i>).</center> <br/> A necessidade de um marcador pode ser facilmente entendida ao escrevermos o código <tt>varc = a;</tt>, que corresponde a guardar o valor atual da variável <i>a</i> na variável <i>varc</i>. </p> <p> 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'. <center> <i>Tab. 3. Sobre conversão entre o caractere ASCII e seu código inteiro</i> <br/> <table class="tbCodeLinCol"> <tr><th>C </th> <th>Python 2</th></tr> <tr valign="top"><td><table class="tbCode"> <tr><td><pre>#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; }</pre></td></tr> </table></td> <td><table class="tbCode"><pre>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()</pre></td></tr> </table></td></tr> </table></center> </p> <a name="tabela"> <p class="subsecao">Como gerar uma tabelas ASCII em <i>C</i> e em <i>Python</p> </a> <p> Vale destacar que a codificação dos caracteres segue uma organização lógica, uma vez que o código para o caractere <i>0</i> é o <i>48</i>, então o <i>49</i> é para o <i>1</i> e assim por diante. Do mesmo modo, sendo <i>65</i> o código do caractere <i>A</i>, <i>66</i> é o caractere <i>B</i> e assim por diante. </p> <p> 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". </p> <p> Em <i>C</i> a converção entre inteiro ou caractere é praticamente direta, bastando usar o formatador correto (<tt>%d</tt> para inteiro ou <tt>%c</tt> para caractere). Entretanto em <i>Python</i> é necessário usar duas funções pré-definidas para isso, <tt>ord(inteiro)</tt> e <tt>chr(caractere)</tt>: sendo <tt>i</tt> inteiro, <tt>chr(i)</tt> fornece o caractere cujo código é <tt>i</tt>; sendo <tt>c</tt> caractere, <tt>ord(c)</tt> fornece o código do caractere <tt>c</tt>. </p> <center> Tab. 4. Como imprimir uma tabela código ASCII e o correspondente caractere<br/> <table class="tbCodeLinCol"> <tr><th>C </th> <th>Python 2</th></tr> <tr valign="top"><td><table class="tbCode"> <tr><td><pre>#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; }</pre></td></tr> </table></td> <td><table class="tbCode"><pre>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();</pre></td></tr> </table></td></tr> </table></center> </p> <p> Primeiro notem que usamos os formatadores <tt>%3d</tt> e <tt>%3c</tt> para ajustar 3 colunas à direita, o que é bastante útil para imprimir tabelas. O <tt>%d</tt> é utilizado para imprimir inteiro, enquanto <tt>%c</tt> para caractere, tanto em <i>C</i>, quanto em <i>Python</i>. 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 <tt>" %3d : %3c"</tt>, portanto deveria vir a seguir 2 valores, o primeiro inteiro e o segundo caractere. </p> <p> Entretanto existe uma diferença na sintaxe das duas linguagens, em <i>C</i> a lista de parâmetros vem separadas por vírgula simples, mas em <i>Python</i> precisa do símbolo de percentagem (<tt>%</tt>) após a cadeia de caracteres (<tt>" %3d : %3c"</tt>) e, havendo mais de um valor a substituir, deve-se usar a sintaxe de <i>lista</i> (<tt>(i, chr(i))</tt>). </p> <p> Note que o <i>Python</i> precisa de uma função especial para conveter inteiro em caractere, <tt>chr(i)</tt>, que devolve o caractere cujo código seja o valor armazenado na variável <i>i</i> (que deve ser inteira). Para fazer o oposto deve-se usar a função <tt>ord(varc)</tt> que é a função que devolve o código ASCII (<i>ord</i>enado) do caractere armazenado na variável <i>varc</i> (que neste caso deve ser para caractere - <i>char</i>). </p> <p> <a href="https://www.ime.usp.br/~leo" target="_blank" title="seguir para a pagina do prof. Leônidas">Leônidas de Oliveira Brandão</a><br/> <a href="http://www.ime.usp.br/~leo" target="_blank" title="seguir para a página do LInE">http://line.ime.usp.br</a> </p> <p class="rodape"> <b>Alterações</b>:<br/> 2020/08/19: novo formato, pequenas correções<br/> 2019/04/18: acerto '0010'=4 para '100001'=33, explicita funções <tt>ord</tt> e <tt>chr</tt>)<br/> 2018/04/28: acertos no texto (valor 2^8) e cortada a parte sobre numero em ponto flutuante<br/> 2017/05/01: primeira versão </p> </div>