2017-01-10 4 views
-3

Может ли кто-нибудь объяснить мне самый простой способ создать динамически массив строк 2D со стабильным вторым измерением? У меня есть txt-файл с некоторыми строками в нем, и я хочу передать этот txt в массив. Поэтому я хочу связать номер строки txt с первым измерением и самой строкой со вторым измерением. Второе измерение является количество символов в каждой строке (которая является стабильной, так как каждая строка в формате TXT имеет определенный синтаксис) Так что, если у меня в ТХТ:Создать 2D динамический массив строк

hello how (newline) 
are youuu 

* (я писал youuu, потому что, как я сказал , каждая строка имеет одинаковое количество символов).

Я хочу что-то вроде:

array[0]["hello how"], 
array[1]["are youuu"] 
+0

Посмотрите на http://stackoverflow.com/questions/3536153/c -dynamically-growth-array – Jay

+2

Вам интересно, как динамически выделять 2D-массив или как его изменить? Что-то вроде: 'char (* arr) [CHARS_PER_LINE] = malloc (sizeof (* arr) * NUM_LINES);' может быть? – Dmitri

+0

В вашем примере на первой строке есть «(новая строка)», а вторая - нет. Это намеренно, надзор или что? – chux

ответ

2

Non цифровые клавиши не допускаются в C. Вы пытаетесь сделать некоторые PHP и JavaScript вздор на языке, который работает только с числами.

Но, с C всегда есть 2 дороги в ад.

char *lookup_key(int index, char *key) { ... } 


printf(lookup_key(0, "hello how")); 
2

Если вы знаете длину строк и сколько у вас есть, вы можете настроить массив как этот

char strings[numLines][strLen+1]; 

вы можете получить доступ к массиву, как это

strcpy(strings[1], "test2"); 

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

+1

Конечно, мой плохой – aggaton

+1

Возможно, 'size_t strLen = foo(); char (* строки) [strLen + 1] = malloc (sizeof * arr * numLines); '? – chux

1

динамический в C подразумевает, что вам нужно будет использовать один из [c] [m] alloc для создания памяти для ваших строк. И 2D подразумевает массив из char массивов. Предполагая, что вы знаете, число строк и самая длинная строка необходима, следующая будет создавать память, чтобы содержать их:

char ** Create2DStr(ssize_t numStrings, ssize_t maxStrLen) 
{ 
    int i; 
    char **a = {0}; 
    a = calloc(numStrings, sizeof(char *)); 
    for(i=0;i<numStrings; i++) 
    { 
     a[i] = calloc(maxStrLen + 1, 1); 
    } 
    return a; 
} 

Ниже будет освободить память, созданную выше:

void free2DStr(char ** a, ssize_t numStrings) 
{ 
    int i; 
    for(i=0;i<numStrings; i++) 
    { 
     if(a[i]) free(a[i]); 
    } 
    free(a); 
} 

Они могут быть называемый так:

... 
char **strArray = {0}; 
strArray = Create2DStr(10, 20); 
//Use strArray... 
free2DStr(10); 

Дает 10 массивов, каждый из которых может содержать 20 символов, плюс NULL. (+ 1 после maxStrLen предоставляет дополнительное пространство для NULL).

+0

Технически это не 2D-массив или массив массивов ... это 1D-массив указателей, каждый из которых указывает на отдельно выделенный 1D-массив 'char'. Также возможен реальный 2D-массив, но другой. – Dmitri

+0

@Dmitri - технически вы правы. Но в C он концептуально близок к тому, который можно получить, если он должен быть динамически создан. – ryyker

+0

Как насчет 'char (* arr) [21] = calloc (10, sizeof (* arr));'? – Dmitri

1

Если вы хотите сохранить каждую строку файла в виде строки в массиве, используйте 2D массив char:

char fileContents[NUM_LINES][LINE_LENGTH + 1]; // +1 for zero terminator 

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

#define INITIAL_EXTENT 20 // or some good starting point 

char (*fileContents)[LINE_LENGTH + 1] = malloc(sizeof *fileContents * INITIAL_EXTENT); 
if (!fileContents) 
{ 
    // malloc failed; fatal error 
    fprintf(stderr, "FATAL: could not allocate memory for array\n"); 
    exit(EXIT_FAILURE); 
} 
size_t numRows = INITIAL_EXTENT; // number of rows in array 
size_t rowsRead = 0;    // number of rows containing data 

Как читать из файла, вы будете проверять, чтобы убедиться, что у вас есть место в массиве; если вы этого не сделаете, вам необходимо расширить массив с помощью вызова realloc, что является потенциально дорогостоящей операцией. Общим методом является удвоение размера массива каждый раз, когда вы его расширяете, что сводит к минимуму общее количество звонков realloc. Риск является некоторой внутренней фрагментацией, если удвоить размер массива, потому что вам нужно всего лишь еще один ряд, но это, вероятно, что-то вы можете проанализировать вокруг:

char tmpBuf[LINE_LENGTH + 2]; // account for newline in input buffer 

while (fgets(tmpBuf, sizeof tmpBuf, inputFile)) 
{ 
    /** 
    * Check to see if you have any room left in your array; if not, 
    * you'll need to extend it. You'll probably want to factor this 
    * into its own function. 
    */ 
    if (rowsRead == numRows) 
    { 
    /** 
    * Use a temporary variable for the result of realloc in case of failure 
    */ 
    char (*tmp)[LINE_LENGTH + 1] = 
     realloc(fileContents, sizeof *fileContents * (2 * numRows)); 

    if (!tmp) 
    { 
     /** 
     * realloc failed - we couldn't extend the array any more. 
     * Break out of the loop. 
     */ 
     fprintf(stderr, "ERROR: could not extend fileContents array - breaking out of loop\n"); 
     break; 
    } 
    /** 
    * Otherwise, set fileContents to point to the new, extended buffer 
    * and update the number of rows. 
    */ 
    fileContents = tmp; 
    numRows *= 2; 
    } 

    // strip the newline from the input buffer 
    char *newline = strchr(tmpBuf, '\n'); 
    if (newline) 
    *newline = 0; 

    strcpy(fileContents[rowsRead++], tmpBuf); 
} 
Смежные вопросы