mirror of
https://gitlab.com/blau_araujo/cblc.git
synced 2025-05-09 18:16:37 -03:00
Compare commits
4 commits
2fc358accd
...
60d0d0a598
Author | SHA1 | Date | |
---|---|---|---|
60d0d0a598 | |||
1a86a63298 | |||
add1c00268 | |||
76a3f77882 |
4 changed files with 304 additions and 2 deletions
|
@ -37,6 +37,6 @@ qualquer distribuição.
|
|||
- [[./aulas/13-read][Aula 13: Leitura da entrada padrão com chamadas de sistema]] ([[https://youtu.be/bW3Xox6LP_U][vídeo]]) ([[./exercicios/13/README.org][exercícios]])
|
||||
- [[./aulas/14-rfiles][Aula 14: Abertura de arquivos para leitura]] ([[https://youtu.be/uh3UdYyzXRM][vídeo]]) ([[./exercicios/14/README.org][exercícios]])
|
||||
- [[./aulas/15-wfiles][Aula 15: Abertura de arquivos para escrita]] ([[https://youtu.be/vL8vy3krcKc][vídeo]]) ([[./exercicios/15/README.org][exercícios]])
|
||||
- [[./aulas/#][Aula 16: Abertura de arquivos para leitura e escrita]] ([[https://youtu.be/B42KIZfivsg][vídeo]]) ([[./exercicios/16/README.org][exercícios]])
|
||||
- [[./aulas/16-rwfiles][Aula 16: Abertura de arquivos para leitura e escrita]] ([[https://youtu.be/B42KIZfivsg][vídeo]]) ([[./exercicios/16/README.org][exercícios]])
|
||||
|
||||
|
||||
|
|
245
aulas/16-rwfiles/README.org
Normal file
245
aulas/16-rwfiles/README.org
Normal file
|
@ -0,0 +1,245 @@
|
|||
#+title: Curso Básico da Linguagem C
|
||||
#+subtitle: Aula 16: Abertura de arquivos para leitura e escrita
|
||||
#+author: Blau Araujo
|
||||
#+startup: show2levels
|
||||
#+options: toc:3
|
||||
|
||||
* Aula 16: Abertura de arquivos para leitura e escrita
|
||||
|
||||
[[https://youtu.be/B42KIZfivsg][Vídeo desta aula]]
|
||||
|
||||
** Modos de abertura para leitura e escrita
|
||||
|
||||
As strings de modos ="r"=, ="w"= e ="a"=, da função =fopen=, quando sucedidas do
|
||||
caractere =+=, indicam a abertura do arquivo também para suas respectivas
|
||||
operações contrarias:
|
||||
|
||||
| Modo | Leitura | Escrita | Truncar | Offset | Criar |
|
||||
|------+---------+---------+---------+--------+-------|
|
||||
| ="r"= | Sim | Não | Não | Início | Não |
|
||||
| ="r+"= | Sim | Sim | Não | Início | Não |
|
||||
| ="w"= | Não | Sim | Sim | Início | Sim |
|
||||
| ="w+"= | Sim | Sim | Sim | Início | Sim |
|
||||
| ="a"= | Não | Sim | Não | Fim | Sim |
|
||||
| ="a+"= | Sim | Sim | Não | Fim | Sim |
|
||||
|
||||
De acordo com a tabela acima, nós precisamos observar alguns pontos
|
||||
importantes:
|
||||
|
||||
- Se a string de modo iniciar com =w=, o arquivo sempre será truncado
|
||||
na sua abertura.
|
||||
- Se a string de modo iniciar com =a=, o ponteiro interno sempre será
|
||||
posicionado no fim do arquivo na sua abertura.
|
||||
- Se a string de modo iniciar com =r=, o ponteiro interno sempre será
|
||||
posicionado no início do arquivo na sua abertura.
|
||||
- Se não existir, o arquivo só será criado se a string de modo
|
||||
iniciar com =w= ou =a=.
|
||||
|
||||
** Manipulação do ponteiro interno
|
||||
|
||||
O ponteiro interno do arquivo representa o número do byte que será lido
|
||||
ou escrito no próximo acesso: ou seja, seu /offset/ (ou /ponto de partida/).
|
||||
Isso é particularmente importante quando abrimos arquivos para ambas as
|
||||
operações com as strings de modo ="r+"= ou ="a+"=, visto que o modo ="w+"=
|
||||
truncará o conteúdo do arquivo.
|
||||
|
||||
*** A função =fseek=
|
||||
|
||||
As funções da família =fseek= (=stdio.h=) são utilizadas para posicionar
|
||||
ou obter informações sobre o ponteiro interno do arquivo:
|
||||
|
||||
| Função | Descrição | Retorno |
|
||||
|---------+-----------------------------------------------------------------------------------------+--------------------------------|
|
||||
| =fseek= | Define a posição do ponteiro interno. | Sucesso: =0= (=int=) |
|
||||
| =ftell= | Obtém a posição corrente do ponteiro interno. | Sucesso: número do byte (=long=) |
|
||||
| =rewind= | Posiciona o ponteiro interno no byte =0=. | =void= |
|
||||
| =fsetpos= | Interface para =fseek= referenciando a definição do /offset/ a partir do início do arquivo. | Sucesso: =0= (=int=) |
|
||||
| =fgetpos= | Interface para =ftell= escrevendo o /offset/ obtido em um dado endereço. | Sucesso: =0= (=int=) |
|
||||
|
||||
*Notas:*
|
||||
|
||||
- Com a função =fseek=, o novo /offset/ é definido com uma expressão do tipo =long=.
|
||||
- Com a função =fsetpos=, o novo /offset/ é definido em um ponteiro do tipo =fpos_t=.
|
||||
- Com a função =fgetpos=, o /offset/ corrente é escrito em um ponteiro do tipo =fpos_t=.
|
||||
|
||||
#+begin_quote
|
||||
A função =fseek= trabalha com /streams/, mas é possível manipular o ponteiro interno
|
||||
a partir de descritores de arquivos com a chamada de sistema =lseek=.
|
||||
#+end_quote
|
||||
|
||||
*** Pontos de origem de =fseek=
|
||||
|
||||
A função =fseek= recebe 3 argumentos:
|
||||
|
||||
- O /stream/ associado ao arquivo;
|
||||
- A expressão do valor do /offset/ (tipo =long=);
|
||||
- Um inteiro determinando o ponto de origem para a definição do novo /offset/.
|
||||
|
||||
Este é o seu protótipo na =glibc= (=stdio.h=):
|
||||
|
||||
#+begin_src c
|
||||
int fseek(FILE *stream, long offset, int whence);
|
||||
#+end_src
|
||||
|
||||
#+begin_quote
|
||||
O termo /whence/ significa /"a partir de onde"/ e representa o ponto de origem
|
||||
do deslocamento do ponteiro interno do arquivo.
|
||||
#+end_quote
|
||||
|
||||
O terceiro argumento (=whence=) pode receber qualquer valor inteiro, mas
|
||||
a =glibc= oferece três macros para os pontos de origem mais comuns:
|
||||
|
||||
- =SEEK_SET=: o início do arquivo;
|
||||
- =SEEK_END=: o fim do arquivo;
|
||||
- =SEEK_CUR=: o /offset/ corrente.
|
||||
|
||||
*** Abertura de arquivos com "r+"
|
||||
|
||||
Como o /offset/ inicial será o byte =0=, se a primeira operação for uma
|
||||
escrita, os primeiros bytes do arquivo serão sobrescritos. Caso esta
|
||||
não seja a intenção, será preciso deslocar o ponteiro interno para o
|
||||
fim do arquivo:
|
||||
|
||||
#+begin_src c
|
||||
// Abertura do arquivo para leitura e escrita...
|
||||
char *file = "arquivo.txt";
|
||||
FILE *stream = fopen(file, "r+");
|
||||
|
||||
// Posicionar offset no fim do arquivo...
|
||||
fseek(stream, 0, SEEK_END);
|
||||
|
||||
// Rotinas de escrita...
|
||||
#+end_src
|
||||
|
||||
Aqui, nós deslocamos o ponteiro interno em zero bytes a partir do fim do
|
||||
arquivo (origem em =SEEK_END=).
|
||||
|
||||
*** Abertura de arquivos com "a+"
|
||||
|
||||
O /offset/ inicial será o fim do arquivo e, se quisermos começar a leitura
|
||||
a partir de seu início, será preciso deslocar o ponteiro interno para lá:
|
||||
|
||||
#+begin_src c
|
||||
// Abertura do arquivo para leitura e escrita...
|
||||
char *file = "arquivo.txt";
|
||||
FILE *stream = fopen(file, "r+");
|
||||
|
||||
// Posicionar offset no início do arquivo...
|
||||
fseek(stream, 0, SEEK_SET);
|
||||
|
||||
// Rotinas de leitura...
|
||||
#+end_src
|
||||
|
||||
Desta vez, nós deslocamos o ponteiro interno em zero bytes a partir do
|
||||
início do arquivo (origem em =SEEK_SET=).
|
||||
|
||||
** Procedimentos úteis
|
||||
|
||||
Para encerrar esta aula (e o nosso curso), aqui estão alguns exemplos de
|
||||
procedimentos gerais úteis envolvendo a manipulação de arquivos.
|
||||
|
||||
*** Quantidade de linhas
|
||||
|
||||
|
||||
#+begin_src c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(void) {
|
||||
// Abertura do arquivo para leitura...
|
||||
char *file = "meuarquivo.txt";
|
||||
FILE *stream = fopen(file, "r");
|
||||
if (!stream) {
|
||||
fprintf(stderr, "Erro ao abrir o arquivo!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Contagem de linhas...
|
||||
char buf[BUFSIZ]; // Buffer para ler blocos do arquivo (8192 bytes).
|
||||
int lines = 0; // Total de linhas encontradas.
|
||||
|
||||
// Lê uma linha até encontrar \n, até BUFSIZ-1 ou até EOF...
|
||||
while (fgets(buf, BUFSIZ, stream) != NULL) {
|
||||
// Só conta uma linha se houver \n no buffer...
|
||||
if (buf[strlen(buf) - 1] == '\n' ) lines++;
|
||||
}
|
||||
// Se a última linha não contiver \n, ela também será contada...
|
||||
if (lines > 0 && buf[strlen(buf) - 1] != '\n') lines++;
|
||||
|
||||
// Fechamento do arquivo...
|
||||
fclose(stream);
|
||||
|
||||
// Impressão do resultado...
|
||||
printf("%d linhas", lines);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#+end_src
|
||||
|
||||
*** Obter o tamanho do arquivo
|
||||
|
||||
#+begin_src c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
// Abertura do arquivo...
|
||||
char *file = "meuarquivo.txt";
|
||||
FILE *stream = fopen(file, "rb");
|
||||
if (!stream) {
|
||||
perror("Erro ao abrir o arquivo");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Posiciona o ponteiro de leitura no final do arquivo...
|
||||
if (fseek(stream, 0, SEEK_END) != 0) {
|
||||
perror("Erro ao deslocar o offset para o final");
|
||||
fclose(stream);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Obtém o offset corrente (tamanho do arquivo em bytes)...
|
||||
long fsize = ftell(stream);
|
||||
if (fsize == -1L) {
|
||||
perror("Erro ao obter o offset corrente");
|
||||
fclose(stream);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Exibe o tamanho do arquivo...
|
||||
printf("Tamanho do arquivo: %ld bytes\n", fsize);
|
||||
|
||||
// Fechamento do arquivo...
|
||||
fclose(stream);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#+end_src
|
||||
|
||||
*** Testar se um arquivo está vazio (0 bytes)
|
||||
|
||||
#+begin_src c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
// Abertura do arquivo...
|
||||
char *file = "meuarquivo.txt";
|
||||
FILE *stream = fopen(file, "r");
|
||||
if (!stream) {
|
||||
perror("Erro na abertura do arquivo");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// is_empty recebe 1 se o arquivo estiver vazio...
|
||||
int is_empty = (fseek(stream, 0, SEEK_END) == 0 && ftell(stream) == 0);
|
||||
|
||||
// Fechamento do arquivo...
|
||||
fclose(stream);
|
||||
|
||||
// O programa terminará com sucesso (0) se o arquivo estiver vazio...
|
||||
return !is_empty;
|
||||
}
|
||||
#+end_src
|
||||
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
* Exercícios da aula 15: Abertura de arquivos para escrita
|
||||
|
||||
- [[../../aulas/14-wfiles/README.org][Anotações da aula]]
|
||||
- [[../../aulas/15-wfiles/README.org][Anotações da aula]]
|
||||
- [[https://youtu.be/vL8vy3krcKc][Vídeo]]
|
||||
|
||||
** 1. Programa 'nf' (new file)
|
||||
|
|
57
exercicios/16/README.org
Normal file
57
exercicios/16/README.org
Normal file
|
@ -0,0 +1,57 @@
|
|||
#+title: Curso Básico da Linguagem C
|
||||
#+subtitle: Exercícios
|
||||
#+author: Blau Araujo
|
||||
#+startup: show2levels
|
||||
#+options: toc:3
|
||||
|
||||
* Exercícios da aula 16: Abertura de arquivos para leitura e escrita
|
||||
|
||||
- [[../../aulas/16-rwfiles/README.org][Anotações da aula]]
|
||||
- [[https://youtu.be/B42KIZfivsg][Vídeo]]
|
||||
|
||||
** 1. Contando e inserindo linhas
|
||||
|
||||
Dado o arquivo =lorem.txt=, abaixo:
|
||||
|
||||
#+begin_example
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
Curabitur pretium tincidunt lacus. Nulla gravida orci a odio.
|
||||
Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris.
|
||||
Integer in mauris eu nibh euismod gravida. Duis ac turpis.
|
||||
Integer vitae libero ac risus egestas placerat. Praesent eu lacus quam.
|
||||
Morbi ac felis. Suspendisse ac metus gravida, cursus nunc eu, dictum risus.
|
||||
#+end_example
|
||||
|
||||
Escreva um programa que determine quantas linhas ele tem e escreva esse resultado
|
||||
no início deste mesmo arquivo segundo o formato abaixo:
|
||||
|
||||
#+begin_example
|
||||
Este arquivo tinha X linhas, agora tem X+2 linhas...
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
Curabitur pretium tincidunt lacus. Nulla gravida orci a odio.
|
||||
Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris.
|
||||
Integer in mauris eu nibh euismod gravida. Duis ac turpis.
|
||||
Integer vitae libero ac risus egestas placerat. Praesent eu lacus quam.
|
||||
Morbi ac felis. Suspendisse ac metus gravida, cursus nunc eu, dictum risus.
|
||||
#+end_example
|
||||
|
||||
** 2. Desafio: Trocando palavras
|
||||
|
||||
Utilizando o mesmo arquivo anterior (na sua forma original), crie um programa que
|
||||
substitua todas as ocorrências da palavra =gravida= por =>ACHEI<=, imprimindo no terminal
|
||||
a quantidade de ocorrências e em que linhas e colunas do texto elas foram encontradas.
|
||||
|
||||
** 3. Desafio: O código Da Vinci
|
||||
|
||||
Utilizando, mais uma vez, o arquivo de exemplo na sua forma original, crie um
|
||||
programa que reescreva seu conteúdo invertendo a ordem dos caracteres de cada linha,
|
||||
como se estivéssemos vendo o texto em um espelho.
|
Loading…
Add table
Reference in a new issue