MAC2166 - Introdução à Computação

11/05/2017 - Aula 14

Introdução às strings

O str é um tipo de dado um pouco diferente dos demais tipos nativos de Python (que são int, float e bool) porque valores do tipo str, diferentemente do que ocorre com os valores dos demais tipos nativos, são formados a partir da composicação de valores "menores" - os caracteres. Nesse sentido, strings têm muitas semelhanças com listas, já que uma string pode ser vista como uma lista onde cada posição contém um caracter.

Assim como fazemos com listas, nós podemos:

  • usar a função len() para saber qual é o tamanho de uma string

  • acessar uma posição específica de uma string usando o operador de indexação []

  • usar o operador de "fatiar" : para obter trechos de uma string

Veja os exemplos a seguir:

In [1]:
texto = "A minha matéria favorita é MAC2166"
print("Texto completo: %s" %(texto))
print("O texto possui %d caracteres" %len(texto))
print("O caracter na posição 3 do texto é:", texto[2])
print("O trecho de texto entre as posições 7 e 15 é:", texto[6:15])
Texto completo: A minha matéria favorita é MAC2166
O texto possui 34 caracteres
O caracter na posição 3 do texto é: m
O trecho de texto entre as posições 7 e 15 é: a matéria

Embora possamos acessar o seu valor, não podemos modificar uma posição específica de uma string usando indexação. Strings em Python são imutáveis. Essa é uma diferença importante entre strings e listas. Veja o exemplo abaixo:

In [2]:
poeminha = "Betatinha quando dorme, espalha a rama pelo chão"
poeminha[1] = "a"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-7a95dff50d37> in <module>()
      1 poeminha = "Betatinha quando dorme, espalha a rama pelo chão"
----> 2 poeminha[1] = "a"

TypeError: 'str' object does not support item assignment

Há diferentes formas de se converter valores numéricos em strings. A mais direta delas é por meio da função str(), como mostrado nos exemplos a seguir:

In [3]:
num_dois = 2
print(num_dois, "-->", type(num_dois))
str_dois = str(num_dois)   # converte o valor em num_dois para string e armazena-o em str_dois
print(str_dois, "-->", type(str_dois))
2 --> <class 'int'>
2 --> <class 'str'>

In [4]:
str_real = str(3.33333333333)
print(str_real, "-->", type(str_real))
3.33333333333 --> <class 'str'>

Uma outra forma de converter números em strings é por meio de strings de formatação, como as que frequentemente usamos nos comandos print e input, nos exercícios que fazemos em aula. Veja exemplos a seguir:

In [5]:
num_real1 = 13.2278430
num_real2 =  4.9
num_int1 = 121
num_int2 = 6
str_reais_formatados = "Números reais formatados: |%6.3f|, |%6.3f|" %(num_real1, num_real2)
print(str_reais_formatados)
str_ints_formatados = "Números inteiros formatados: |%4d|, |%4d|" %(num_int1, num_int2)
print(str_ints_formatados)
str_num_simples = "%d" %(num_int1)
print(str_num_simples, "-->", type(str_num_simples))
Números reais formatados: |13.228|, | 4.900|
Números inteiros formatados: | 121|, |   6|
121 --> <class 'str'>

O operador + (de concatenação) pode ser aplicado tanto a listas quanto a strings. O primeiro exemplo a seguir mostra um caso de uso envolvendo listas, enquanto o segundo exemplo se refere à concatenação de strings:

In [6]:
lista1 = [1,2,3]
lista2 = [9,8,7,6,5]
lista3 = lista1 + lista2 # cria uma nova lista contendo os elementos de lista1 e lista2
print(lista3)
[1, 2, 3, 9, 8, 7, 6, 5]

In [7]:
verso1 = "Como diria o Cebolinha: "
verso2 = "- Keep calm and make an infallible plan!"
citacao = verso1 + verso2  # cria uma nova string com a junção de verso1 e verso2
print(citacao)
Como diria o Cebolinha: - Keep calm and make an infallible plan!

