Использование Malloc для i бесконечной C-строки

#c #arrays #string #function #memory-management

#c #массивы #строка #функция #управление памятью

Вопрос:

Мне было интересно, возможно ли создать один бесконечный массив, который может хранить бесконечно длинные строки?

Итак, что я имею в виду, я хочу создать функцию, которая получает i строк длиной n.Я хочу ввести в программу бесконечные строки, длина которых может составлять бесконечные символы!

 void endless(int i){
     //store user input on char array i times 
}
  

Для достижения этого мне нужен malloc, который я обычно использую следующим образом:

 string = malloc(sizeof(char));
  

Но как это будет работать, скажем, для 5 или 10 массивов или даже бесконечного потока массивов? Или это невозможно?

Редактировать: я знаю, что память не бесконечна, я имею в виду, если она бесконечна, как бы вы попытались этого достичь? Или, может быть, просто выделять память, пока не будет использована вся память?

Редактировать 2: Итак, я немного поиграл, и это получилось:

 void endless (char* array[], int numbersOfArrays){
int j;

//allocate memory
for (j = 0; j < numbersOfArrays; j  ){
    array[j] = (char *) malloc(1024*1024*1024);
}

//scan strings
for (j = 0; j < numbersOfArrays; j  ){
    scanf("%s",array[j]);
    array[j] = realloc(array[j],strlen(array[j] 1));
}

//print stringd
for (j = 0; j < numbersOfArrays; j  ){
    printf("%sn",array[j]);
}
}
  

Однако это не работает, может быть, я неправильно понял часть перераспределения?

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

1. Вы имеете в виду неограниченный, а не бесконечный? В конечном итоге у вас закончится память, бесконечность — сложная концепция. Разве вы не можете использовать malloc() для выделения указателей символов, а затем использовать эти указатели для выделения буферов?

2. Возможно, у вас есть более реалистичная проблема, которую вы пытаетесь решить, для которой, по вашему мнению , бесконечная память является решением?

3. Мне просто интересно, как кто-то попытается достичь чего-то подобного, если память не ограничена. Это теоретический вопрос, я забыл указать на это, извините

4. Вы могли бы объявить a char ** и использовать его для динамического выделения char * , а также использовать их для буферов malloc() / realloc() . Трудно представить реалистичный, бесконечный пример, есть ограничения.

5. Идея динамического выделения заключается в том, что вы выделяете память по мере необходимости и освобождаете, как только она больше не нужна. предварительная обработка большого количества данных не имеет особого смысла, независимо от того, сколько у вас памяти. Что касается scanf части, вы бы просто использовали один буфер для всего чтения, malloc новую строку на каждой итерации и копировали строку из этого единственного буфера в строку malloc’d ..

Ответ №1:

Память не бесконечна, поэтому вы не можете.

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

malloc() завершится с ошибкой и не выделит памяти, когда ваша программа запрашивает слишком много памяти:

Если функции не удалось выделить запрошенный блок памяти, возвращается нулевой указатель.


Предполагая, что память бесконечна, я бы создал 2D-массив SxN, где S — количество строк и N самая длинная длина строк, которые вы получили, но, очевидно, есть много способов сделать это! 😉

Другим способом было бы иметь простой связанный список (у меня есть один в List (C), если он вам нужен), где каждый узел будет иметь указатель char, и этот указатель в конечном итоге будет содержать строку.


Вы можете define указать максимальную длину, которую вы предполагаете, это будет максимальная длина ваших строк. В противном случае вы могли бы выделить огромный массив символов размером 1d, в который вы вставляете новую строку, используете strlen() для определения фактической длины строки, а затем динамически выделяете массив, который будет точно такого размера, который необходим, равный этой длине 1 для нулевой строки-терминатора.

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

1. Это теоретический вопрос! Давайте просто представим, что это бесконечно, как бы вы попытались этого добиться?

2. спасибо за ваш вклад, но откуда мне знать, какова самая длинная длина строки? Я думаю, это очень сложный вопрос

3. Снова обновлено @Raavgo! 🙂

4. так это сработает? array[j] = (char *) malloc(strlen(array[j])*sizeof(char));

