Как динамически выделять память для char** в C

Как мне динамически выделять память для списка символов ** в этой функции?

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

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

Спасибо!

void readFileAndReplace(int argc, char** argv)
{
    FILE *myFile;
    char** list;
    char c;
    int wordLine = 0, counter = 0, i;
    int maxNumberOfChars = 0, numberOfLines = 0, numberOfChars = 0;

    myFile = fopen(argv[1], "r");

    if(!myFile)
    {
        printf("No such file or directory\n");
        exit(EXIT_FAILURE);
    }

    while((c = fgetc(myFile)) !=EOF)
    {
        numberOfChars++;
        if(c == '\n')
        {
            if(maxNumberOfChars < numberOfChars)
                maxNumberOfChars += numberOfChars + 1;

            numberOfLines++;
        }
    }

    list = malloc(sizeof(char*)*numberOfLines);

    for(i = 0; i < wordLine ; i++)
        list[i] = malloc(sizeof(char)*maxNumberOfChars);


    while((c = fgetc(myFile)) != EOF)
    {
        if(c == '\n' && counter > 0)
        {
            list[wordLine][counter] = '\0';
            wordLine++;
            counter = 0;
        }
        else if(c != '\n')
        {
            list[wordLine][counter] = c;
            counter++;
        }
    }
}

person ShadyBears    schedule 09.02.2013    source источник


Ответы (2)


Делайте так:

char** list; 

list = malloc(sizeof(char*)*number_of_row);
for(i=0;i<number_of_row; i++) 
  list[i] = malloc(sizeof(char)*number_of_col);  

Кроме того, если вы выделяете память динамически. вы должны освободить его по мере выполнения работы:

for(i=0;i<number_of_row; i++) 
  free(list[i] );
free(list);  

ИЗМЕНИТЬ

В вашем исправленном вопросе:

 int wordLine = 0, counter = 0, i;    

wordLine и counter равны 0

перед этим кодом:

list = malloc(sizeof(char*)*wordLine+1);
for(i = 0;i < wordLine ; i++)
   list[i] = malloc(sizeof(char)*counter);  

вам нужно присвоить значение переменной wordLine и counter

Также выделение памяти должно быть перед следующим циклом (снаружи):

 while((c = fgetc(myFile)) != EOF){
  :
  :
 }

ИЗМЕНИТЬ:

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

попробуйте с:

fseek(fp, 0, SEEK_SET); // same as rewind()
rewind(fp);             // same as fseek(fp, 0, SEEK_SET)

также я сомневаюсь в вашей логике расчета numberOfLines и maxNumberOfChars. проверьте это также

ИЗМЕНИТЬ

Я думаю, что ваш расчет для maxNumberOfChars = 0, numberOfLines = 0 неверен, попробуйте так:

maxNumberOfChars = 0, numberOfLines = 0, numberOfChars = 0;
while((c = fgetc(myFile)) !=EOF){
     if(c == '\n'){
         numberOfLines++; 
         if(maxNumberOfChars < numberOfChars)
             maxNumberOfChars = numberOfChars;
         numberOfChars=0
     }
     numberOfChars++;
}    

maxNumberOfChars - максимальное количество символов в строке.

Также измените код:

malloc(sizeof(char)*(maxNumberOfChars + 1));  
person Grijesh Chauhan    schedule 09.02.2013
comment
попробовал, и я получаю ошибку seg. Я отредактирую свой код, чтобы показать, как я его реализовал. Спасибо за ваш быстрый ответ - person ShadyBears; 09.02.2013
comment
Я присвоил значение wordLine и counter и все еще не работает. - person ShadyBears; 09.02.2013
comment
@CarlosCarrillo В чем проблема сейчас? распечатайте wordLine and counter перед malloc(), чтобы проверить значения. - person Grijesh Chauhan; 09.02.2013
comment
Если бы я не знал словарный запас раньше времени? Должен ли я переключиться на использование связанного списка, где каждый узел в списке представляет слово? - person viki.omega9; 26.04.2013
comment
@viki.omega9 Если вы не можете подсчитать, какой размер вам потребуется, у вас есть два подхода (1) void* realloc (void* ptr, size_t size); (2) связанный список - person Grijesh Chauhan; 27.04.2013

На вашем месте я бы сопоставил файл с частной памятью, используя mmap, а затем перебрал файл, сохраняя начало слов в массиве char**, который вы можете увеличивать по мере продвижения с помощью realloc, и заменяя разрывы строк на 0. .

Таким образом, ваши слова хранятся в памяти как непрерывный блок, вам не нужно заботиться о файловом вводе-выводе, потому что у вас есть весь текстовый файл в памяти как char*, и вам не нужно malloc массива массивы.

Для получения информации о функциях см. соответствующие справочные страницы или напишите мне комментарий :)

РЕДАКТИРОВАТЬ: Если вы еще не знакомы с mmap, взгляните на это: http://www.jimscode.ca/index.php/component/content/article/13-c/45-c-примерпростого-mmap

Большинство программистов на C сегодня все еще пытаются читать файлы в память, используя fopen и подобные, но это совершенно не нужно и вводит дополнительные уровни сложности. (буферизация, растущие массивы,...) и mmap - хорошая альтернатива, которая переносит всю неприятную работу на ОС

person Andreas Grapentin    schedule 09.02.2013