Obra: Programar em C++/Entrada e saída de dados 2
entrada saída em ficheiros arquivos nota introdutória este capitulo geralmente colocado uns capítulos mais para fim mas acho por bem que se torne as coisas mais interativas que possível introduzindo agora operações em arquivos dá muito mais entusiasmo encontramos aqui conceitos avançados mas poderão ser deixados para depois se leitor não quiser observar tema neste momento gravar salvar os dados para um ficheiro arquivo os dados que mantemos nos programas estão guardados na memória ram que limpa quando programa ou computador para de funcionar isso implicaria que perderíamos toda informação porém existe uma maneira para tornar os dados persistentes que gravar os dados num ficheiro arquivo no hard drive disco rígido ou no outro meio persistente nas formas mais diretas de escrita podemos passar os dados em formato binário para ficheiro arquivo outros meios avançados para guardar dados podem envolver bases de dados relacionais ou xml que um ficheiro arquivo um arquivo uma coleção de dados que estão localizados numa memória persistente tipo hard drive cd rom etc para identificarmos arquivo podemos atribuir lhe um nome filename os filenames têm usualmente uma extensão que determina tipo de arquivo em sistemas operacionais semelhantes aos da microsoft mas que podem ser dispensados em sistemas operacionais que guardam as características dos arquivos no meio de armazenamento tais quais sistemas unix seus similares gnu linux freebsd etc extensão representada por ou letras que seguem após nome do arquivo um ponto por exemplo joao doc ou joao odt isto diz me que temos um ficheiro arquivo que se chama joao que tem extensão doc que refere usualmente documentos do word no primeiro caso com extensão odt do openoffice no segundo outros tipos de extensões podem ser xls para documentos excel ods para planilhas do openoffice ou ainda cpp para ficheiros arquivos de códigos de ficheiros arquivos binários tipo texto existem na verdade dois tipos de ficheiros arquivos os do tipo texto os do tipo binário os arquivos tipo texto apenas armazenam texto obedecendo uma codificação de caracteres mais comum ascii isto implica uso do código para armazenamento ou seja pode ser que codificação seja interpretada antes de ser efetivada no meio de armazenamento os arquivos binários podem guardar mais informação como imagens base de dados programas por exemplo editores de texto com formatação como openoffice word guardam os seus arquivos em formatos binários porque eles possuem além do texto informação acerca da formatação do texto para as tabelas as listas numeradas tipo de fonte etc daí aparecerem os caracteres de formatação tipo ìl os arquivos binários poderão ser mais bem explorados em um tópico avançado vamos trabalhar inicialmente com arquivos tipo texto que poderemos operar de maneira mais simplificada biblioteca padrão fstream até agora temos usado biblioteca iostream de input de output stream que suporta entre várias funcionalidades objeto cin para ler da standard input que us
output stream que suporta entre várias funcionalidades objeto cin para ler da standard input que usualmente teclado objeto cout para standard output que usualmente monitor ora agora queremos ler escrever para ficheiros arquivos isso requer biblioteca fstream de file stream esta biblioteca define novos tipos de classe ofstream apenas para saída out to file serve para criar manipular ficheiros arquivos escrever não serve para ler ifstream apenas para entrada in from file serve para ler ficheiros arquivos receber dados dos mesmos não serve para criar nem escrever fstream este conjuga os dois tipos anteriores input and output to file cria ficheiros arquivos escreve lê informação dos mesmos abrir um ficheiro arquivo um ficheiro arquivo deve ser aberto pelo programa para que mesmo possa ser manipulado abertura do arquivo implica entre outras coisas atribuir um identificador que nos permita ter acesso aos seus dados necessário criar uma linha de comunicação entre arquivo objeto stream podemos recorrer dois métodos para abrir um ficheiro arquivo usando um construtor usando função membro chamada de open usando construtor construtor uma função que automaticamente chamada quando tentamos criar uma instância de um objeto fstream afile criado uma instância do fstream chamada de afile os construtores de objetos podem ser sobrecarregados ou seja para mesma classe podemos ter um construtor sem argumentos com um argumento dois argumentos etc no exemplo anterior criamos um sem argumentos os construtores não retornam valores geralmente compilador reporta erro quando se declara funções que retornam valor estas têm mesmo nome da classe pois este nome reservado para os construtores vamos dar um exemplo com dois argumento ofstream outfile joao doc ios out chama construtor com dois argumentos criando uma instância de ofstream abrindo ficheiro arquivo joao doc para operações de saída usando função membro open esta função tem como primeiro argumento nome localização do ficheiro arquivo ser aberto segundo argumento especifica modo de abertura sobre questão da localização existem tipos path relativo path absoluto para este último indicamos caminho todo joao doc em sistemas microsoft ou home joao joao odt para sistemas unix similares path relativo dispensa essa descrição se ficheiro arquivo estiver na mesma directoria no mesmo diretório que programa sobre questão do modo de abertura temos as seguintes modalidades modo do abertura sinalizador flag descrição ios app append mode todos os dados do arquivo são preservados qualquer saída escrita partir do fim do arquivo ios ate se arquivo já existe programa vai diretamente ao seu fim modo de escrita então feito de forma aleatória usado normalmente com arquivos do modo binário binary mode ios binary binary mode informações são escritas na forma binária não na forma textual text mode ios in input mode leitura de informações de arquivo não irá criar um arquivo novo ios out output mode informações serão escritas no arquivo ios trunc
o não irá criar um arquivo novo ios out output mode informações serão escritas no arquivo ios trunc se arquivo já existe suas informações serão truncadas outra forma de se dizer deletadas reescritas os sinalizadores flags são números em potências da base binária portanto podemos ter vários flags ao mesmo tempo se usarmos operador unário para operação ou como no exemplo abaixo ofstream outfile crio objeto outfile outfile open students dat ios binary ios app chamo função membro open do objeto com parâmetro que nome do arquivo modo de abertura observe que estamos abrindo arquivo students dat em modo binário ao mesmo tempo com modo append isto significa que abriremos arquivo poderemos preservar seu conteúdo anterior inserindo os novos dados no fim do arquivo comparando os dois métodos pela função membro pelo construtor primeiro método similar ter int age age segundo método similar int age escolha do melhor método em cada situação depende do contexto em que estamos criando código geralmente quando já temos objeto criado ele está fechado podemos abrir um novo arquivo com ele depois fechá lo novamente isto nos sugere que usemos função open quando objeto deve abrir arquivos diferentes em cada trecho de código embora que possam surgir outras funcionalidades dependendo de como projeto foi idealizado abrir um arquivo para leitura história aqui mesma só tem uma diferença que no caso de leitura não será criado nenhum ficheiro arquivo caso ele não exista ifstream arq cria objeto arq arq open joão doc chama função membro open ao objeto arq com parâmetro do nome do ficheiro poderíamos fazer mesmo com construtor ifstream arq joão doc ou ainda fstream bloco bloco open joao doc ios in ou ainda fstream joao doc ios in há mais uma nota fazer se quisermos ler escrever não podemos usar ofstream ifstream ao mesmo tempo teremos de usar fstream teremos de fazer fstream joão doc ios in ios out neste caso comportamento padrão preservar conteúdo do ficheiro arquivo ou criá lo caso ele não exista verificar se ficheiro arquivo foi aberto vamos verificar que acontece quando tentamos abrir um arquivo que não existe primeira versão do nosso exemplo observa comportamento básico do fstream include include using namespace std int main ifstream arq crio objeto arq da classe ifstream leitura arq open joao doc chamo função membro open cout no caso do ficheiro arquivo joao doc não existir arq arq fail no caso do ficheiro arquivo joao doc existir no mesmo diretório que programa fe fail repare que resultado impressão do endereço do objeto de ifstream dá um ponteiro agora vajamos um exemplo mais completo include include using namespace std int main ifstream arq crio objeto arq da classe ifstream leitura string str arq open joao doc chamo função membro open if arq is_open arq good arq str cout observe que aqui verificamos se arquivo foi aberto com função membro is_open que retorna verdadeiro true caso arquivo foi aberto depois verificamos se arquivo foi aberto através da função membro good
true caso arquivo foi aberto depois verificamos se arquivo foi aberto através da função membro good que também retorna verdadeiro se arquivo pode ser usado fechar um ficheiro arquivo devemos fechar depois de ler ou escrever mas por que se objeto do ficheiro irá ser fechado assim que programa acabar porque estamos utilizar recursos com um ficheiro arquivo aberto porque alguns sistemas operativos operacionais limitam no de ficheiros arquivos abertos estando este aberto impede que outros se possam abrir por fim porque se não fecharmos outros programas não poderão abri lo até que fechemos este comportamento faz parte de um esquema de controle de acesso usado pelo sistema para assegurar que os arquivos não serão usados por processos diferentes ao mesmo tempo ofstream outfile outfile open students dat outfile close vamos criar um exemplo mais real queremos criar um programa que escreva informação inserida pelo utilizador num ficheiro por nós escolhido include include using namespace std int main char data criamos um array de caracteres ofstream outfile criamos objeto da classe ofstream outfile open joao doc chamamos função membro da classe para objeto criado esta função membro cria arquivo joao doc if outfile is_open outfile good verificamos se está tudo bem cout podemos ir ver novo ficheiro arquivo com nome joao doc tem lá escrito aquilo que digitamos agora vamos tentar ler que escrevemos no documento criado include include using namespace std int main char data ifstream infile infile open joao doc if infile is_open infile good verificamos se está tudo bem infile data colocamos os dados abertos no array cout repare que se tivéssemos escrito duas palavras apenas uma era apresentada ela pára no primeiro whitespace para isso necessitaríamos de repetir include include using namespace std int main char data ifstream infile infile open joao doc if infile is_open infile good verificamos se está tudo bem infile data colocamos os dados abertos no array cout data colocamos os dados abertos no array cout agora já obtemos palavras são apresentadas em linhas diferentes mas temos de arranjar um método para não estar repetir constantemente podemos fazer isso com infile getline data então ficamos com include include include using namespace std int main string data ofstream outfile outfile open joao doc if outfile is_open outfile good verificamos se está tudo bem cout data cin ignore esta função membro para limpar caractere newline do inputbuffer depois de usar objeto cin com operador de extração outfile looping pelo ficheiro arquivo se não soubermos quantas linhas tem arquivo objeto ifstream tem uma função membro que eof end of file esta função não tem parâmetros retorna true se fim do arquivo for alcançado false caso contrário no entanto esta função eof não de confiança com os ficheiros arquivos texto como para os binários que nos ficheiros arquivos binários não existem espaços em branco melhor alternativa usar função membro fail ifstream infile infile open joao doc
em espaços em branco melhor alternativa usar função membro fail ifstream infile infile open joao doc if infile is_open infile good infile data while infile fail infile data cout refazendo tudo include include include using namespace std int main string data ofstream outfile outfile open joao doc if outfile is_open outfile good cout data cin ignore outfile agora vamos fazer nosso programa mais modular writefile para abrir um arquivo para escrita usando ofstream readfile ler do ficheiro arquivo usando ifstream cada função irá verificar se ficheiro arquivo foi aberto com sucesso include include include using namespace std bool writefile ofstream char bool readfile ifstream char int main string data bool status ofstream outfile status writefile outfile students dat if status cout data cin ignore outfile manipuladores os objetos das classes stream podem ser configurados para fornecer reportar os dados de maneira pré formatada da mesma maneira que temos formatação quando usamos funções de formatação como printf scanf na linguagem podemos usar os manipuladores na linguagem para informar os objetos streams em que formato desejamos receber os dados deles ou fornecer para eles abaixo temos uma série de manipuladores úteis manipulator uso boolalpha faz com que variáveis tipo bool sejam reportadas como true ou false noboolalhpa padrão faz com que variáveis tipo bool sejam reportadas omo ou dec padrão determina que variáveis tipo inteiras int sejam reportadas na base hex determina que variáveis tipo inteiras int sejam reportadas em hexadecimal oct determina que variáveis tipo inteiras int sejam reportadas em octal left faz com que textos sejam justificados esquerda no campo de saída right faz com que textos sejam justificados direita no campo de saída internal faz com que sinal de um número seja justificado esquerda número seja justificado direita noshowbase padrão desativa exibição do prefixo que indica base do número showbase ativa exibição do prefixo que indica base do número noshowpoint padrão mostra ponto decimal apenas se uma parte fracionária existe showpoint mostra ponto decimal sempre noshowpos padrão nenhum sinal prefixado em números positivos showpos mostra um sinal prefixado em números positivos skipws padrão faz com que espaços em branco tabulações novas linhas sejam descartados pelo operador de entrada noskipws faz com que espaços em branco tabulações novas linhas não sejam descartados pelo operador de entrada fixed padrão faz com que números com ponto flutuante sejam mostrados em notação fixa scientific faz com que números com ponto flutuante sejam mostrados em notação científica nouppercase padrão mostrado para números em hexadecimal para notação científica uppercase mostrado para números em hexadecimal para notação científica ajustando largura da entrada saída setw ajusta largura da saída entrada para precisa ser incluído width uma função membro das classes iostream preenchimento de espaços em branco setfill ch preenche os espaços em branco e
o das classes iostream preenchimento de espaços em branco setfill ch preenche os espaços em branco em campos de saída com ch precisa ser incluído fill ch uma função membro das classes iostream ajustando precisão setprecision ajusta precisão de casas decimais em números com ponto flutuante para dígitos este ajuste apenas visual de forma que manipulador não afeta modo de cálculo do número pelo programa exemplificando uso de manipuladores include include include using namespace std int main int intvalue cout exercícios quero colocar num documento uma lista das combinações possíveis entre com respectiva ordenação quantidade quero que seja pessoa escolher nome do ficheiro arquivo escrever também localização quero que seja depois tansformado num sistema modular encontrar uma maneira para contar no de espaços em branco no de caracteres que quisermos de um dado documento include include using namespace std int main int blank_count int char_count int sentence_count char ch ifstream object jo txt if object cout