Nano Hash - криптовалюты, майнинг, программирование

Чтение текстового файла в массив символов

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

char speech[15000];

но это было неэффективно, поэтому я попытался использовать вместо этого calloc. Это заставило его перестать работать. Массив существует нужного размера, но в него ничего не записывается. Вот соответствующий код. Что я делаю неправильно?

int main() {

FILE* inFile;
int i;
int count = 0;

printf("\nOpening file April_30_1789.txt\n");

inFile = fopen("./speeches/April_30_1789.txt", "r");

if(inFile == NULL) {
    printf("Could not find April_30_1789.txt\n");
    return -1;
}

char ch;

while((ch = fgetc(inFile) != EOF)) count++;

rewind(inFile);

int size = count;

printf("Size of the array is %d\n", size);

char *speech = (char *)malloc(size*sizeof(char) + 1*sizeof(char));

fscanf(inFile, "%s", speech);

printf("Closing the file.\n");
fclose(inFile);

printf("%s", speech);

printf("\n\nDone\n");

return 0;

}

В настоящее время это дает мне

Opening file April_30_1789.txt
Size of the array is 8617
Closing the file.
Fellow-Citizens

Done
27.03.2014

  • внутренний указатель файла все еще указывает на конец файла. 27.03.2014
  • с помощью fseek переместите указатель файла на 0-е смещение и инициализируйте счетчик до 0 в начале 27.03.2014
  • Как вы думаете, почему статическое распределение неэффективно по сравнению с динамическим распределением? Вы проводили какие-либо тесты, чтобы доказать это? Или вы боитесь тратить память, если вам нужно прочитать менее 15000 байт? Это странный вопрос, потому что статическое распределение требует меньше накладных расходов, чем динамическое. Во всяком случае, вы хотите, чтобы динамическое распределение позволяло вашему буферу увеличиваться по мере необходимости. 27.03.2014
  • изменение и речь в речь. 27.03.2014
  • @ FilipeGonçalves Что ж, мне приходится использовать эту программу с текстовыми файлами разной длины, поэтому я решил, что лучше использовать malloc / calloc, чем заданное число. 27.03.2014
  • @ user2797058 Достаточно честно. Оказывается, тогда дело не в эффективности. 27.03.2014
  • Когда он встречает пробел или '\ n', он возвращает 28.03.2014

Ответы:


1

Возможный дубликат чтения всего текстового файла в массив символов в C.


Ваша проблема: fscanf с форматом "%s" будет считываться до первого обнаруженного пробела.

Возможное решение (проверка ошибок опущена для краткости):

#include <stdio.h>  /* printf */
#include <stdlib.h> /* fopen, fseek, ... */

char *buffer = NULL;
size_t size = 0;

/* Open your_file in read-only mode */
FILE *fp = fopen("your_file_name", "r");

/* Get the buffer size */
fseek(fp, 0, SEEK_END); /* Go to end of file */
size = ftell(fp); /* How many bytes did we pass ? */

/* Set position of stream to the beginning */
rewind(fp);

/* Allocate the buffer (no need to initialize it with calloc) */
buffer = malloc((size + 1) * sizeof(*buffer)); /* size + 1 byte for the \0 */

/* Read the file into the buffer */
fread(buffer, size, 1, fp); /* Read 1 chunk of size bytes from fp into buffer */

/* NULL-terminate the buffer */
buffer[size] = '\0';

/* Print it ! */
printf("%s\n", buffer);
27.03.2014
  • Что ж, это действительно хорошо сработало. Он выглядит чище, чем то, что у меня было раньше (никогда раньше не использовал fseek / fread), и я могу просто придерживаться этого. Однако для справки в будущем: что было неправильно в моем исходном коде? 28.03.2014
  • fscanf в формате "%s" будет считываться до первого обнаруженного пробела. Например, если я использую ваш код для печати моего файла main.c, на самом деле печатается только #include. 28.03.2014
  • Ах, это все объясняет. Так что, если бы я хотел использовать свой исходный код, мне просто нужно было бы, чтобы он продолжал читать до EOF, не так ли? 28.03.2014
  • Вы можете использовать цикл, но поскольку пробелы отбрасываются, вы в конечном итоге потеряете форматирование вашего документа. Использование fread сохранит форматирование. Да, кстати, эту строку while((ch = fgetc(inFile) != EOF)) count++; нужно переписать как while((ch = fgetc(inFile)) != EOF) count++;. 28.03.2014

  • 2

    Указатель вашего файла inFile указывает на конец

    Я бы сделал что-то вроде следующего:

    long lSize;
    
    fseek( inFile , 0L , SEEK_END); //use the function instead
    lSize = ftell( inFile );       // to know the file size
    rewind( inFile );             // Now point to beginning 
    
    char* speech = calloc( 1, lSize+1 );
    if( speech )
    {
        if( fread( speech , lSize, 1 , inFile) != 1)
        {
          fclose(inFile) ;
          free(speech); 
          exit(1);
        }
    }
    
    // Process the speech Here
    
    
    fclose(inFile); 
    free(speech); // Don't forget to free the allocated memory !
    
    27.03.2014

    3

    поскольку pmg сказал, что while((ch = fgetc(inFile) != EOF)) count++; заставляет ваш указатель файла указывать в конце, используйте rewind(FILE* fileptr);, чтобы вернуться к началу файла.

    27.03.2014
  • Кажется, это сработало, но это сработало только для первого слова текста, которым было «Сограждане». Будет ли это проблемой при чтении текста в массив или это ошибка при печати массива? 27.03.2014
  • @ user2797058 Измените fscanf(inFile, "%s", &speech); на fscanf(inFile, "%s", speech); 27.03.2014
  • @ FilipeGonçalves Упс, забыл упомянуть, что уже сделал. Я обновлю ОП. Он по-прежнему печатает только сограждан. 27.03.2014
  • @ nikolaMM94 Похоже, что массив правильного размера. Microsoft Word выдал примерно такое же количество символов, которое сообщает счетчик переменных. Если я правильно сделал malloc, он должен быть подходящего размера 27.03.2014
  • @ nikolaMM94 Это сработает? char Speech = (char *) malloc (size sizeof (char) + 1 * sizeof (char)); Это то, что у меня есть прямо сейчас, и это пока дает только Согражданам. 27.03.2014
  • Да, нет необходимости 1 * sizeof, sizeof, и если это не сработает, попробуйте прочитать в буфер. 27.03.2014
  • Новые материалы

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

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..