Esta página descreve superficialmente as funções "de entrada" (= input) e "de saída" (= output) mais importantes da linguagem C. Todas estão na biblioteca stdio. Portanto, o seu programa deve ter um
#include <stdio.h>
para usar essas funções.
A função printf (abreviatura de print formatted) exibe na tela do monitor uma lista "formatada" de números, caracters, strings etc. O primeiro argumento da função é uma string que especifica o formato da impressão.
A função scanf lê do teclado (= keyboard) e "formata" uma lista de números, caracters, strings etc. O primeiro argumento da função é uma string que especifica o formato da lista a ser lida. Os demais argumentos são os endereços dos objetos onde os valores lidos serão armazenados.
Exemplo:
#include <stdio.h> int main (void) { int a, b; double media; scanf ("%d %d", &a, &b); media = (a + b) / 2.0; printf ("A média de %d e %5d é %7.2f\n", a, b, media); return EXIT_SUCCESS; }
Supondo que o nome do programa é xx, teremos o seguinte resultado (o computador escreve em vermelho e o usuário em azul):
prompt> xx 222 333 A média de 222 e 333 é 277.50 prompt>
Um arquivo (= file) é uma seqüência de bytes que reside em um disco magnético. Abstratamente, um arquivo tem estrutura semelhante à memória do computador. Mas, ao contrário do que acontece com a memória do computador, os bytes de um arquivo não podem ser endereçados individualmente. Assim, o acesso a um arquivo é estritamente seqüencial: para chegar ao 5º byte é preciso passar pelo 1º, 2º, 3º e 4º bytes.
Para manipular um arquivo dentro de um programa, é preciso associar a ele uma variável do tipo FILE *. Essa operação de associação é conhecida como "abertura" do arquivo e é executada pela função fopen (abreviatura de file open). O primeiro argumento de fopen é o nome do arquivo e o segundo argumento é "r" ou "w" para indicar se o arquivo deve ser aberto "para leitura" ou "para escrita". Se fopen não encontra o arquivo especificado, devolve o valor NULL.
Depois de usar o arquivo, é preciso "fechá-lo" com a função fclose (abreviatura de file close).
Exemplo: Digamos que o arquivo dados.txt contém uma seqüência de números inteiros separados por brancos. O programa abaixo calcula a média dos números. Para ler o arquivo, o programa usa a função fscanf (abreviatura de file scanf):
#include <stdio.h> #define TRUE 1 int main (void) { int x, n, k; double soma; FILE *entrada; entrada = fopen ("dados.txt", "r"); if (entrada == NULL) { printf ("\nNão encontrei arquivo\n"); exit (EXIT_FAILURE); } soma = n = 0; while (TRUE) { k = fscanf (entrada, "%d", &x); if (k != 1) break; soma += x; n += 1; } fclose (entrada); printf ("A média dos números é %f\n", soma / n); return EXIT_SUCCESS; }
A função fscanf, tal como a função scanf, devolve o número de objetos efetivamente lidos. O programa acima usa isso para detectar o fim do arquivo. A propósito: o programa supõe que o arquivo contém pelo menos um número!
O teclado é um "arquivo padrão de entrada" (= standard input). Ele está permanente "aberto" e é representado pela constante stdin. Portanto fscanf(stdin,...) equivale a scanf(...).
Algo análogo acontece com as funções printf, fprintf e o "arquivo" stdout, que representa a tela do monitor.
A função mais básica de entrada de dados — mais básica que scanf — é getc (o nome é uma abreviatura de get character). Cada chamada da função lê um caracter de um arquivo. Se arq aponta um arquivo então getc(arq) lê o próximo caracter do arquivo. Em particular, getc(stdin) lê o próximo caracter do teclado.
A função correspondente de gravação de caracteres é putc (o nome é uma abreviatura de put character). O primeiro argumento da função é o caracter que você deseja gravar e o segundo é o arquivo onde o caracter deve ser gravado. Por exemplo, putc('*', stdout) exibe um * na tela do monitor.
Exemplo: O programa abaixo lê uma linha de caracteres do teclado, armazena essa linha em um vetor (= array) e em seguida exibe esses caracteres no monitor. Vamos supor que a linha tem no máximo 100 caracteres (incluindo o '\n' final):
#include <stdio.h> #define TRUE 1 int main (void) { char linha[100]; int i, j; j = 0; while (TRUE) { linha[j] = getc (stdin); if (linha[j] == '\n') break; j = j + 1; } for (i = 0; i <= j; i += 1) putc (linha[i], stdout); return EXIT_SUCCESS; }
Outro exemplo: O programa abaixo lê o primeiro caracter do arquivo dados.txt e exibe esse caracter na tela do monitor (o program tem um defeito, que discutiremos a seguir):
#include <stdio.h>
int main (void) {
char c; /* erro */
FILE *entrada;
entrada = fopen ("dados.txt", "r");
if (entrada == NULL) exit (EXIT_FAILURE);
c = getc (entrada);
fclose (entrada);
putc (c, stdout);
return EXIT_SUCCESS;
}
Que acontece se getc tenta ler o próximo caracter de um arquivo que já acabou? É preciso que getc devolva algum tipo de "caracter inválido". Acontece que todos os 256 caracteres são "válidos"!
Para resolver o impasse, getc não devolve um char mas sim um int, pois o conjunto de valores de int contém o conjunto de valores de char e é maior que esse último. Se o arquivo tiver acabado, getc devolve um int que não possa ser confundido com um char. Mais especificamente, a função faz o seguinte:
Se houver um próximo caracter no arquivo, getcCaso contrário (ou seja, se o arquivo não tiver mais caracteres), getc devolve –1.
- lê o caracter como se ele fosse um unsigned char,
- transforma-o em um int
- e devolve o resultado.
Para ser mais exato, se o arquivo não tem mais caracteres a função devolve a constante EOF (abreviatura de end of file), que está definida no arquivo-interface stdio.h. Em muitos computadores — mas não em todos! — o valor de EOF é –1.
A solução adotado por getc é uma boa lição de projeto de algoritmos. Situações análogas acontecem em muitas outras ocasiões: a função devolve um objeto que pertence a um superconjunto do conjunto em que estamos realmente interessados.
Exemplo: O seguinte fragmento de código exibe o próximo caracter do arquivo a menos que estejamos no fim do arquivo:
int i; i = getc (entrada); if (i != EOF) printf ("%c", i); else printf ("\nO arquivo terminou!");
Se o arquivo for stdin (ou seja, o teclado) o sinal de fim-de-arquivo é produzido pela combinação de teclas Ctrl-D.
unsigned char c; while ((c = getc (entrada)) != EOF) printf ("%c ", c);
int main (void) { FILE *entrada; int c; entrada = fopen ("dados.txt", "r"); while ((c = getc (entrada)) != EOF) printf ("%c ", c); fclose (entrada); return EXIT_SUCCESS; }
Para ganhar inspiração, analise o comportamento do utilitário wc (abreviatura de word count).