#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
они хранятся в вашей строке.