Подтвердить что ты не робот

В C, как я должен читать текстовый файл и печатать все строки

У меня есть текстовый файл с именем test.txt

Я хочу написать программу на C, которая может прочитать этот файл и распечатать содержимое на консоли (предположим, что файл содержит только текст ASCII).

Я не знаю, как получить размер моей строковой переменной. Вот так:

char str[999];
FILE * file;
file = fopen( "test.txt" , "r");
if (file) {
    while (fscanf(file, "%s", str)!=EOF)
        printf("%s",str);
    fclose(file);
}

Размер 999 не работает, потому что строка, возвращаемая fscanf, может быть больше. Как я могу это решить?

4b9b3361

Ответ 1

Самый простой способ - прочитать символ и напечатать его сразу после прочтения:

int c;
FILE *file;
file = fopen("test.txt", "r");
if (file) {
    while ((c = getc(file)) != EOF)
        putchar(c);
    fclose(file);
}

c выше int, так как EOF - отрицательное число, а простая char может быть unsigned.

Если вы хотите прочитать файл в кусках, но без динамического распределения памяти, вы можете сделать:

#define CHUNK 1024 /* read 1024 bytes at a time */
char buf[CHUNK];
FILE *file;
size_t nread;

file = fopen("test.txt", "r");
if (file) {
    while ((nread = fread(buf, 1, sizeof buf, file)) > 0)
        fwrite(buf, 1, nread, stdout);
    if (ferror(file)) {
        /* deal with error */
    }
    fclose(file);
}

Второй метод, описанный выше, состоит в том, как вы будете читать файл с динамически распределенным массивом:

char *buf = malloc(chunk);

if (buf == NULL) {
    /* deal with malloc() failure */
}

/* otherwise do this.  Note 'chunk' instead of 'sizeof buf' */
while ((nread = fread(buf, 1, chunk, file)) > 0) {
    /* as above */
}

Ваш метод fscanf() с %s в качестве формата теряет информацию о пробеле в файле, поэтому он не точно копирует файл в stdout.

Ответ 2

Здесь есть много хороших ответов о том, чтобы прочитать его в кусках, я просто покажу вам небольшой трюк, который сразу же будет считывать все содержимое буфера и печатать его.

Я не говорю об этом лучше. Это не так, и, как Рикардо, иногда это может быть плохо, но я считаю это хорошим решением для простых случаев.

Я посыпал его комментариями, потому что там много чего происходит.

#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;
}

Сообщите мне, если это полезно, или вы могли бы что-то узнать от него:)

Ответ 3

Вместо этого просто прямо напечатайте символы на консоли, потому что текстовый файл может быть очень большим, и вам может потребоваться много памяти.

#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;
}

Ответ 4

Используйте "read()" вместо o fscanf:

ssize_t read(int fildes, void *buf, size_t nbyte);

ОПИСАНИЕ

Функция read() пытается прочитать nbyte байты из файла, связанного с дескриптором открытого файла, fildes, в буфер, на который указывает buf.

Вот пример:

http://cmagical.blogspot.com/2010/01/c-programming-on-unix-implementing-cat.html

Рабочая часть из этого примера:

f=open(argv[1],O_RDONLY);
while ((n=read(f,l,80)) > 0)
    write(1,l,n);

Альтернативный подход заключается в использовании getc/putc для чтения/записи 1 char за раз. Гораздо менее эффективно. Хороший пример: http://www.eskimo.com/~scs/cclass/notes/sx13.html

Ответ 5

Вы можете использовать fgets и ограничить размер прочитанной строки.

char *fgets(char *str, int num, FILE *stream);

Вы можете изменить while в вашем коде на:

while (fgets(str, 100, file)) /* printf("%s", str) */;

Ответ 6

Два подхода бросаются в глаза.

Во-первых, не используйте scanf. Используйте fgets(), который принимает параметр, чтобы указать размер буфера, и который оставляет неизменными символы новой строки. Простой цикл над файлом, который печатает содержимое буфера, должен, естественно, копировать файл без изменений.

Во-вторых, используйте fread() или общий C-образ с fgetc(). Они обрабатывали бы файл в куски фиксированного размера или один символ за раз.

Если вы должны обработать файл по строкам с разделителями белого пробела, используйте fgets или fread для чтения файла, а что-то вроде strtok для разделения буфера на пробелы. Не забудьте обработать переход от одного буфера к другому, так как ваши целевые строки, вероятно, будут охватывать границу буфера.

Если для выполнения чтения требуется внешнее требование использовать scanf, ограничьте длину строки, которую она могла бы читать, с полем точности в спецификаторе формата. В вашем случае с буфером из 999 байт, скажите scanf("%998s", str);, который будет писать не более 998 символов в буфер, оставляя место для nul-терминатора. Если разрешены одиночные строки дольше, чем ваш буфер, вам придется обрабатывать их двумя частями. Если нет, у вас есть возможность рассказать пользователю об ошибке вежливо, не создавая отверстия для предотвращения переполнения буфера.

Независимо от этого, всегда проверяйте возвращаемые значения и думайте о том, как обращаться с плохим, злым или некорректным вводом.

Ответ 7

#include <stdio.h>
#include <stdlib.h>
int main() {

int num;
FILE *fptr; 



if ((fptr = fopen("/root/Desktop/my_pass.txt","r")) == NULL) {       // checks if file exists
    puts("File not exists");
    exit(1);                    // for exit(1) is required #include <stdlib.h> 
} else 

fscanf(fptr,"%d", &num);                

printf("My pass is:  %d\n", num);           
fclose(fptr); 

return 0;
}

Ответ 8

Вы можете прочитать весь файл с динамическим распределением памяти, но это не очень хорошая идея, потому что если файл слишком большой, у вас могут быть проблемы с памятью.

Поэтому лучше прочитать короткие фрагменты файла и распечатать его.

#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;
}