Strings e arquivos

Tópicos

  • Strings (tipo str)
    • Manipulação de strings
    • Representação de caracteres
  • Arquivos

Strings

Um string (=tipo str) é uma sequência de caracteres. Em Python, podemos representar um string colando-o entre aspas ou apóstrofes. O uso desses 2 marcadores é útil quando queremos utilizar um deles dentro do texto, como:

>>> texto = "Esse é string usa 'aspas' como demarcador"
>>> print(texto)
Esse é string usa 'aspas' como demarcador
>>> novo_texto = 'Esse é string usa "apóstrofes" como demarcador'
>>> print(novo_texto)
Esse é string usa "apóstrofes" como demarcador
>>>

Por ser uma sequência de caracteres, podemos fazer uma analogia de strings com listas em Python. Assim como listas, um caractere de um string pode ser acessado por meio de índices, o comprimento pode ser dado pela função len(), e os caracteres podem ser fatiados e concatenados. A grande diferença é que strings são imutáveis, ou seja, não é possível alterar um de seus elementos. Para isso, é necessário criar um novo string. Veja os exemplos abaixo:

>>> texto = "Esse é um 'string'"
>>> texto
"Esse é um 'string'"
>>> texto[2]
's'
>>> texto[2:4]
'se'
>>> texto[7:]
"um 'string'"
>>> texto[2] = c
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'c' is not defined
>>>

Representação de caracteres

Um conhecimento importante para trabalhar com strings é a conhecer a sua forma de representação (ou encoding). Uma grande diferença entre as versões 2.X e 3.X do Python é que, na versão 2.X os strings são codificados em ASCII e na versão 3.X em UTF-8.

No ASCII (American Standard Code for Information Interchange), cada caractere é representado usando apenas 7 bits, sendo que os caracteres de 0 a 31 são considerados de controle, e os de 32 a 127 correspondem aos caracteres comuns de um teclado de computador em inglês. Execute o seguinte programa para ver os caracteres de 32 a 127:

(aula13_tabela_ascii)



Esse programa usa a função chr que converte um índice da tabela ASCII em seu caractere correspondente. Observe que a ordem dos caracteres na tabela não é arbitrária. Por exemplo, os caracteres de a a z (tanto minúsculos quanto maiúsculos) estão agrupados sequencialmente, respeitando a ordem alfabética. Observe no entanto que não há caracteres acentuados, pois estes não fazem parte da língua inglesa.

O Unicode é um conjunto de caracteres que inclui os símbolos de todas as línguas humanas, desde os milhares de caracteres de línguas asiáticas como o chinês, até os caracteres de línguas mortas como os hieróglifos usados pelos egípicios. Para representar os caracteres do Unicode, foram desenvolvidos diversas formas de codificação. Uma delas é a UTF-32 (U de Universal Character Set e o TF de Transformation Format - usando 32 bits). Essa forma utiliza sempre 32 bits (ou 4 bytes) para codificar um caractere (ou, mais exatamente, para codificar o índice do caractere na tabela Unicode).

O UTF-32 não é muito utilizado hoje pois, apesar de ser simples de decodificar, seus arquivos tornam-se muito grandes. O UTF-16 exige ao menos 2 bytes (16 bits) para codificar cada caractere, criando arquivos menores em geral. Esse padrão é utilizado na linguagem Java e em sistemas operacionais como o Microsoft Windows e o Mac OS X. Já o padrão mais utilizado para codificar páginas na Internet atualmente é o UTF-8, que usa pelo menos 8 bits para representar cada caractere.

O Python oferece vários métodos para operar com strings (consulte a documentação do Python sobre strings). A seguir veremos apenas alguns mais úteis para processar arquivos.

Arquivos

Utilizamos arquivos para armazenar informação, programas, documentos, etc. Para os fins desse curso, vamos trabalhar apenas com arquivos tipo texto.

Criação de arquivos

Para criar um arquivo e poder gravar informações nele, vamos utilizar a seguinte forma:

nome = "poesia.txt"    # poderia ser um input("Digite o nome do arquivo: ")

with open(nome, 'w', encoding='utf-8') as arq:
    # CORPO DO WITH
    arq.write("    O poeta é um fingidor.      \n")
    arq.write("    Finge tão completamente     \n")
    arq.write("    Que chega a fingir que é dor\n")
    arq.write("    A dor que deveras sente.    \n")
    arq.write("                Fernando Pessoa.\n")

Utilizamos o comando with para nos proteger contra alguns problemas que podem acontecer com arquivos (que não iremos detalhar no momento). A função open() abre o arquivo de nome poesia.txt (certifique-se de incluir todo o caminho (path) no nome, ou o arquivo será gravado no mesmo diretório do programa sendo executado) para gravação (devido a opção w do inglês write) e, para garantir que o arquivo será gravado em utf-8, definimos também a forma de codificação pela opção encoding.

