2012-10-26 5 views
2

Можно ли «динамически» выделять указатели файлов в C? Что я имею в виду следующее:Динамически выделять массив указателей файлов

FILE **fptr; 
fptr = (FILE **)calloc(n, sizeof(FILE*)); 

где п целое значение. Мне нужен массив значений указателя, но я не знаю, сколько еще до того, как я получу пользовательский ввод, поэтому я не могу его жестко записать. Любая помощь будет замечательной!

+1

Что причина такого массива? – rkosegi

+1

, если вам нужен массив FILE *, ваш код выше будет работать. каждый FILE * может быть проиндексирован с помощью 'fptr [n]'. не забудьте закрыть все это, когда закончите, и освободите() блок. Я не собираюсь спрашивать, почему ты это делаешь. это * ваша * проблема =) – WhozCraig

+0

@rkosegi -I хочу открыть несколько файлов одновременно.Файлы последовательно пронумерованы, поэтому я подумал, что могу пропустить их, чтобы открыть их все одновременно. – Kitchi

ответ

2

Вы пытаетесь реализовать то, что иногда называют гибкий массив (или flex array), то есть массив, который динамически меняет размер в течение срока службы программы.) Такая сущность не существует среди системы родного типа C, поэтому вы должны ее реализовать самостоятельно. В следующем случае я предполагаю, что T является типом элемента в массиве, поскольку идея не имеет никакого отношения к какому-либо определенному типу контента. (В вашем случае T является FILE *.)

Более или менее, вы хотите структуру, которая выглядит следующим образом:

struct flexarray { 
    T *array; 
    int size; 
} 

и семейство функций для инициализации и манипулировать эту структуру. Во-первых, давайте рассмотрим основные аксессорах:

T fa_get(struct flexarray *fa, int i) { return fa->array[i]; } 
void fa_set(struct flexarray *fa, int i, T p) { fa->array[i] = p; } 
int fa_size(struct flexarray *fa) { return fa->size; } 

Обратите внимание, что в интересах краткости эти функции не делают никакой проверки ошибок. В реальной жизни вы должны добавить проверку границ на fa_get и fa_set. Эти функции предполагают, что flexarray уже инициализирован, но не показывают, как это сделать:

void fa_init(struct flexarray *fa) { 
    fa->array = NULL; 
    fa->size = 0; 
} 

Обратите внимание, что это начинается вне FlexArray как пустые. Обычно такой инициализатор создает массив с фиксированным минимальным размером, но начиная с нулевого значения нуля вы выполняете код роста массива (см. Ниже) и почти ничего не стоите в большинстве практических ситуаций.

И, наконец, как вы делаете flexarray больше? Это на самом деле очень просто:

void fa_grow(struct flexarray *fa) { 
    int newsize = (fa->size + 1) * 2; 
    T *newarray = malloc(newsize * sizeof(T)); 
    if (!newarray) { 
     // handle error 
     return; 
    } 
    memcpy(newaray, fa->array, fa->size * sizeof(T)); 
    free(fa->array); 
    fa->array = newarray; 
    fa->size = newsize; 
} 

Обратите внимание, что новые элементы в FlexArray не инициализированы, так что вы должны организовать, чтобы сохранить что-то для каждого нового индекса я перед получением из него.

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

Я не показал код сжиматься массив, но он очень похож на код роста,

+0

Это классно ... но мой код, похоже, работает для моего дела. Это еще один способ реализовать одно и то же? – Kitchi

+0

Действительно странно использовать 'callloc()', с бессмысленной очисткой (и без шансов на эффективное увеличение блока) вместо 'realloc()', который включал бы следующее копирование. – unwind

+0

@unwind: Мнения зависят от того, следует ли использовать realloc. Это универсальная функция allocate/grow/shrink/free, которая, возможно, немного важна для одной точки входа. Тем не менее, я бы не использовал 'calloc' сам в таком коде, я бы использовал' malloc' (или, может быть, 'realloc'). –

1

В любом случае это просто указатели, так что вы можете выделить память для них но не забудьте fclose() каждый указатель файла, а затем free() к объему памяти

+0

Может быть 'fclose()'? –

+0

@Joseph: да, конечно .. Я имел в виду, что на самом деле – Omkant

 Смежные вопросы

  • Нет связанных вопросов^_^