Как объявить массив произвольного размера

#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. Он работает только с непрерывным блоком памяти. В настоящее время большинство операционных систем умнее и обеспечивают более динамичное поведение. Однако этот парень учится в школе, и я уверен, что его учитель хочет научить / показать им основные структуры памяти, такие как связанный список и т.д. . Не причудливые функции распределения / перераспределения. .