Ferramentas do usuário

Ferramentas do site


prog2:acesso_a_arquivos

Diferenças

Aqui você vê as diferenças entre duas revisões dessa página.

Link para esta página de comparações

Ambos lados da revisão anterior Revisão anterior
prog2:acesso_a_arquivos [2019/05/13 15:47]
maziero [Outras funções]
prog2:acesso_a_arquivos [2019/05/14 23:26] (atual)
maziero
Linha 1: Linha 1:
 +====== Acesso a arquivos ======
 +
 +Aqui serão descritas algumas das funções mais usuais para operações de entrada/​saída em arquivos na linguagem C. A maioria das funções aqui descritas está declarada no arquivo de cabeçalho ''​stdio.h'':​
 +
 +<​code>​
 +#include <​stdio.h>​
 +</​code>​
 +
 +===== Conceitos básicos =====
 +
 +==== Tipos de arquivos ====
 +
 +Um arquivo armazena uma sequência de bytes, cuja interpretação fica a cargo da aplicação. Contudo, para facilitar a manipulação de arquivos, a linguagem C considera dois tipos de arquivos:
 +
 +  * **arquivos de texto**: contém sequências de bytes representando caracteres de texto, separadas por caracteres de controle como ''​\n''​ ou ''​\r''​ e usando uma codificação como ASCII, ISO-8859-1 ou Unicode. São usados para armazenar informação textual, como código-fonte,​ páginas Web, arquivos de configuração,​ etc.
 +  * **arquivos binários**:​ contém sequências de bytes, cuja interpretação fica totalmente a cargo da aplicação. São usualmente empregados para armazenar imagens, vídeos, músicas, dados compactados,​ etc.
 +
 +==== Streams e descritores ====
 +
 +As operações sobre arquivos em C podem ser feitas de duas formas:
 +
 +  * por **streams**:​ acesso em um nível mais elevado, independente de sistema operacional e portanto portável. Permite entrada/​saída formatada, mas pode ter um desempenho inferior ao acesso de baixo nível. //Streams// são acessadas através de variáveis do tipo ''​FILE*''​. ​
 +  * por **descritores**:​ acesso através dos descritores de arquivo fornecidos pelo sistema operacional,​ pouco portável mas com melhor desempenho.
 +  ​
 +Na sequência deste texto serão apresentadas as funções de acesso usando //​streams//,​ que valem para qualquer sistema operacional. Explicações sobre entrada/​saída usando descritores UNIX podem ser encontradas [[pua:​operacoes_usando_descritores|nesta página]].
 +
 +==== Entradas e saídas padrão ====
 +
 +Cada programa em execução tem acesso a três arquivos padrão definidos no arquivo de cabeçalho ''​stdio.h'',​ que são:
 +
 +  * ''​FILE* stdin'':​ a entrada padrão, normalmente associada ao teclado do terminal, usada para informar dados ao programa (''​scanf'',​ por exemplo).
 +  * ''​FILE* stdout'':​ a saída padrão, normalmente associada à tela do terminal, usada para as saídas normais do programa (''​printf'',​ por exemplo).
 +  * ''​FILE* stderr'':​ a saída de erro, normalmente associada à tela do terminal, usada para mensagens de erro.
 +
 +===== Abrindo e fechando arquivos =====
 +
 +Antes de ser usado, um arquivo precisa ser "​aberto"​ pela aplicação (com execção dos arquivos padrão descritos acima, que são abertos automaticamente). Isso é realizado através da chamada ''​fopen'':​
 +
 +<code c>
 +#include <​stdio.h>​
 +FILE* fopen (const char *filename, const char *opentype)
 +</​code>​
 +
 +Abre um arquivo indicado por ''​filename''​ e retorna um ponteiro para o //stream//. A //string// ''​opentype''​ define o modo de abertura do arquivo:
 +
 +  * ''​r''​ : abre um arquivo existente para leitura (//read//).
 +  * ''​w''​ : abre um arquivo para escrita (//​write//​). Se o arquivo já existe, seu conteúdo é descartado. Senão, um novo arquivo vazio é criado.
 +  * ''​a''​ : abre um arquivo para concatenação (//​append//​). Se o arquivo já existe, seu conteúdo é preservado e as escritas serão concatenadas no final do arquivo. Senão, um novo arquivo vazio é criado.
 +  * ''​r+''​ : abre um arquivo existente para leitura e escrita. O conteúdo anterior do arquivo é preservado e o ponteiro é posicionado no início do arquivo.
 +  * ''​w+''​ : abre um arquivo para leitura e escrita. Se o arquivo já existe, seu conteúdo é descartado. Senão, um novo arquivo vazio é criado.
 +  * ''​a+''​ : abre um arquivo para escrita e concatenação. Se o arquivo já existe, seu conteúdo é preservado e as escritas serão concatenadas no final do arquivo. Senão, um novo arquivo vazio é criado. O ponteiro de leitura é posicionado no início do arquivo, enquanto as escritas são efetuadas no seu final.
 +
 +<note important>​
 +Os modos ''​a''​ e ''​a+''​ **sempre** escreverão no final do arquivo, mesmo se o cursor do mesmo for reposicionado.
 +</​note>​
 +
 +<code c>
 +#include <​stdio.h>​
 +int fclose (FILE* stream)
 +</​code>​
 +
 +Fecha um //stream//. Dados de saída em //buffer// são escritos, enquanto dados de entrada são descartados.
 +
 +<code c>
 +#include <​stdio.h>​
 +FILE* freopen (const char *filename, const char *opentype, FILE *stream)
 +</​code>​
 +
 +Fecha e abre novamente um //stream//, permitindo alterar o arquivo e/ou modo de abertura.
 +
 +Exemplo: abrindo o arquivo ''​x''​ em leitura:
 +
 +<code c fopen-read.c>​
 +#include <​stdio.h>​
 +#include <​stdlib.h>​
 +
 +int main ()
 +{
 +   FILE* arq ;
 +  ​
 +   arq = fopen ("​x",​ "​r"​) ;
 +  ​
 +   if ( ! arq )
 +   {
 +      perror ("Erro ao abrir arquivo x") ;
 +      exit (1) ; // encerra o programa com status 1
 +   }
 +  ​
 +   ​fclose (arq) ;
 +   exit (0) ; 
 +}
 +</​code>​
 +
 +Exemplo: abre o arquivo ''​x''​ em leitura/​escrita,​ criando-o se não existir:
 +
 +<code c fopen-write.c>​
 +#include <​stdio.h>​
 +
 +int main (int argc, char *argv[])
 +{
 +   FILE* arq ;
 +   
 +   arq = fopen ("​x",​ "​w+"​) ;
 +   
 +   if ( ! arq )
 +   {
 +      perror ("Erro ao abrir/criar arquivo x") ;
 +      exit (1) ; // encerra o programa com status 1
 +   }
 +   
 +   ​fclose (arq) ;
 +   exit (0) ;
 +}
 +</​code>​
 +
 +===== Arquivos-texto =====
 +
 +Arquivos-texto contêm sequências de bytes representando um texto simples (sem formatações especiais, como negrito, itálico, etc), como código-fonte ou uma página em HTML, por exemplo.
 +
 +Em um arquivo-texto,​ os caracteres do texto são representados usando uma codificação padronizada,​ para que possam ser abertos por diferentes aplicações em vários sistemas operacionais. As codificações de caracteres mais usuais hoje são:
 +
 +  * [[https://​en.wikipedia.org/​wiki/​ASCII|ASCII]]:​ criada em 1963 para representar os caracteres comuns da língua inglesa, usando 7 bits (valores entre 0 e 127).
 +  * [[https://​en.wikipedia.org/​wiki/​ISO/​IEC_8859|ISO-8859]]:​ conjunto de extensões da codificação ASCII para suportar outras línguas com alfabeto latino, como o Português. Os caracteres entre 0 e 127 os mesmos da tabela ASCII, enquanto os caracteres entre 128 e 255 são específicos. Por exemplo, a extensão [[https://​en.wikipedia.org/​wiki/​ISO/​IEC_8859-1|ISO-8859-1]] contém os caracteres acentuados e cedilhas da maior parte das linguagens ocidentais (Português,​ Espanhol, Francês etc).
 +  * [[https://​en.wikipedia.org/​wiki/​UTF-8|UTF8]]:​ codificação baseada no padrão Unicode, capaz de representar mais de um milhão de caracteres em todas as línguas conhecidas, além de sinais gráficos (como //​emojis//​). Os caracteres em UTF8 podem usar entre 1 e 4 bytes para sua representação,​ o que torna sua manipulação mais complexa em programas.
 +
 +Além dos caracteres em si, as codificações geralmente suportam **caracteres de controle**, ​ que permitem representar algumas estruturas básicas de formatação do texto, como quebras de linha. Alguns caracteres de controle presentes nas codificações acima são:
 +
 +^ nome ^ valor ^ representação ^
 +| null | 0 | NUL, \0, %%^%%@ |
 +| bell | 7 | BEL, \a, %%^%%G |
 +| backspace | 8 | BS, \b, %%^%%H |
 +| tab | 9 | HT, \t, %%^%%I |
 +| line feed | 10 | LF, \n, %%^%%J |
 +| form feed | 12 | FF, \f, %%^%%L |
 +| carriage return | 13 | CR, \r, %%^%%M |
 +| escape | 27 | ESC, %%^%%[ |
 +
 +==== Saída simples ====
 +
 +Estas funções permitem gravar caracteres ou strings simples em //​streams//​.
 +
 +<code c>
 +#include <​stdio.h>​
 +
 +int fputc   (int c, FILE* stream) ​  // escreve o caractere equivalente a "​c"​ em "​arq"​
 +int putc    (int c, FILE* stream) ​  // idem, implementada como macro
 +int putchar (int c)                 // idem, em "​stdout"​
 +
 +int fputs (const char *s, FILE* stream) ​ // escreve a string "​s"​ no stream indicado
 +int puts  (const char *s)                // idem, em "​stdout"​
 +</​code>​
 +
 +==== Entrada simples ====
 +
 +Estas funções permitem ler caracteres isolados de um //stream//. O valor lido é um ''​int''​ indicando o caractere lido ou então o valor especial ''​EOF''​ (//​End-Of-File//​):​
 +
 +<code c>
 +#include <​stdio.h>​
 +
 +int fgetc (FILE* stream) ​ // Lê o próximo caractere do //stream// indicado
 +int getc  (FILE* stream) ​ // Idem, implementado como macro (mais rápido)
 +int getchar ()            // Idem, sobre ''​stdin''​
 +</​code>​
 +
 +Para a leitura de strings:
 +
 +<code c>
 +#include <​stdio.h>​
 +char* gets (char *s)
 +</​code>​
 +
 +Lê caracteres de ''​stdin''​ até encontrar um //newline// e os armazena na string ''​s''​. O caractere //newline// é descartado.
 +
 +<note warning>
 +Atenção: a função ''​gets''​ é **perigosa**,​ pois não provê segurança contra //​overflow//​ na string ''​s''​. Sempre que possível, deve ser usada a função ''​fgets''​ ou ''​getline''​.
 +</​note>​
 +
 +<code c>
 +#include <​stdio.h>​
 +char* fgets (char *s, int count, FILE *stream)
 +</​code>​
 +
 +Lê uma linha de caracteres do //stream// e a deposita na string ''​s''​. O tamanho da linha é limitado em ''​count-1''​ caracteres, aos quais é adicionado o '''​\0'''​ que marca o fim da string. O //newline// é incluso.
 +
 +==== Saída formatada ====
 +
 +As operações de entrada e saída formatada usam padrões para formatação dos diversos tipos de dados descritos em livros de programação em C e no manual da GLibC.
 +
 +<code c>
 +#include <​stdio.h>​
 +int printf (const char* format, ...)
 +</​code>​
 +
 +Escreve dados usando a formatação definida em ''​format''​ no //stream// de saída padrão ''​stdout''​.
 +
 +<code c>
 +#include <​stdio.h>​
 +int fprintf (FILE* stream, const char* format, ...)
 +</​code>​
 +
 +Idêntico a ''​printf'',​ usando o stream indicado.
 +
 +<code c>
 +#include <​stdio.h>​
 +int sprintf (char* s, const char* template, ...)
 +</​code>​
 +
 +Similar a ''​printf'',​ mas a saída é depositada na string ''​s''​.
 +
 +<note important>​
 +Atenção: o programador deve garantir que s tenha tamanho suficiente para receber a saída; caso contrário, pode ocorrer um //​overflow//​ com consequências imprevisíveis. As funções ''​snprintf''​ e ''​asprintf''​ são mais seguras e evitam esse problema.
 +</​note>​
 +
 +==== Entrada formatada ====
 +
 +<code c>
 +#include <​stdio.h>​
 +int scanf (const char* format, ...)
 +</​code>​
 +
 +Lê dados do stream ''​stdin''​ de acordo com a formatação definida na string ''​format''​. Os demais argumentos são ponteiros para as variáveis onde os dados lidos são depositados. Retorna o número de dados lidos ou ''​EOF''​.
 +
 +<code c>
 +#include <​stdio.h>​
 +int fscanf (FILE* stream, const char* format, ...)
 +</​code>​
 +
 +Similar a ''​scanf'',​ mas usando como entrada o //stream// indicado.
 +
 +<code c>
 +#include <​stdio.h>​
 +int sscanf (const char* s, const char* format, ...)
 +</​code>​
 +
 +Similar a ''​scanf'',​ mas usando como entrada a string ''​s''​.
 +
 +==== Erros e fim de stream ====
 +
 +<code c>
 +int EOF
 +</​code>​
 +
 +Esta macro define o valor retornado por algumas funções para indicar fim do arquivo ou erro.
 +
 +<code c>
 +#include <​stdio.h>​
 +int feof (FILE* stream)
 +</​code>​
 +
 +Retorna valor não nulo se o //stream// chegou ao seu fim.
 +
 +<code c>
 +#include <​stdio.h>​
 +int ferror (FILE* stream)
 +</​code>​
 +
 +Retorna um valor não nulo se ocorreu um erro em algum acesso anterior ao //​stream//​. ​
 +
 +Além de ajustar o indicador de erro do //stream//, as funções de acesso a //streams// também ajustam a variável ''​errno''​.
 +
 +===== Arquivos binários =====
 +
 +Todos os arquivos contêm sequências de bytes, mas costuma-se dizer que um arquivo é "​binário"​ quando seu conteúdo não é uma informação textual (ou seja, não representa um texto usando codificações como ASCII e outras).
 +
 +Arquivos binários são usados para armazenar informações mais complexa que texto puro, como imagens, música, filmes, código executável,​ etc. A interpretação do conteúdo de um arquivo binário é de responsabilidade da aplicação envolvida.
 +
 +A linguagem C oferece funções para ler e escrever blocos de bytes em arquivos, que efetuam a cópia desses bytes da memória da aplicação para o arquivo, ou vice-versa.
 +
 +==== Leitura/​escrita de blocos ====
 +
 +A funções a seguir permitem ler/​escrever blocos de bytes em arquivos binários:
 +
 +<code c>
 +#include <​stdio.h>​
 +size_t fread (void* data, size_t size, size_t count, FILE* stream)
 +</​code>​
 +
 +Lê até ''​count''​ blocos de tamanho ''​size''​ bytes cada um e os deposita no vetor ''​data'',​ a partir do //stream// indicado. Retorna o número de blocos lidos.
 +
 +<code c>
 +#include <​stdio.h>​
 +size_t fwrite (const void* data, size_t size, size_t count, FILE* stream)
 +</​code>​
 +
 +Escreve até ''​count''​ blocos de tamanho ''​size''​ bytes do vetor ''​data''​ no //stream// indicado. Retorna o número de blocos escritos.
 +
 +<note tip>
 +Essas funções também podem ser usadas para ler/​escrever em arquivos-texto,​ pois textos são sequências de bytes.
 +</​note>​
 +
 +==== Exemplo de uso ====
 +
 +Este exemplo manipula um arquivo binário ''​numeros.dat''​ contendo números reais. São implementadas (em arquivos separados) as operações de escrita de números no arquivo, listagem e ordenação do conteúdo:
 +
 +<code c escreve.c>​
 +#include <​stdio.h>​
 +#include <​stdlib.h>​
 +#include <​time.h>​
 +
 +#define ARQUIVO "​numeros.dat"​
 +#define NUMVAL 10
 +
 +int main (int argc, char *argv[])
 +{
 +  FILE* arq ;
 +  int i, ret ;
 +  float value[NUMVAL] ;
 +
 +  // abre o arquivo em modo "​append"​
 +  arq = fopen (ARQUIVO, "​a"​) ;
 +  if (!arq)
 +  {
 +    perror ("Erro ao abrir arquivo"​) ;
 +    exit (1) ;
 +  }
 +
 +  // inicia gerador de aleatórios
 +  srand (clock()) ;
 +
 +  // gera NUMVAL valores aleatórios reais
 +  for (i = 0; i< NUMVAL; i++)
 +    value[i] = random() / 100000.0 ;
 +
 +  // escreve os valores gerados no final do arquivo
 +  ret = fwrite (value, sizeof(float),​ NUMVAL, arq) ;
 +  if (ret)
 +    printf ("​Gravou %d valores com sucesso!\n",​ NUMVAL) ;
 +  else
 +    printf ("Erro ao gravar...\n"​) ;
 +
 +  // fecha o arquivo
 +  fclose (arq) ;
 +  return (0) ;
 +}
 +</​code>​
 +
 +<code c lista.c>
 +#include <​stdio.h>​
 +#include <​stdlib.h>​
 +
 +#define ARQUIVO "​numeros.dat"​
 +
 +int main (int argc, char *argv[])
 +{
 +  FILE* arq ;
 +  float value ;
 +
 +  // abre o arquivo em modo leitura
 +  arq = fopen (ARQUIVO, "​r"​) ;
 +  if (!arq)
 +  {
 +    perror ("Erro ao abrir arquivo"​) ;
 +    exit (1) ;
 +  }
 +
 +  // lê e imprime os valores contidos no arquivo
 +  fread (&​value,​ sizeof(float),​ 1, arq) ;
 +  while (! feof(arq))
 +  {
 +    printf ("​%f\n",​ value) ;
 +    fread (&​value,​ sizeof(float),​ 1, arq) ;
 +  }
 +
 +  // fecha o arquivo
 +  fclose (arq) ;
 +  return (0) ;
 +}
 +</​code>​
 +
 +<code c ordena.c>​
 +#include <​stdio.h>​
 +#include <​stdlib.h>​
 +
 +#define ARQUIVO "​numeros.dat"​
 +#define MAXVAL 100000
 +
 +float value[MAXVAL] ;
 +int num_values ;
 +
 +int main (int argc, char *argv[])
 +{
 +  FILE* arq ;
 +  int i, j, menor ;
 +  float aux ;
 +
 +  // abre o arquivo em leitura/​escrita,​ preservando o conteúdo
 +  arq = fopen (ARQUIVO, "​r+"​) ;
 +  if (!arq)
 +  {
 +    perror ("Erro ao abrir arquivo"​) ;
 +    exit (1) ;
 +  }
 +
 +  // lê números do arquivo no vetor
 +  num_values = fread (value, sizeof(float),​ MAXVAL, arq) ;
 +  printf ("​Encontrei %d números no arquivo\n",​ num_values) ;
 +
 +  // ordena os números (por seleção)
 +  for (i=0; i < num_values-1;​ i++)
 +  {
 +    // encontra o menor elemento no restante do vetor
 +    menor = i ;
 +    for (j=i+1; j < num_values; j++)
 +      if (value[j] < value[menor])
 +        menor = j ;
 +
 +    // se existe menor != i, os troca entre si
 +    if (menor != i)
 +    {
 +      aux = value[i] ;
 +      value[i] = value[menor] ;
 +      value[menor] = aux ;
 +    }
 +  }
 +
 +  // retorna o ponteiro ao início do arquivo
 +  rewind (arq) ;
 +
 +  // escreve números do vetor no arquivo
 +  fwrite (value, sizeof(float),​ num_values, arq) ;
 +
 +  // fecha o arquivo
 +  fclose (arq) ;
 +  return (0) ;
 +}
 +</​code>​
 +
 +===== Posicionamento no arquivo =====
 +
 +Para cada arquivo aberto em uma aplicação,​ o sistema operacional mantém um contador interno indicando a posição da próxima operação de leitura ou escrita. Esse contador é conhecido como **ponteiro de posição** (embora não seja realmente um ponteiro).
 +
 +Por default, as operações em um arquivo em C ocorrem em posições sucessivas dentro do arquivo: cada leitura (ou escrita) corre **após** a leitura (ou escrita) precedente, até atingir o final do arquivo. Essa forma de acesso ao arquivo é chamada de **acesso sequencial**.
 +
 +Por vezes uma aplicação precisa ler ou escrever em posições específicas de um arquivo, ou precisa voltar a ler uma posição do arquivo que já percorreu anteriormente. Isso ocorre frequentemente em aplicações que manipulam arquivos muito grandes, como vídeos ou bases de dados. Para isso é necessária uma forma de **acesso direto** a posições específicas do arquivo.
 +
 +Em C, o acesso direto a posições específicas de um arquivo é feita através de funções de **posicionamento de ponteiro**, que permitem alterar o valor do ponteiro de posição do arquivo, antes da operação de leitura/​escrita desejada.
 +
 +As funções mais usuais para acessar o ponteiro de posição de um arquivo em C são:
 +
 +<code c>
 +#include <​stdio.h>​
 +int fseek (FILE* stream, long int offset, int whence)
 +</​code>​
 +
 +Ajusta posição do ponteiro no //stream// indicado.
 +
 +O ajuste é definido por ''​offset'',​ enquanto o valor de ''​whence''​ indica se o ajuste é relativo ao início do arquivo (''​SEEK_SET''​),​ à posição corrente (''​SEEK_CUR''​) ou ao final do arquivo (''​SEEK_END''​). Ver também ''​fseeko''​ e ''​fseeko64''​. Exemplos:
 +
 +<code c>
 +                              // posiciona o ponteiro de "​arq":​
 +fseek (arq, 1000, SEEK_SET) ; // 1000 bytes após o início
 +fseek (arq,  300, SEEK_END) ; // 300 bytes antes do fim 
 +fseek (arq, -500, SEEK_CUR) ; // 500 bytes antes da posição atual
 +</​code>​
 +
 +<code c>
 +#include <​stdio.h>​
 +void rewind (FILE* stream)
 +</​code>​
 +
 +Reposiciona o ponteiro no início (posição 0) do //stream// indicado.
 +
 +<code c>
 +#include <​stdio.h>​
 +long int ftell (FILE* stream)
 +</​code>​
 +
 +Informa a posição corrente de leitura/​escrita em ''​stream''​ (ver também ''​ftello''​ e ''​ftello64''​ no manual).
 +
 +<note important>​
 +Todas as funções de manipulação do ponteiro de arquivo consideram as **posições em bytes** a partir do início do arquivo, nunca em registros ou estruturas.
 +</​note>​
 +
 +===== Outras funções =====
 +
 +Para truncar ("​encurtar"​) um arquivo, deixando somente os primeiros ''​length''​ bytes:
 +
 +<code c>
 +#include <​unistd.h>​
 +#include <​sys/​types.h>​
 +
 +int truncate ​ (const char *path, off_t length);
 +int ftruncate (int fd, off_t length);
 +</​code>​
 +
 +Para obter as propriedades (metadados) de um arquivo:
 +
 +<code c>
 +#include <​sys/​types.h>​
 +#include <​sys/​stat.h>​
 +#include <​unistd.h>​
 +
 +int stat  (const char *pathname, struct stat *statbuf);
 +int fstat (int fd, struct stat *statbuf);
 +</​code>​
 +
 +As informações sobre o arquivo serão depositadas pelo núcleo na estrutura ''​statbuf'',​ cujo conteúdo é o seguinte:
 +
 +<code c>
 +struct stat
 +{
 +  dev_t     ​st_dev; ​        /* ID of device containing file */
 +  ino_t     ​st_ino; ​        /* Inode number */
 +  mode_t ​   st_mode; ​       /* File type and mode */
 +  nlink_t ​  ​st_nlink; ​      /* Number of hard links */
 +  uid_t     ​st_uid; ​        /* User ID of owner */
 +  gid_t     ​st_gid; ​        /* Group ID of owner */
 +  dev_t     ​st_rdev; ​       /* Device ID (if special file) */
 +  off_t     ​st_size; ​       /* Total size, in bytes */
 +  blksize_t st_blksize; ​    /* Block size for filesystem I/O */
 +  blkcnt_t ​ st_blocks; ​     /* Number of 512B blocks allocated */
 +  struct timespec st_atim; ​ /* Time of last access */
 +  struct timespec st_mtim; ​ /* Time of last modification */
 +  struct timespec st_ctim; ​ /* Time of last status change */
 +  #define st_atime st_atim.tv_sec ​ /* For backward compatibility */
 +  #define st_mtime st_mtim.tv_sec
 +  #define st_ctime st_ctim.tv_sec
 +};
 +</​code>​
 +
 +===== Exercícios =====
 +
 +  - Escreva um programa em C para informar o número de caracteres presentes em um arquivo de texto.
 +  - Escreva um programa em C para ler um arquivo ''​minusc.txt''​ e escrever um arquivo ''​maiusc.txt''​ contendo o mesmo texto em maiúsculas.
 +  -  Escreva um programa ''​mycp''​ para fazer a cópia de um arquivo em outro: ''​mycp arq1 arq2''​. Antes da cópia, ''​arq1''​ deve existir e ''​arq2''​ não deve existir. Mensagens de erro devem ser geradas caso essas condições não sejam atendidas ou o nome dado a ''​arq2''​ seja inválido.
 +  - o comando ''​grep''​ do UNIX imprime na saída padrão (//​stdout//​) as linhas de um arquivo de entrada que contenham uma determinada string informada como parâmetro. Escreva esse programa em C (dica: use a função ''​strstr''​).
 +  - Escreva três programas C separados para:
 +    - escrever um arquivo com 10 milhões de inteiros ''​long''​ aleatórios,​ armazenados em modo binário;
 +    - ler o arquivo de inteiros em um vetor, ordenar o vetor e reescrever o arquivo;
 +    - escrever na tela os primeiros 10 números e os últimos 10 números contidos no arquivo.
 +
 +Mais exercícios no capítulo 11 da {{apostila_c_-_nce.pdf|apostila do NCE/UFRJ}}.
  
prog2/acesso_a_arquivos.txt · Última modificação: 2019/05/14 23:26 por maziero