Dentro comando with (corpo do with), devemos fazer todas as operações com o arquivo arq, nesse exemplo, escrever algumas linhas de texto usando o método write(). Observe que o \n faz a mudança de linha explicitamente. Uma grande vantagem de utilizar o comando with é que o arquivo é fechado automaticamente ao final do corpo, não sendo necessário fechar o arquivo explicitamente.

Leitura de arquivos

Agora vamos abrir o arquivo “poesia.txt” para processar o seu conteúdo, utilizando o comando with novamente:

nome = "poesia.txt"    # poderia ser um input("Digite o nome do arquivo: ")

with open(nome, 'r', encoding='utf-8') as arq_entrada:
    # CORPO DO WITH
    conteudo = arq_entrada.read()

# continue o programa usando conteudo
print(conteudo)

A saída seria:

O poeta é um fingidor.
Finge tão completamente
Que chega a fingir que é dor
A dor que deveras sente.
            Fernando Pessoa.

A função open() abre o arquivo com nome indicado no string nome (certifique-se de passar todo o caminho (path) no nome, ou o arquivo deve estar no mesmo diretório do programa sendo executado) para leitura (devido a opção r do inglês read) e usamos a mesma forma de codificação, no caso, utf-8.

No corpo do comando with devemos fazer toda a computação com o arquivo, acessando-o pela variável arq_entrada (poderia ser qualquer outro nome). O método read() lê todo o conteúdo de arq_entrada e o atribui para conteudo. Nesse caso, a variável conteudo faz referência a um string cujo conteúdo foi carregado do arquivo. Ao final do corpo do with, esse comando fecha automaticamente o arquivo.

Ao invés de carregar o arquivo inteiro de uma vez, muitos vezes é mais conveniente processar uma linha de cada vez para converte-lo ou extrair as informações necessárias, e assim evitar de manter o arquivo todo (que pode ser muito grande) na memória do computador.

Para isso, o Python oferece a seguinte forma de processar as linhas de um arquivo:

nome = "poesia.txt"

with open(nome, 'r', encoding='utf-8') as arquivo:
    for linha in arquivo:
        print(linha)

A saída seria:

O poeta é um fingidor.

Finge tão completamente

Que chega a fingir que é dor

A dor que deveras sente.

            Fernando Pessoa.

Nesse caso, é como se o arquivo fosse uma lista de linhas. Ao rodar esse programa no entanto, você deve notar que o espaçamento entre linhas aumentou. Isso porque a linha contém o \n e a função print() muda automaticamente de linha.

Como já mencionamos, o Python oferece vários métodos para operar com strings (consulte a documentação do Python sobre strings). O método strip() é um método para eliminar o \n e demais caracteres considerados “brancos” (como o espaço e o tab) no início e final de um string. Experimente agora rodar o programa abaixo:

nome = "poesia.txt"

with open(nome, 'r', encoding='utf-8') as arquivo:
    for linha in arquivo:
        linha_sem_brancos = linha.strip()
        print(linha_sem_brancos)

e nesse caso a saída seria:

O poeta é um fingidor.
Finge tão completamente
Que chega a fingir que é dor
A dor que deveras sente.
Fernando Pessoa.

O strip() é muito útil quando estamos interessados apenas no texto e podemos desconsiderar a formatação. Observe que não apenas o \n foi desconsiderado, mas também o tab no início de cada linha do poema.

Finalmente, se além do texto queremos separar a frase em palavras, podemos utilizar o método split(), que em seu comportamento padrão separa a frase em palavras usando os caracteres considerados “brancos” como separadores. Rode o seguinte programa para ver o resultado de split() nas linhas do poema.

(aula13_exemplo_split)



Experimente rodar esse mesmo programa sem o strip().

Exercícios

Exercício 13.1

PARTE A

Escreva uma função separa, que recebe um string texto e um caractere separador. A função “corta” o texto nos separadores, retornando uma lista com as palavras do texto. Exemplo: para o texto: ”,1,,2,3,” a saída deve ser a lista: [‘’, ‘1’, ‘’, ‘2’, ‘3’, ‘’] onde ‘’ indica uma palavra vazia (entre 2 separadores consecutivos).

(aula13_ex131a_tentativa)



PARTE B

Usando a função do item anterior, escreva um programa que leia uma linha com palavras separadas por vírgula, e determina o comprimento da maior palavra. A linha pode conter palavras vazias.

(aula13_ex131b_tentativa)



PARTE C

Escreva o programa da parte B usando a função split().

Exercício 13.2

Escreva um programa que leia vários números reais em uma mesma linha, e imprima a soma.

(aula13_ex132_tentativa)



Exercício 13.3

Escreva um programa que leia um arquivo contendo ao menos 1 número real por linha, e para cada linha imprima a sua soma. Ao final, o programa deve imprimir também a soma total. Exemplo: para o arquivo numeros.txt com:

5 4 3 2 1
4 4 4
2.7
3.14 2.1

a saída deve ser:

Digite o nome do arquivo: numeros.txt
Soma = 15.000000
Soma = 12.000000
Soma = 2.700000
Soma = 5.240000
Total = 34.940000

Dessa vez, use um editor como o Idle no seu computador para escrever o programa.