Caracteres e uma (brevíssima) introdução sobre sua codificação

"Um caractere pode ser uma letra (maiúscula ou minúscula, um ponto final, ponto de interrogação, colchetes, enfim, símbolos que normalmente encontramos num teclado de um computador".

Em Python, um caractere é uma string de comprimento 1.

Como vimos na primeira aula deste curso, tudo o que computador armazena e processa são números. Por outro lado, durante este curso também já escrevemos programas que leem e manipulam textos (strings). Então, como será que o computador lida com os caracteres?
Para que possam ser processados pelo computador, precisamos representar os caracteres por meio de números.

Existem diferentes codificações (= representações numéricas) que podem ser usadas para caracteres. Algumas codificações são específicas para uma língua (como Chinês, Russo, etc.), enquanto outras podem ser usadas para múltiplas línguas. Um mesmo caracter pode aparecer em diferentes codificações; entretanto, duas codificações diferentes podem usar códigos numéricos diferentes para representar um mesmo caracter.

Uma das codificações mais conhecida (e antiga!) é a ASCII (American Standard Code for Information Interchange), que foi definida como um padrão em 1968. A ASCII foi criada para representar caracteres da língua inglesa e, para isso, usa os números entre 0 e 127. Como um código ASCII é um número entre 0 e 127, ele pode ser armazenado usando-se apenas 7 bits, ou seja, menos de 1 byte (= 8 bits). Você pode ver a tabela da codificação ASCII na Wikipédia.

A codificação ASCII define códigos apenas para caracteres não acentuados, portanto ela não representa completamente os caracteres de outras línguas que possuem o mesmo alfabeto do inglês, como o português, o francês e o espanhol. Para lidar com esse problema, nos anos 80 várias extensões do ASCII foram criadas usando os valores entre 128 e 255 como códigos para caracteres acentuados, resultando em códigos de 1 byte. Um exemplo de uma dessas extensões, usada para a língua portuguesa, é a codificação ISO-8859-1, também chamada de Latin1.

Problema das extensões do ASCII: 128 caracteres adicionais ainda não eram suficientes para representar ao mesmo tempo, por exemplo, os caracteres "especiais" existentes no português e no alfabeto russo.
A criação e uso de codificações específicas para um língua resolve uma parte desse problema. Um arquivo contendo um texto em português pode ter uma determinada codificação, enquanto um outro arquivo contendo um texto em russo pode ter uma codificação diferente. Mas o que fazer quando um texto em português precisava conter uma citação a um trecho em russo?

Para solucionar esse problema e prover uma representação unificada dos alfabetos de todas as línguas da humanidade (objetivo bastante ambicioso!), o padrão Unicode foi desenvolvido. Em sua proposta inicial, o Unicode usava códigos de até 16 bits (2 bytes), sendo capaz de codificar 2^16 = 65536 caracteres diferentes. Mas essa quantidade de caracteres logo mostrou-se insuficiente; atualmente, um código Unicode pode ocupar até 4 bytes (= 32 bits). O Unicode possui diferentes "implementações": UTF-8, UTF-16 e UTF-32. Para todos os caracteres que estão na tabela ASCII, o código Unicode (UTF-8) e o código ASCII são iguais.

O Python 3.x usa codificação UTF-8 como padrão. Já o Python 2.x usa a codificação ASCII como padrão.

As funções ord() e chr()

A função ord() devolve o código numérico do caractere passado como parâmetro. Veja os exemplos a seguir:

In [1]:
print(ord("8"))
print(ord("?"))
print(ord("A"))
print(ord("C"))
print(ord("^"))
print(ord("a"))
56
63
65
67
94
97

A função ord() gerará um erro se passarmos como parâmetro uma string contendo mais de um caracter:

In [2]:
ord("olá!")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-2e7b9727d71f> in <module>()
----> 1 ord("olá!")

TypeError: ord() expected a character, but string of length 4 found

A função chr() devolve o caracter corresponde ao código numérico passado como parâmetro. Veja os exemplos abaixo:

