next up previous contents
Next: Rotinas para interação com Up: Rotinas para entrada e Previous: Interação com dispositivos padrão   Sumário


Interação com arquivos

Os dispositivos padrão de entrada e saída são apenas casos especiais de arquivos.

Os arquivos referentes a teclado e tela são abertos automaticamente pelo sistema quando se inicia a execução de um programa. Eles podem ser acessados através dos manipuladores stdin (entrada padrão, teclado) e stdout (saída padrão, tela). Além destes dois arquivos, um terceiro arquivo padrão também é iniciado pelo sistema -- o arquivo padrão de mensagens de erro, stderr, também associado à tela. Por exemplo, para enviar uma mensagem de erro para a saída padrão de erros, a função fprintf pode ser utilizada, como em

    fprintf(stderr, "Mensagem de erro");

Essa função tem o mesmo comportamento que a função printfC.1, recebendo como primeiro argumento uma variável do tipo FILE *.

Há rotinas de acesso a arquivos similares àquelas descritas para a interação com teclado e tela. (Na verdade, aquelas rotinas são criadas a partir destas.)

Por exemplo, para obter um caráter de um arquivo pode-se utilizar a rotina getc:

    #include <stdio.h>
    int getc(FILE *);
Assim, getchar é equivalente a getc(stdin). Há também uma rotina fgetc que tem o mesmo formato. A diferença entre elas é que getc é uma macro enquanto que fgetc é uma função.

Observe que o valor de retorno de getc é um inteiro. Isto permite testar se o caráter obtido é EOF (definido em stdio.h), que é um valor que não é armazenável em um tipo char. Por exemplo, o seguinte programa para apresentar o conteúdo de um arquivo texto na tela pode não terminar propriamente:

    /*
     *  Exemplo de programa "type" que pode nao funcionar
     */
    #include <stdio.h>

    main(int argc, char *argv[]) {
      char  ch;       /* deve ser int! */
      FILE *arq;

      /* testa se numero de argumentos correto */
      if (argc != 2) {
        printf("Uso: %s <nome arquivo>\n",argv[0]);
        return(1);
      }
      /* abre arquivo para leitura */
      arq = fopen(argv[1],"r");
      if (arq == 0) {
        perror(argv[1]);
        return(1);
      }
      /* apresenta arquivo caracter a caracter */
      do {
        ch = getc(arq);
        putchar(ch);
      } while (ch != EOF);

      /* finalizacoes */
      fclose(arq);
      return(0);
    }

O programa deste exemplo pode não terminar porque ch, sendo do tipo char, nunca será igual a EOF. Mudando-se a declaração de ch para int resolverá o problema.

Observe também neste exemplo a utilização da rotina de impressão de erros do sistema, perror:

    void perror(char *);
Quando algum recurso do sistema operacional (neste caso, o sistema de arquivos) é utilizado e um erro ocorre, esta rotina pode ser utilizada para detectar que tipo de erro ocorreu. O argumento de perror é uma string que irá preceder a mensagem de erro do sistema. Por exemplo, suponha que o usuário tente acessar um arquivo chamado abobora que não existe. Então a abertura de arquivo para leitura irá falhar, e a seguinte mensagem será apresentada:
    abobora: No such file or directory

Para inserir um caráter em um arquivo, a rotina putc pode ser usada:

    #include <stdio.h>
    int putc(char, FILE *);

Acesso a dados formatados em arquivos pode ser realizado através das rotinas fprintf e fscanf,

    #include <stdio.h>
    int fprintf(FILE *, char *, ...);
    int fscanf(FILE *, char *, ...);

A entrada e saída de dados binários são suportadas pelas rotinas fread (leitura) e fwrite (escrita):

    #include <stdio.h>
    int fread(void *aptr, int tam, int qtde, FILE *arq);
    int fwrite(void *aptr, int tam, int qtde, FILE *arq);
Estas rotinas suportam a transferência de blocos de qtde elementos de tamanho tam bytes cada elemento entre o arquivo com manipulador arq e a área de memória cujo endereço inicial é aptr. O valor retornado é o número de elementos transferidos de fato.

Por exemplo, supondo que um arquivo teste.dat contém cem números inteiros armazenados em formato binário (isto é, os padrões de bits da representação inteira de cada número são armazenados no arquivo). O seguinte programa lê estes cem inteiros do arquivo, incrementa cada inteiro caso seu conteúdo seja diferente de 0, e escreve de volta os valores atualizados para o arquivo:

    /*
     *  atualiza NELEM valores inteiros em um arquivo NOMARQ
     */
    #include <stdio.h>

    #define NELEM  100
    #define NOMARQ "teste.dat"
   
    int main() {
        FILE *fp;
        int buffer[NELEM];
        int i, qtde_lida;

        /* abrir arquivo */
        if ((fp = fopen(NOMARQ,"rw")) == 0) {
           perror(NOMARQ);
           return(1);
        }

        /* le dados */
        qtde_lida = fread(buffer, sizeof(int), NELEM, fp);

        /* atualiza */
        for (i=0; i<qtde_lida; ++i)
            if (buffer[i] != 0)
                buffer[i]++;

        /* escreve dados atualizados */
        fwrite(buffer, sizeof(int), qtde_lida, fp);

        /* finalizacoes */
        fclose(fp);
        return(0);
}


next up previous contents
Next: Rotinas para interação com Up: Rotinas para entrada e Previous: Interação com dispositivos padrão   Sumário
Ivan L. M. Ricarte 2003-02-14