5. @Raavgo, если array[i] содержит бесконечную строку, strlen вернет бесконечное и бесконечное число, связанное с конечным числом, по-прежнему бесконечно. Материал имеет тенденцию становиться сложным и очень неинтуитивным, когда он начинает становиться бесконечным. Я бы предложил перейти к любому cs.stackexchange.com или mathoverflow. сеть для таких теоретических вопросов. Одно предостережение: вы можете не сразу понять ответ.

Ответ №2:

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

Я думаю, важным моментом здесь является то, что существует два этапа выделения: один для строк и один для массива, в котором хранятся указатели на строки. Если вы добавляете строковый литерал в массив хранения, вам не нужно выделять для него. Но если вы добавите строку, которая неизвестна во время компиляции (например, пользовательский ввод), вам придется динамически выделять для нее память.

Редактировать:

Если кто-нибудь пытался запустить исходный код, приведенный ниже, он мог столкнуться с каким-то странным поведением для длинных строк. В частности, они могут быть усечены и завершены таинственным символом. Это было результатом того факта, что исходный код неправильно обрабатывал ввод пустой строки. Я протестировал его для очень длинной строки, и, похоже, это сработало. Я думаю, что мне просто «повезло». Кроме того, произошла крошечная (1 байт) утечка памяти. Оказалось, что я забыл освободить память, на которую указывает from newstring , которая содержала один символ ‘ 0’ при выходе. Спасибо, Valgrind!

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

 #include <stdio.h>
#include <stdlib.h>

char * get_string(void);
char ** add_string(char *str, char **arr, int num_strings);

int main(void)
{
    char *newstring;
    char **string_storage;
    int i, num = 0;

    string_storage = NULL;

    puts("Enter some strings (empty line to quit):");
    while ((newstring = get_string()) != NULL) {
        string_storage = add_string(newstring, string_storage, num);
          num;
    }

    puts("You entered:");
    for (i = 0; i < num; i  )
        puts(string_storage[i]);

    /* Free allocated memory */
    for (i = 0; i < num; i  )
        free(string_storage[i]);
    free(string_storage);

    return 0;
}

char * get_string(void)
{
    char ch;
    int num = 0;
    char *newstring;

    newstring = NULL;
    while ((ch = getchar()) != 'n') {
          num;
        newstring = realloc(newstring, (num   1) * sizeof(char));
        newstring[num - 1] = ch;
    }
    if (num > 0)
        newstring[num] = '';

    return newstring;
}

char ** add_string(char *str, char **arr, int num_strings)
{
      num_strings;
    arr = realloc(arr, num_strings * (sizeof(char *)));
    arr[num_strings - 1] = str;

    return arr;
}
  

Ответ №3:

Мне было интересно, возможно ли создать один бесконечный массив, который может хранить бесконечно длинные строки?

Память не может быть infinite . Итак, ответ ОТРИЦАТЕЛЬНЫЙ. Даже если у вас есть все большие объемы памяти, вам понадобится процессор, который мог бы обрабатывать это огромное пространство памяти. Существует ограничение на объем динамической памяти, который может быть выделен, malloc и на объем статической памяти (выделенный во время компиляции), который может быть выделен. malloc вызов функции вернет значение NULL, если нет подходящего блока памяти, запрошенного вами в heap memory .

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

В C на самом деле нет многомерных массивов, но есть несколько способов их имитации. Вы можете использовать (динамически выделяемый) массив указателей на (динамически выделяемые) массивы. Это используется в основном, когда границы массива неизвестны до времени выполнения. или

Вы также можете выделить глобальный двумерный массив достаточной длины и ширины. Статическое распределение для хранения входных строк случайного размера не является хорошей идеей. Большая часть пространства памяти будет неиспользуемой.

Кроме того, C programming language не имеет string типа данных. Вы можете имитировать строку, используя массив символов с нулевым завершением. Итак, для динамического выделения массива символов в C мы должны использовать malloc , как показано ниже:

 char *cstr = malloc((MAX_CHARACTERS   1)*sizeof(char));
  

Здесь MAX_CHARACTERS представляет максимальное количество символов, которые могут быть сохранены в вашем cstr массиве. Добавляется 1 для выделения места для null символов, если MAX_CHARACTERS они хранятся в вашей строке.