In [3]:
print(chr(43))
print(chr(54))
print(chr(65))
print(chr(472))
+
6
A
ǘ

Importante: Em todos os exercícios a seguir, por simplicidade, trabalharemos apenas com strings com codificação ASCII, ou seja, strings que não contêm caracteres com acentos.

Problema 14.1

Escreva um programa que imprima todos os caracteres ASCII de 32 a 127.

In [2]:
def main():
    for i in range(32,128):
        print("Caracter '%c' tem código ASCII %d"%(chr(i), i))

#################        
main()
Caracter ' ' tem código ASCII 32
Caracter '!' tem código ASCII 33
Caracter '"' tem código ASCII 34
Caracter '#' tem código ASCII 35
Caracter '$' tem código ASCII 36
Caracter '%' tem código ASCII 37
Caracter '&' tem código ASCII 38
Caracter ''' tem código ASCII 39
Caracter '(' tem código ASCII 40
Caracter ')' tem código ASCII 41
Caracter '*' tem código ASCII 42
Caracter '+' tem código ASCII 43
Caracter ',' tem código ASCII 44
Caracter '-' tem código ASCII 45
Caracter '.' tem código ASCII 46
Caracter '/' tem código ASCII 47
Caracter '0' tem código ASCII 48
Caracter '1' tem código ASCII 49
Caracter '2' tem código ASCII 50
Caracter '3' tem código ASCII 51
Caracter '4' tem código ASCII 52
Caracter '5' tem código ASCII 53
Caracter '6' tem código ASCII 54
Caracter '7' tem código ASCII 55
Caracter '8' tem código ASCII 56
Caracter '9' tem código ASCII 57
Caracter ':' tem código ASCII 58
Caracter ';' tem código ASCII 59
Caracter '<' tem código ASCII 60
Caracter '=' tem código ASCII 61
Caracter '>' tem código ASCII 62
Caracter '?' tem código ASCII 63
Caracter '@' tem código ASCII 64
Caracter 'A' tem código ASCII 65
Caracter 'B' tem código ASCII 66
Caracter 'C' tem código ASCII 67
Caracter 'D' tem código ASCII 68
Caracter 'E' tem código ASCII 69
Caracter 'F' tem código ASCII 70
Caracter 'G' tem código ASCII 71
Caracter 'H' tem código ASCII 72
Caracter 'I' tem código ASCII 73
Caracter 'J' tem código ASCII 74
Caracter 'K' tem código ASCII 75
Caracter 'L' tem código ASCII 76
Caracter 'M' tem código ASCII 77
Caracter 'N' tem código ASCII 78
Caracter 'O' tem código ASCII 79
Caracter 'P' tem código ASCII 80
Caracter 'Q' tem código ASCII 81
Caracter 'R' tem código ASCII 82
Caracter 'S' tem código ASCII 83
Caracter 'T' tem código ASCII 84
Caracter 'U' tem código ASCII 85
Caracter 'V' tem código ASCII 86
Caracter 'W' tem código ASCII 87
Caracter 'X' tem código ASCII 88
Caracter 'Y' tem código ASCII 89
Caracter 'Z' tem código ASCII 90
Caracter '[' tem código ASCII 91
Caracter '\' tem código ASCII 92
Caracter ']' tem código ASCII 93
Caracter '^' tem código ASCII 94
Caracter '_' tem código ASCII 95
Caracter '`' tem código ASCII 96
Caracter 'a' tem código ASCII 97
Caracter 'b' tem código ASCII 98
Caracter 'c' tem código ASCII 99
Caracter 'd' tem código ASCII 100
Caracter 'e' tem código ASCII 101
Caracter 'f' tem código ASCII 102
Caracter 'g' tem código ASCII 103
Caracter 'h' tem código ASCII 104
Caracter 'i' tem código ASCII 105
Caracter 'j' tem código ASCII 106
Caracter 'k' tem código ASCII 107
Caracter 'l' tem código ASCII 108
Caracter 'm' tem código ASCII 109
Caracter 'n' tem código ASCII 110
Caracter 'o' tem código ASCII 111
Caracter 'p' tem código ASCII 112
Caracter 'q' tem código ASCII 113
Caracter 'r' tem código ASCII 114
Caracter 's' tem código ASCII 115
Caracter 't' tem código ASCII 116
Caracter 'u' tem código ASCII 117
Caracter 'v' tem código ASCII 118
Caracter 'w' tem código ASCII 119
Caracter 'x' tem código ASCII 120
Caracter 'y' tem código ASCII 121
Caracter 'z' tem código ASCII 122
Caracter '{' tem código ASCII 123
Caracter '|' tem código ASCII 124
Caracter '}' tem código ASCII 125
Caracter '~' tem código ASCII 126
Caracter '' tem código ASCII 127

Problema 14.2

Dada uma sequência de caracteres representando um texto, determinar a frequência relativa de vogais no texto.

Por exemplo, no texto:

"Em terra de cego quem tem um olho e caolho"

essa frequência é 16/42.

Solução 1 (usa for elemento in ...)

In [7]:
def main():
    texto = input("Digite um texto: ")

    n = len(texto)
    nv = 0
    vogais = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']

    for letra in texto:
        if letra in vogais:
            nv += 1

    print ("Frequencia relativa = %d/%d = %f" %(nv, n, nv/n))

#-------------------------------------------
main()
Digite um texto: Em terra de cego quem tem um olho e caolho
Frequencia relativa = 16/42 = 0.380952

Solução 2 (usa for para varrer a lista de vogais)

In [4]:
def main():
    texto = input("Digite um texto: ")

    n = len(texto)
    nv = 0
    vogais = "aeiouAEIOU"

    for i in range(n):
        for j in range(len(vogais)):
            if texto[i] == vogais[j]:
                nv += 1

    print ("Frequencia relativa = %d/%d = %f" %(nv, n, nv/n))

#-------------------------------------------
main()
Digite um texto: Em terra de cego quem tem um olho e caolho
Frequencia relativa = 16/42 = 0.380952

Problema 14.3

a) Escreva uma função que recebe um caractere e, caso o caractere seja uma letra minúscula, retorna a letra maiúscula correspondente. Caso contrário, retorna o caractere.

b) Escreva uma função que recebe um caractere e, caso o caractere seja uma letra maiúscula, retorna a letra minúscula correspondente. Caso contrário, retorna o caractere.

c) Escreva um programa que leia uma frase e imprima:

  • a frase toda em maiúsculas
  • a frase toda em minúsculas
In [9]:
def main():
    texto = input("digite um texto: ")  

    textoMaiusculo = ''
    textoMinusculo = ''
    for l in texto:
        textoMaiusculo += maiuscula(l)
        textoMinusculo += minuscula(l)

    print("Em maiúsculas: ")
    print (textoMaiusculo)

    print("Em minúsculas: ")
    print(textoMinusculo)



def maiuscula(c):
    if c >= 'a' and c <= 'z':
        return chr(ord('A') + ord(c) - ord('a'))
    else:
        return c
    
def minuscula(c):
    if c >= 'A' and c <= 'Z':
        return chr(ord('a') + ord(c) - ord('A'))
    else:
        return c

#------------------------------
main()
digite um texto: PeQuEno TesTE
Em maiúsculas: 
PEQUENO TESTE
Em minúsculas: 
pequeno teste

Obs.: O tipo string em Python já possui funções para converter uma string para letras maiúsculas ou minúsculas - são as funções upper() e lower(). Veja um exemplo do uso delas a seguir:

In [7]:
texto = "PeQuEno TesTE"
textoMaiusculo = texto.upper()  # cria uma string com o texto em letras maiúsculas
textoMinusculo = texto.lower()  # cria uma string com o texto em letras minúsculas
print(textoMaiusculo)
print(textoMinusculo)
PEQUENO TESTE
pequeno teste

Problema 14.4

Faça um programa que, dada uma frase, imprima o comprimento da palavra mais longa nela.

In [10]:
def main():
    frase = input("Digite uma frase: ")

    n = len(frase)
    tam = 0
    max = 0
    for ch in frase:
        if 'a' <= ch <= 'z' or 'A' <= ch <= 'Z':
            tam = tam + 1
        else:
            tam = 0

        if tam > max:
            max = tam

    print("\nMaior comprimento de uma palavra = %d\n" %(max)

# início da execução do programa
main()
Digite uma frase: Batatinha quando nasce, espalha a rama pelo chão

Maior comprimento de uma palavra = 9


Problema 14.5

(a) Escreva uma função separa(texto, sep) que recebe como parâmetro um texto (= uma string) e um caractere separador sep e retorna uma lista contendo as "palavras" do texto usando o caractere sep como delimitador:

Por exemplo, para:

texto = "Como é bom estudar MAC2166!"

sep = " "

a função deve retornar

['Como', 'é', 'bom', 'estudar', 'MAC2166!']

A função deve "cortar" o texto nos separadores.

(b) Escreva um programa que leia uma linha com palavras separadas por espaços e determina o maior comprimento de uma palavra do texto. Utilize a função separa() do item anterior.

In [11]:
def main():
    frase = input("Digite palavras separadas por espacos: ")
    palavras = separa(frase, ' ')
    print (palavras)

    if len(palavras) > 0:
        maxp = palavras[0]
        for p in palavras:
            print ("A palavra '%s' tem %d caracteres."%(p, len(p)))
            if len(p) > len(maxp):
                maxp = p
        print("A maior palavra e '%s', que tem %d caracteres." %(maxp, len(maxp)))
    else:
        print("Nao achei nenhuma palavra em sua frase!")

#---------------------------------------------------------
def separa(texto, sep = ' '):
    ''' (str, chr) -> list

     Recebe um string texto e um caractere separador sep e
     retorna uma lista contendo as 'palavras' do texto usando
     o caractere sep como delimitador:
     Por exemplo para:

         texto = "Como e bom estudar MAC2166!"
         sep   = " "

     a funcao retorna

        ['Como', 'e', 'bom', 'estudar', 'MAC2166']

     A funcao 'corta' o texto nos separadores.
    '''
    lista = []
    palavra = ''
    for car in texto:
        if car != sep:
            palavra += car
        elif palavra != '':
            lista.append(palavra)
            palavra = ''

    # coloca a ultima palavra na lista
    if palavra != '':
        lista.append(palavra)

    return lista

#------------------------------------------------------
main()
Digite palavras separadas por espacos: Como é bom estudar MAC2166!
['Como', 'é', 'bom', 'estudar', 'MAC2166!']
A palavra 'Como' tem 4 caracteres.
A palavra 'é' tem 1 caracteres.
A palavra 'bom' tem 3 caracteres.
A palavra 'estudar' tem 7 caracteres.
A palavra 'MAC2166!' tem 8 caracteres.
A maior palavra e 'MAC2166!', que tem 8 caracteres.

A linguagem Python já tem uma função equivalente à separa() implementada no Problema 14.5: é função split(), que cria uma lista de strings a partir de uma só string. Essa função pode ser chamada por meio da notação de ponto, a partir de um objeto do tipo str. A função recebe como parâmetro o caractere (ou a string) que será usada como separador de substrings dentro da string a ser "desmembrada". Veja os exemplos de uso dela a seguir:

In [12]:
texto = "Passarim quis pousar, não deu, voou"
palavras = texto.split(" ")   # usa o caracter de espaço como separador de substrings   
print(palavras)
['Passarim', 'quis', 'pousar,', 'não', 'deu,', 'voou']

In [13]:
outro_texto = "Este é um string"
pedacos = outro_texto.split("t")  # usa "t" como caracter separador
print(pedacos) 
['Es', 'e é um s', 'ring']

Tópicos vistos na aula 14

  • Caracteres e uma breve introdução sobre a sua codificação
  • As funções ord() e chr