Сканирование файла и выделение правильного места для хранения файла

#c

#c

Вопрос:

В настоящее время я использую fscanf для получения слов, разделенных пробелом. Я устанавливаю символ[] фиксированного размера для хранения каждого из извлеченных слов. Как бы мне создать символ[] с правильным количеством пробелов для хранения правильного количества символов из word? Спасибо.

Редактировать: если я выполняю strdup для символа [1000], а символ [1000] на самом деле содержит только 3 символа, будет ли strdup резервировать место в куче для 1000 или 4 (для завершающего символа)?

Комментарии:

1. Вы имеете в виду, что char[] выделяемое вами пространство недостаточно велико для слов, с которыми вы читаете fscanf() ?

2. strdup() выделяется только используемое пространство вплоть до первого NUL '' включительно в копируемой строке — таким образом, 4, а не 1000 в вашем примере.

3. Итак, я выделяю большое пространство для символа[]. Существуют строки в диапазоне от 1 до 1000. Я не хочу резервировать 1000 байт для каждой строки, если они могут состоять только из 3 символов.

Ответ №1:

Вот решение, включающее только два выделения и без realloc :

  1. Определите размер файла, просматривая до конца и используя ftell .
  2. Выделите блок памяти такого размера и прочитайте в него весь файл с помощью fread .
  3. Подсчитайте количество слов в этом блоке.
  4. Выделите массив, char * способный содержать указатели на такое количество слов.
  5. Снова выполните цикл по блоку текста, назначая каждому указателю адрес начала слова и заменяя разделитель слов в конце слова на 0 (нулевой символ).

Также, немного философский вопрос: если вы считаете, что такой подход, заключающийся в вставке на место ограничителей строк и разбиении одной гигантской строки, чтобы использовать ее как можно больше маленьких строк, уродлив, халтурен и т.д. Тогда вам, вероятно, следует забыть о программировании на C и использовать Python или какой-либо другой язык более высокого уровня. Возможность выполнять радикально более эффективные операции обработки данных, подобные этой, при минимизации потенциальных точек сбоя — это практически единственная причина, по которой кто-либо должен использовать C для такого рода вычислений. Если вы хотите выделить каждое слово отдельно, вы просто превращаете свою жизнь в сущий ад, делая это на C; другие языки с радостью скроют эту неэффективность (и множество возможных точек сбоя) за удобными строковыми операторами.

Ответ №2:

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

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

Но если вы выделили буфер, скажем, из 250 символов, трудно представить ни одного слова, не помещающегося в этот буфер.

Ответ №3:

 char *ptr;    
ptr = (char*) malloc(size_of_string   1);

char first = ptr[0];
/* etc. */