Eu tenho um arquivo de texto chamado test.txt
Quero escrever um programa C que possa ler este arquivo e imprimir o conteúdo no console (suponha que o arquivo contenha apenas texto ASCII).
Não sei como obter o tamanho da minha variável de string. Como isso:
char str[999];
FILE * file;
file = fopen( "test.txt" , "r");
if (file) {
while (fscanf(file, "%s", str)!=EOF)
printf("%s",str);
fclose(file);
}
O tamanho 999
não funciona porque a string retornada por fscanf
pode ser maior do que isso. Como posso resolver isso?
fonte
stdout
.c
é int e C garantirá queEOF
não seja igual a nenhum caractere válido.Há muitas respostas boas aqui sobre como lê-lo em partes, só vou mostrar um pequeno truque que lê todo o conteúdo de uma vez em um buffer e o imprime.
Não estou dizendo que é melhor. Não é, e como Ricardo às vezes pode ser ruim, mas acho que é uma boa solução para os casos simples.
Eu polvilhei com comentários porque há muita coisa acontecendo.
#include <stdio.h> #include <stdlib.h> char* ReadFile(char *filename) { char *buffer = NULL; int string_size, read_size; FILE *handler = fopen(filename, "r"); if (handler) { // Seek the last byte of the file fseek(handler, 0, SEEK_END); // Offset from the first to the last byte, or in other words, filesize string_size = ftell(handler); // go back to the start of the file rewind(handler); // Allocate a string that can hold it all buffer = (char*) malloc(sizeof(char) * (string_size + 1) ); // Read it all in one operation read_size = fread(buffer, sizeof(char), string_size, handler); // fread doesn't set it so put a \0 in the last position // and buffer is now officially a string buffer[string_size] = '\0'; if (string_size != read_size) { // Something went wrong, throw away the memory and set // the buffer to NULL free(buffer); buffer = NULL; } // Always remember to close the file. fclose(handler); } return buffer; } int main() { char *string = ReadFile("yourfile.txt"); if (string) { puts(string); free(string); } return 0; }
Deixe-me saber se é útil ou você pode aprender algo com ele :)
fonte
buffer[string_size] = '\0';
vez destring_size+1
? Afaik a string real vai de0
parastring_size-1
e o\0
caractere precisa estar emstring_size
, certo?ftell
efseek
encontrar o tamanho de um arquivo não é seguro: securecoding.cert.org/confluence/display/seccode/…fclose(handle)
calloc(2)
vez demalloc(1)
ignorar a necessidade de definir o terminador nulo.Em vez disso, apenas imprima diretamente os caracteres no console porque o arquivo de texto pode ser muito grande e você pode precisar de muita memória.
#include <stdio.h> #include <stdlib.h> int main() { FILE *f; char c; f=fopen("test.txt","rt"); while((c=fgetc(f))!=EOF){ printf("%c",c); } fclose(f); return 0; }
fonte
Use "read ()" em vez de fscanf:
ssize_t read(int fildes, void *buf, size_t nbyte);
Aqui está um exemplo:
http://cmagical.blogspot.com/2010/01/c-programming-on-unix-implementing-cat.html
Parte desse exemplo:
f=open(argv[1],O_RDONLY); while ((n=read(f,l,80)) > 0) write(1,l,n);
Uma abordagem alternativa é usar
getc
/putc
ler / escrever 1 caractere por vez. Muito menos eficiente. Um bom exemplo: http://www.eskimo.com/~scs/cclass/notes/sx13.htmlfonte
read
permitirá que você leia um certo número de caracteres. Leia o suficiente para encher o buffer e, em seguida, despeje-o na tela, limpe-o e repita até chegar ao final do arquivo.Duas abordagens vêm à mente.
Primeiro, não use
scanf
. Use ofgets()
que recebe um parâmetro para especificar o tamanho do buffer e que deixa quaisquer caracteres de nova linha intactos. Um loop simples sobre o arquivo que imprime o conteúdo do buffer deve naturalmente copiar o arquivo intacto.Em segundo lugar, use
fread()
ou o idioma C comum comfgetc()
. Eles processariam o arquivo em pedaços de tamanho fixo ou um único caractere por vez.Se você deve processar o arquivo em strings delimitadas por espaços em branco, use
fgets
oufread
para ler o arquivo e algo comostrtok
dividir o buffer em espaços em branco. Não se esqueça de lidar com a transição de um buffer para o próximo, uma vez que suas strings de destino provavelmente ultrapassarão o limite do buffer.Se houver um requisito externo a ser usado
scanf
para fazer a leitura, limite o comprimento da string que ela pode ler com um campo de precisão no especificador de formato. No seu caso com um buffer de 999 bytes, digascanf("%998s", str);
qual irá gravar no máximo 998 caracteres no buffer, deixando espaço para o terminador nul. Se strings únicas maiores que seu buffer forem permitidas, você terá que processá-las em duas partes. Caso contrário, você terá a oportunidade de informar ao usuário sobre um erro educadamente, sem criar uma brecha de segurança de estouro de buffer.Independentemente disso, sempre valide os valores de retorno e pense em como lidar com entradas incorretas, maliciosas ou apenas malformadas.
fonte
Você pode usar
fgets
e limitar o tamanho da string de leitura.char *fgets(char *str, int num, FILE *stream);
Você pode alterar o
while
em seu código para:while (fgets(str, 100, file)) /* printf("%s", str) */;
fonte
Você poderia ler o arquivo inteiro com alocação de memória dinâmica, mas não é uma boa ideia porque se o arquivo for muito grande, você pode ter problemas de memória.
Portanto, é melhor ler partes curtas do arquivo e imprimi-lo.
#include <stdio.h> #define BLOCK 1000 int main() { FILE *f=fopen("teste.txt","r"); int size; char buffer[BLOCK]; // ... while((size=fread(buffer,BLOCK,sizeof(char),f)>0) fwrite(buffer,size,sizeof(char),stdout); fclose(f); // ... return 0; }
fonte