#c #arrays #size #malloc
#c #массивы #размер #malloc
Вопрос:
Хорошо, это вопрос домашнего задания по программированию на C. Но я действительно застрял.
Я прошу пользователя ввести слова, а затем вставляю входные данные в массив, но я не могу контролировать количество слов, которые вводит пользователь.
Я предполагаю, что я спрашиваю, как вы объявляете массив в C, не объявляя его длину и не спрашивая пользователя, какой должна быть длина.
Я знаю, что это как-то связано с malloc, но если бы вы могли привести мне несколько примеров того, как это сделать, я был бы очень признателен.
Комментарии:
1. как насчет этих символов a[]=»somename»; ? вместо malloc
Ответ №1:
Вы можете malloc
использовать блок памяти, достаточно большой, чтобы вместить определенное количество элементов массива.
Затем, прежде чем превысить это число, вы можете использовать realloc
, чтобы увеличить блок памяти.
Вот фрагмент кода на C, который показывает это в действии, перераспределяя целочисленный массив всякий раз, когда он слишком мал, чтобы вместить следующее целое число.
#include <stdio.h>
#include <stdlib.h>
int main (void) {
int *xyzzy = NULL; // Initially NULL so first realloc is a malloc.
int currsz = 0; // Current capacity.
int i;
// Add ten integers.
for (i = 0; i < 10; i ) {
// If this one will exceed capacity.
if (i >= currsz) {
// Increase capacity by four and re-allocate.
currsz = 4;
xyzzy = realloc (xyzzy, sizeof(int) * currsz);
// Should really check for failure here.
}
// Store number.
xyzzy[i] = 100 i;
}
// Output capacity and values.
printf ("CurrSz = %d, values =", currsz);
for (i = 0; i < 10; i ) {
printf (" %d", xyzzy[i]);
}
printf ("n");
return 0;
}
Комментарии:
1. Спасибо, но как мне это сделать?
2. Чтобы повысить скорость, начните с
currsz = 4
, а затем удваивайтеcurrsz
каждое перераспределение, это даст вам амортизированное постоянное время вместо линейного.3. Ошибка, @Dani, конечно, это будет O (log N) время, да? Не то чтобы это имело значение в контексте ответа, который просто показывал, как использовать
realloc
🙂4. @paxdiablo: ну, поскольку вы собирались разбить его на фрагменты, я показал дальнейшую оптимизацию. и его
O(1)
нетO(log n)
5. Все говорят, что лучше всего удваивать его каждый раз, но я действительно не понимаю, почему. Просто добавлять емкость для еще одного элемента каждый раз, должно быть, плохо, но есть ли золотая середина?
Ответ №2:
Вы можете перераспределять его каждый раз, например:
int size = 0;
char **array = malloc(0);
while(/* something */)
{
char *string = // get input
size ;
array = realloc(array, size * sizeof(char*));
array[size - 1] = string;
}
Или в виде кусков, если вы заботитесь о скорости.
Комментарии:
1. @Marlon Brando: просто прочитайте ввод
string
и прервите, если пользователь подаст сигнал о завершении ввода. если вы ненавидите c, почему бы не использовать c ?2. Это пустая трата времени на вызов
malloc(0)
— поведение определяется реализацией в том смысле, что оно либо выделит блок, который вы не можете использовать, либо выдаст вам NULL (см. C99 7.20.3). В любом случае вам лучше просто установить для него значение NULL, которое можно использоватьrealloc
и сохранять при вызове функции.3. @MarlonBrando: Если вы ненавидите C, значит, вы ненавидите программирование. Пересмотрите свои академические планы.
4. @paxdiablo — Непригодный для использования блок, предоставленный пользователем
malloc(0)
, все еще можно использоватьrealloc
, но я согласен, чтоmalloc(0)
это довольно глупо. Также он должен использоватьsize_t size
вместоint
.5. @Carey: это все равно, что сказать: «Если вы ненавидите beetle car, вы ненавидите автомобили» — у программирования много сторон.
Ответ №3:
Да, вам нужен malloc. Проверьте это здесь.
http://www.cprogramming.com/tutorial/dynamic_memory_allocation.html
Этот сайт в целом хорош для обучения.
Вот пример использования realloc, это в основном именно то, что вы просите сделать.
http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/
Комментарии:
1. но он не знает размер даже во время выполнения.
2. malloc по-прежнему подходит, и, как указал @pax, вы просто перераспределяете.
Ответ №4:
0) очевидно, вам понадобится несколько буферов, поэтому вам понадобится структура, подобная списку: возможно, запись с массивом символов 100 символов и указателем на следующую структуру 1) Вам нужно записывать слова char по char и сохранять их в вашем буфере 2) как только буфер заполнится, вы выделите другую записьсоедините его с предыдущим и продолжайте, пока не закончится память или процесс не завершится.
Это должно быть лучше по производительности, чем функция перераспределения. Я считаю, что malloc пытается предоставить непрерывный блок памяти. Поэтому структура, подобная списку, будет быстрее и работать лучше.
Комментарии:
1. А что, если пользователь вводит слово с более чем 100 символами? И зачем тратить 95 символов на большинство слов, которые вводит большинство пользователей? В realloc() намного больше производительности, чем вы думаете.
2. Может показаться, что Malloc предоставляет непрерывный блок памяти, но из-за виртуальной машины он не продолжается и может быть фрагментирован. Это означает, что realloc может даже не вызывать copy .
3. @gregory 100 байт — это просто пример. Использование realloc не имеет смысла. Если вы говорите о какой-то необычной реализации, пожалуйста, скажите, какую из них вы имеете в виду.
4. @dani Я говорю о обычном c malloc. Он работает только с непрерывным блоком памяти. В настоящее время большинство операционных систем умнее и обеспечивают более динамичное поведение. Однако этот парень учится в школе, и я уверен, что его учитель хочет научить / показать им основные структуры памяти, такие как связанный список и т.д. . Не причудливые функции распределения / перераспределения. .