Как прочитать полный файл с помощью scanf, может быть, что-то вроде% [^ \ EOF] без цикла в одном выражении - PullRequest
0 голосов
/ 22 сентября 2019

Я хочу знать, смогу ли я прочитать полный файл с одним оператором scanf.Я прочитал это с кодом ниже.

#include<stdio.h>

int main()
{
    FILE * fp;
    char arr[200],fmt[6]="%[^";
    fp = fopen("testPrintf.c","r");
    fmt[3] = EOF;
    fmt[4] = ']';
    fmt[5] = '\0';
    fscanf(fp,fmt,arr);
    printf("%s",arr);
    printf("%d",EOF);
    return 0;
}

И после того, как все произошло, в результате появился оператор

"* * * Обнаружено разрушение стека * * *: прекращено Прервано (ядро сброшено)"

Интересно,Е ( "% s", обр);работал, но printf ("% d", EOF);не показывает вывод.

Можете ли вы дать мне знать, что произошло, когда я попытался прочитать до EOF с помощью scanf?

1 Ответ

0 голосов
/ 22 сентября 2019

Если вы действительно, действительно должны (ab) использовать fscanf() при чтении файла, то здесь описывается, как вы могли бы это сделать:

  • открыть файл
  • используйте fseek() и ftell(), чтобы найти размер файла
  • rewind() (или fseek(fp, 0, SEEK_SET)) для сброса файла в начало
  • выделить большой буфер
  • создать строку формата, которая считывает правильное количество байтов в буфер и записывает, сколько символов прочитано
  • использовать формат с fscanf()
  • добавить нулевой завершающий байт в зарезервированное для него пространство
  • распечатать содержимое файла в виде большой строки.

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

Я выбрал анодное имя data для файла, который нужно прочитать - есть бесконечные способы, которыми вы можетесделайте это выбираемым во время выполнения.

Есть несколько предположений относительно размера файла (прежде всего, что размер не больше, чем может быть помещен в long со знаком переполнения, и что он непусто).Он использует тот факт, что формат %c может принимать длину, как и большинство форматов, и не добавляет нулевого терминатора в конце строки, которую он читает, и не суетится относительно того, являются ли символыread - нулевые байты или что-то еще - он просто читает их.Он также использует тот факт, что вы можете указать размер переменной для хранения смещения с помощью спецификации преобразования %n (или, в данном случае, %ln).И наконец, предполагается, что файл не сжимается (он будет игнорировать рост, если он растет) и что это файл с возможностью поиска, а не FIFO или какой-либо другой специальный тип файла, который не поддерживает поиск.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    const char filename[] = "data";
    FILE *fp = fopen(filename, "r");
    if (fp == NULL)
    {
        fprintf(stderr, "Failed to open file %s for reading\n", filename);
        exit(EXIT_FAILURE);
    }
    fseek(fp, 0, SEEK_END);
    long length = ftell(fp);
    rewind(fp);
    char *buffer = malloc(length + 1);
    if (buffer == NULL)
    {
        fprintf(stderr, "Failed to allocate %ld bytes\n", length + 1);
        exit(EXIT_FAILURE);
    }
    char format[32];
    snprintf(format, sizeof(format), "%%%ldc%%ln", length);
    long nbytes = 0;
    if (fscanf(fp, format, buffer, &nbytes) != 1 || nbytes != length)
    {
        fprintf(stderr, "Failed to read %ld bytes (got %ld)\n", length, nbytes);
        exit(EXIT_FAILURE);
    }
    buffer[length] = '\0';
    printf("<<<SOF>>\n%s\n<<EOF>>\n", buffer);
    free(buffer);
    return(0);
}

Это все еще злоупотребление fscanf() - было бы лучше использовать fread():

    if (fread(buffer, sizeof(char), length, fp) != (size_t)length)
    {
        fprintf(stderr, "Failed to read %ld bytes\n", length);
        exit(EXIT_FAILURE);
    }

Затем можно опустить переменную format и код, который ее устанавливает, итакже nbytes.Или вы можете оставить nbytes (возможно, как size_t вместо long) и присвоить ему результат fread(), а также использовать значение в отчете об ошибках, аналогично тесту в fscanf() Вариант.

Вы можете получить предупреждение от GCC о не буквальной строке формата для fscanf().Это правильно, но это не опасно, потому что программист полностью отвечает за содержимое строки формата.

...