Заполнить массив неизвестным количеством чисел
Как заполнить массив неизвестным заранее количеством чисел? Пользователь просто вводит с клавиатуры 2 или 100000 чисел и они все должны быть внесены в массив.
Отслеживать
218k 15 15 золотых знаков 117 117 серебряных знаков 229 229 бронзовых знаков
задан 12 апр 2016 в 12:55
Oleksandr Zakrevskyi Oleksandr Zakrevskyi
356 2 2 серебряных знака 12 12 бронзовых знаков
Используйте std::vector , и будет вам счастье. На C придётся вручную, через realloc .
12 апр 2016 в 12:56
Используй динамический массив
12 апр 2016 в 12:57
@MajorMeow, и как не указывать размер?
12 апр 2016 в 12:57
@VladD, можно поподробней про вектор?
12 апр 2016 в 12:58
@OleksandrZakrevskiy: Ну, объявляете пустой vector
12 апр 2016 в 13:57
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
На самом деле лучше использовать vector. Вот пример:
#include #include #include // заголовочный файл итераторов using namespace std; int main() < vectorarray1; // создаем пустой вектор // добавляем в конец вектора array1 элементы 4, 3, 1 array1.insert(array1.end(), 4); array1.insert(array1.end(), 3); array1.insert(array1.end(), 1); // вывод на экран элементов вектора copy( array1.begin(), // итератор начала массива array1.end(), // итератор конца массива ostream_iterator(cout," ") //итератор потока вывода ); return 0; >
Отслеживать
ответ дан 12 апр 2016 в 13:02
491 1 1 золотой знак 4 4 серебряных знака 13 13 бронзовых знаков
Вы заранее указали 10 элементов.
12 апр 2016 в 13:06
Исправил. Лучше?)
12 апр 2016 в 13:11
а чем insert лучше чем push_back ? последнее вроде бы читабельнее.
12 апр 2016 в 13:15
@pavel Согласен, читабельнее. Надо было написать несколько вариантов добавления элемента.
12 апр 2016 в 13:19
А за что минус-то?
12 апр 2016 в 13:53
- c++
- c
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.10.27.43697
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Массив с неизвестным заранее количеством элементов
Задача: Создать программу, которая позволит ввести неограниченное количество значений и сохранит их в массиве.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
#include using std::cin; using std::cout; using std::endl; int main() { long *values(nullptr); values = new long []; long inputValue(0); int index(0); while (true) { cout "Enter value, 0 - exit: "; cin >> inputValue; if (inputValue==0) break; values[index] = inputValue; index++; } delete[] values; return 0; }
Подскажите, пожалуйста, если у меня какие то ошибки?
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

Вводится массив строк текста с неизвестным заранее количеством строк
1)Вводится массив строк текста с неизвестным заранее количеством строк.Ввод текста заканчивается.
Массив с неизвестным количеством элементов
Как задать char массив, количество элементов которого мне неизвестно? Туда может быть записано 10.
Одномерный массив с неизвестным количеством элементов, написание ограничения
Здравствуйте. Написала программу, но не понятно как поставить ограничение на x<=bi и вообще.
Организовать динамический массив с заранее неизвестным количеством элементов
Вот задался вопросом: Как организовать динамический массив с заранее неизвестным кол-вом эл-тов? .
42 / 42 / 27
Регистрация: 29.01.2013
Сообщений: 277
Добавлено через 19 секунд
Сообщение от reisal78 
values = new long [];
Что здесь происходит?
Регистрация: 04.07.2013
Сообщений: 52
Создание динамического массива, по моему так должно быть
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
#include #include using std::cin; using std::cout; using std::endl; int main() { setlocale (LC_ALL,"RUSSIAN"); int num; // размер массива int element; printf ( "\n%s", " Введите размер массива " ); scanf_s ( "%d", & num ); // получение от пользователя размера массива int *Massiv = new int[num]; // Выделение памяти для массива // Заполнение массива и вывод значений его элементов printf ( "\n%s", " Введите элементы массива \n\n" ); for ( int i = 1; i num; i ++ ) { printf ( " %+20 Massiv [ %d ] = ", i ); scanf_s ( "%d", & element ); Massiv [i] = element; } for ( int i = 1; i num; i ++ ) { printf ( " %10d\t ", Massiv [i] ); if ( ! ( (i) % 3 ) ) printf ( " \n" ); } _getch (); return 0; return 0; }
944 / 687 / 230
Регистрация: 28.04.2013
Сообщений: 1,926
Сообщение от bgm123 
Добавлено через 19 секунд
Сообщение от reisal78
values = new long [];
Что здесь происходит?
Поидее инициализирую массив values, тк не знаю кол-во элементов, потому пустое. Но подозреваю что действительно эта строка не корректна. В поиске нашел что подобная задача может быть реализована через вектор, но это их изучения я еще не добрался. Есть ли возможность выполнить задачу без использование векторов?
Helo, вся проблема в том что пользователь не знает заранее сколько потребуется ему элементов массива.
150 / 137 / 35
Регистрация: 29.07.2012
Сообщений: 709
Массив с неизвестным заранее количеством элементов у вас не получится сделать, т.к надо либо обьявлять больше, да бы не прогадать, либо меньше, но можно не угадать. Вам нужно либо научится работать с векторами, либо с дим. памятью.
Хотя можно и так, но в любом случаи нужно будет вводить количество елем.
1 2 3 4 5 6 7 8 9 10
int num; // размер массива cout "Enter integer value: "; cin >> num; // получение от пользователя размера массива int *p_darr = new int[num]; // Выделение памяти для массива for (int i = 0; i num; i++) { // Заполнение массива и вывод значений его элементов p_darr[i] = i; cout "Value of " i " element is " p_darr[i] endl; }
403 / 359 / 36
Регистрация: 11.10.2010
Сообщений: 1,907
Сообщение от Bend3r 
но в любом случаи нужно будет вводить количество елем.
я бы так не сказал
Регистрация: 04.07.2013
Сообщений: 52
Может быть как то так.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
#include #include #include int main() { setlocale (LC_ALL,"RUSSIAN"); long* mass=0; int i, k, max=1; printf ( "\n%s", " введите величины элементов "); scanf_s ( "%d", & max ); mass= new long [max]; for (i=1;;++i) { std::cout"Введенно "i" число, для выхода нажмите кнопку \n"; std::cin>>k; if (k==0) { k=i; break; } *(mass+i)=k; } for (i=1;ik;i++) { printf ( " %10d\t ", mass [i] ); if ( ! ( (i) % 3 ) ) printf ( " \n" ); } delete[] mass; _getch (); return 0; }
150 / 137 / 35
Регистрация: 29.07.2012
Сообщений: 709
Сообщение от aram_gyumri 
я бы так не сказал
Ну хорошо, напишите сейчас программу, в которой я бы мог, в любое время добавить елемент, без изменения общего количества елементов.
![]()
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
Сообщение от Bend3r 
Ну хорошо, напишите сейчас программу, в которой я бы мог, в любое время добавить елемент, без изменения общего количества елементов.
а как же списки, стеки, очереди, деревья и т.д. да, это не массивы, но добавляйте, пока в память влезает
150 / 137 / 35
Регистрация: 29.07.2012
Сообщений: 709
Сообщение от Thinker 
а как же списки, стеки, очереди, деревья и т.д. да, это не массивы, но добавляйте, пока в память влезает
Про динамическую память я вообщем ничего не говорю, просто человек говорил мол он может сделать массив как динамическую память. Но мне кажется это не возможно, т.к в любом случаи нужно знать кол-во елементов массив.
944 / 687 / 230
Регистрация: 28.04.2013
Сообщений: 1,926
Я тут порылся в сетке, и вот что у меня получилось =)
Даже все работает
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
#include using std::cin; using std::cout; using std::endl; int main() { //создание "бесконечного" массива int size_arr(1); // ок, тк размер динамического массива надо задавать хоть я его и не знаю, ну задам ему единицу. long *values(nullptr); //задам указатель values = new long [size_arr]; // выделю память под массив long *tmpValues(nullptr); // делаю временный указатель long inputValue(0); while (true) { cout "Enter value, 0 - exit: "; cin >> inputValue; //запрашиваю у пользователя зхначение if (inputValue==0) //если пользователь ввел 0 - выхожу из цикла break; values[size_arr-1] = inputValue; // записываю введеное значение в массив { size_arr++; // увеличиваю размер массива на 1 tmpValues = new long[size_arr]; //выделяю память под временный массив с увеличенным размером на 1 for (int i = 0; i size_arr-1; i++) //Перекидываю значения из основного массива во временный tmpValues[i] = values [i]; delete[] values; //Очищаю память выделеную под основной массив values = tmpValues; //Эм. "подменяю" адреса, так похоже правильно будет сказать tmpValues = nullptr; // "сбрасываю" значения временного указателя } } return 0; }
Работа с массивами в языке Си
На этой странице относительно подробно рассказывается о статических и динамических массивах. Краткое изложение основных моментов и описание методов поиска ошибок доступны при нажатии на кнопки выше. Двумерные массивы описаны на этой странице.
Массив – это линейно упорядоченная совокупность однотипных элементов. Массив определяется типом элементов (int, double, . ) и длиной. Доступ к элементам осуществляется по индексу – порядковому номеру элемента массива. Логически первый элемент массива имеет индекс ноль. В языке Си существуют статические массивы, число элементов в которых должно быть известно в момент компиляции программы, и динамические массивы, размер которых задается в процессе выполнения программы, то есть может зависеть от входных данных. Эти два типа отличаются только методом создания массива, поэтому сначала рассмотрим статические массивы.
Статические массивы
Способы объявления статических массивов
Объявление статического массива отличается от объявления обычной переменной только указанием количества элементов массива. Например, следующее объявление означает, что именем points называется массив из 100 действительных чисел.
double points[100];
В некотором смысле можно считать, что такое объявление переменной points создает 100 переменных, которые называются points[0], points[1], . points[99]. Плюс к этому, «имена» этих переменных можно вычислять: points[1], points[0+1] или points[k-1] имеют одно значение (если k=2).
В реальных программах следует избегать явного использования числовых констант в объявлениях массива (и других частях программы). Если нам нужно объявить два массива, которые теоретически могут иметь разный размер, например,
double points[100]; int students[100];
то в дальнейшем, если возникнет необходимость увеличить один из массивов, будет сложно отличить одну константу от другой. Особенно это верно при обработке элементов массива (см. ниже). Правильным считается использование директив препроцессора для присвоения константам «говорящих» имен. Например:
#define NPOINTS 100 #define NSTUDENTS 100 . double points[NPOINTS]; int students[NSTUDENTS];
Объявление массива может быть совмещено с присвоением значений его элементам. Например,
double points[] = ;
создает массив из четырех действительных чисел с указанными значениями. Заметим, что в данном случае число элементов массива в квадратных скобках не указывается. Компилятор самостоятельно вычисляет длину по списку начальных значений. В программе можно вычислить длину такого массива, разделив его размер на размер одного элемента (пример ниже).
Работа с элементами массива
Для доступа к элементу массива достаточно знать его имя и порядковый номер элемента. В языке Си элементы массива индексируются начиная с нуля, то есть в массиве из двух элементов корректными являются индексы 0 и 1. Если массив имеет имя array, то его k -й элемент записывается как array[k] . Это выражение может использоваться как для получения значения элемента массива, так и для его изменения, если оно стоит в левой части оператора присваивания. Рассмотрим для примера следующую программу.
#define NPOINTS 100 int main() < double points[NPOINTS]; int k; points[0] = 0.1; for(k=1; k < NPOINTS; k++) < points[k] = 0.1 + points[k-1]; >return 0; >
Эта программа заполняет массив действительных чисел значениями 0, 0.1, 0.2 и так далее. Отметим, что макропеременная NPOINTS используется как при объявлении массива, так и в качестве верхней границы цикла по всем его элементам. Если размер массива нужно будет изменить, то достаточно исправить одну строчку в программе (#define).
Пример работы с массивом, который задан с начальными значениями:
int main() < double points[] = ; int k; int npoints = sizeof(points)/sizeof(points[0]); for(k=0; k < npoints; k++) < printf("points[%d] = %lf\n", k, points[k]); >return 0; >
Типичная ошибка при работе с массивами состоит в указании неправильного индекса. Если в приведенной выше программе переменная цикла k будет пробегать значения от 0 до npoints включительно, то поведение программы, вообще говоря, может быть любым. Наиболее вероятным поведением является вывод на экран какого-то значения, но может возникнуть и критическая ошибка, которая приведет к аварийной остановке программы.
Представление массива в памяти и адресная арифметика
В памяти ЭВМ элементы массива записаны последовательно без пропусков. Имя массива является указателем на его начальный элемент (с индексом 0). Поскольку в массиве все элементы имеют одинаковый тип, то зная адрес начала массива (A), размер одного элемента (size) и индекс k можно вычислить адрес размещения k-ого элемента: A + k*size. Если требуется получить значение k-ого элемента массива, то достаточно выполнить одно умножение (k*size), одно сложение (A + k*size) и загрузить значение из памяти по только что вычисленному адресу. Таким образом, обращение к элементу массива очень эффективно и сложность этой операции не зависит от величины индекса k: получение (или изменение) значения нулевого элемента столь же эффективно, как и миллионного.
Хорошо, адрес начала массива мы знаем — это его имя, индекс нам известен, но как узнать size (размер одного элемента)? Чуть ниже мы узнаем как это сделать, но для работы с указателями на элементы массива это не требуется! В языке Си к указателям можно прибавлять целые числа. Например, если есть указатель double *a; , то значением выражения a+9 будет адрес десятого (еще раз вспомним, что массивы индексируются с нуля!) элемента массива, который начинается с адреса a . Компилятор сам понимает, что a является указателем на double и прибавляет нужное значение.
Обратной стороной последовательно хранения элементов в памяти является сложность вставки нового значения с сохранением порядка следования элементов. Например, если в массив нужно добавить новое значение по индексу 0, то чтобы «освободить» место все элементы массива придется сдвинуть на одну позицию. Ясно, что сложность этой операции зависит от длины массива. Чем больше длина, тем дольше выполняется это действие.
Передача массива в функцию
Функция может получать на вход массив. В действительности в функцию передается адрес начала массива и его длина. Прототип функции может быть оформлен либо так:
int print_array(double x[], int len);
int print_array(double *x, int len);
Эти варианты являются эквивалентными. Некоторые программисты предпочитают первый (квадратные скобки показывают, что формальный параметр функции является массивом), другие — второй (имя массива является указателем на нулевой элемент). Естественно, что функция может иметь и другие параметры, в том числе, другие массивы. Это только пример.
Рассмотрим возможную реализацию функции распечатывания массива.
#include int print_array(double x[], int len) < int k; for(k = 0; k < len; k++) < printf("x[%d] = %lf\n", k, x[k]); >return 0; >
При вызове функции в качестве аргумента нужно передавать имя массива и его длину.
int main() < double points[] = ; int npoints = sizeof(points)/sizeof(points[0]); print_array(points, npoints); return 0; >
Внимание! Если функция print_array изменит значение элемента массива x (например, в цикле будет написано x[k]=0; ), то изменятся значения и в массиве points функции main. Элементы массива при вызове функций не копируются! Функция получает на вход адрес памяти, где записаны элементы массива. Эта память «общая» для вызывающей и вызываемой функции.
Динамические массивы: malloc и free
Статические массивы имеют одно существенное ограничение: размер массива должен быть известен в момент компиляции программы. В большинстве задач размер данных становится известным только в момент выполнения программы. Например, вы написали программу для обработки списка друзей или подписчиков в социальной сети. У одного пользователя друзей мало, а у другого — очень много. Какое значение выбрать для длины массива друзей? 200? 1000? Миллион? Если константа будет очень большой, чтобы «заведомо» (посмотрите как росло число пользователей Интернет) устраивать всех пользователей, то для подавляющего числа пользователей это приведет к излишним затратам памяти. Захотите ли Вы поставить на свой телефон программу, которая при запуске займет всю его память с сообщением: «А вдруг у тебя миллион друзей. Нет? Всего 12?! Неплохо, прямо как у Oушена! А y Трампа миллион. «? [Друзей не должно и не может быть так много, но это к делу не относится.] Чтобы избежать таких ситуаций нужно уметь выделять минимально необходимое количество памяти.
- выделение памяти под массив;
- освобождение памяти, когда она больше не требуется.
Стандартная библиотека языка Си содержит несколько функций для работы с динамической памятью. Нам понадобятся две: malloc (memory allocation — выделение памяти) и free (освобождение). Для использования этих удивительных функций нужно в программе подключить заголовочный файл . Пример программы приведен ниже. Сначала посмотрим, что делают эти функции.
malloc: динамическое выделение памяти
Прототип: void *malloc(size_t size); Параметры: size — беззнаковое целое число, размер запрашиваемой памяти в байтах. Возвращает: Адрес начала выделенной памяти или NULL, если не удалось выделить память. Функция malloc возвращает указатель типа void * — это «абстрактный» указатель на память, который может быть приведен к указателю на любой тип. Функция malloc не может сразу возвращать указатель нужного типа, так как она используется для создания разных массивов, а в прототипе нужно указать конкретный тип возвращаемого значения.
Для выделения памяти под массив из n элементов типа T, где в T могут быть стандартные типы int , double и т.п., необходимо знать размер значения T в байтах. Для определения этой величины в языке Си есть специальный оператор sizeof , который в момент компиляции программы вычисляет нужное значение. Например, массив из n целых чисел будет занимать n*sizeof(int) байт памяти.
Таким образом, для создания динамического массива некоторого типа, например с массива целых чисел, нужно использовать команду вида:
int length; int *points; // . получили значение length (длина массива) points = (int *)malloc(length * sizeof(int));
Если нужен другой тип данных, допустим double , то int заменяется на нужное имя ( double ) в трех местах (кроме первой строки, так как длина массива всегда является целым числом).
free: освобождение памяти
Функция free позволяет освободить область памяти, которая ранее была выделена программе при вызове malloc .
Прототип void free(void *ptr); Параметры: ptr — указатель, который был получен в результат вызова malloc.
В качестве аргумента функции free может использоваться только тот адрес, который был получен в результате вызова malloc. Нельзя создать статический массив и «освободить» его функцией free. Адрес может быть освобожден только один раз. Если два раза подряд вызвать функцию free с одним и тем же аргументом, то это приведет к аварийному завершению программы.
Пример программы с динамическим массивом
В качестве иллюстрации описанных методов рассмотрим программу, которая динамически выделяет память под массив и считывает его.
#include #include int main() < int npoints; double *points; int k; scanf("%d", &npoints); /* npoints получает значение в момент выполнения программы */ points = (double *)malloc(npoints*sizeof(double)); /* Выдели память для хранения npoints элементов, каждый размера sizeof(double) */ if(points == NULL) < printf("Произошла ошибка. Запросили слишком много памяти??\n"); return -1; >/* Считываем данные с использованием адресной арифметики */ k = 0; while(k < npoints && scanf("%lf", points+k) == 1) < k++; >/* Работаем с points как с обычным массивом */ /* Например, вызываем функцию print_array(points, npoints) */ free(points); /* Освободили память */ return 0; >
Функции, которые возвращают массив
Иногда бывает удобно сделать функцию, которая возвращает динамически созданный массив. Примером может служить функция считывания массива из файла. Такая функция может получать на вход файловую переменную ( FILE * ) и должна вернуть в вызывающую функцию массив значений. Например, массив действительнах чисел. Попробуем ее реализовать.
Во-первых, нужно понять, какой прототип должна иметь такая функция. Она должна вернуть два значения: адрес выделенной памяти и длину массива. Как мы уже знаем, несколько значений можно вернуть используя указатели. Длина массива имеет тип int . Значит параметр функции будет иметь тип int * (адрес, по которому нужно записать значение). Массив — это адрес нулевого элемента, то есть double * . Значит параметр будет иметь тип double ** — «указатель на указатель». Мы должны передать адрес (одна звездочка), по которому нужно записать результат вызова malloc, который имеет тип double * . В результате получаем следующий прототип:
int read_array(FILE *input, double **array, int *length);
Собственно возвращаемое значение функции ( int ) может быть кодом ошибки. Если функция вернет 0, то это означает успешное выполнение. Любое ненулевое значение означает ошибку.
Теперь можно рассмотреть структуру тела функции (для наглядности в приведенном ниже коде отсутствуют проверки успешности считывания и корректности данных).
int read_array(FILE *input, double **array, int *length) < double *arr; int arr_length, k; /* Считываем массив: сначала длину, потом элементы */ fscanf("%d", &arr_length); arr = (double *)malloc(arr_length * sizeof(double)); for(k = 0; k < arr_length; k++) fscanf("%lf", arr + k); /* Копируем результат по заданным адресам */ *length = arr_length; *array = arr; return 0; >
Создать массив с неизвестным количеством ячеек
Мне надо создать массив из неизвестного количества ячеек, а потом туда набрасывать разное количество элементов в зависимости от ситуации, как это можно сделать?
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Ввод матрицы с заданным пользователем количеством столбцов и неизвестным количеством строк
Доброго времени суток. Пытаюсь написать программу, в которой нужно будет сначала задать количество.
Как создать массив с неизвестным количеством элементов
Товарищи, скажите пожалуйста можно ли как-то сделать массив (НЕ КОЛЛЕКЦИИ), с неизвестным.
Массив с неизвестным количеством элементов
Как задать char массив, количество элементов которого мне неизвестно? Туда может быть записано 10.
Массив с неизвестным количеством индексов
если повторился простите и можете обкидать тему какашками и закрыть. однако поиск меня не.
Заблокирован
Сообщение от Zla9_Kolu4ka 
Мне надо создать массив из неизвестного количества ячеек, а потом туда набрасывать разное количество элементов в зависимости от ситуации, как это можно сделать?
Автоматически никак. Надо написать программный код, который отслеживает емкость массива. Если емкость не удовлетворяет потребностям, создавать новый массив большего размера, копировать туда элементы из старого, потом старый удалять. Как упрощение, существует еще функция realloc.
Либо можно создать не массив, а список.
Регистрация: 28.08.2013
Сообщений: 414
Либо можно создать не массив, а список.
что за список?
Заблокирован
Однонаправленный, двунаправленный списки, стандартные структуры данных.
Регистрация: 28.08.2013
Сообщений: 414
Однонаправленный, двунаправленный списки, стандартные структуры данных.
раньше не сталкивался с ними, как я понял это в динамической памяти делается, у меня по синтаксису не пройдет(нужно для языка павн, там нужен тип массив)
Заблокирован
Значит, так как я написал в первом сообщении. Но массив, если что, тоже в динамической памяти будет находиться.
Регистрация: 28.08.2013
Сообщений: 414
создавать новый массив большего размера
тогда мне нужно будет создавать глобальный массив, потому что в локальный не влезит, а из функции не сделать глобальный
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
Сообщение от nimazzzy 
Автоматически никак.
Стандарт C99 вводит VLA (Variable Length Array) — массивы переменного размера, размещаемые как локальные переменные функции в стеке:
1 2 3 4 5 6
int main( int argc, char *argv[] ) { int n = atoi( argv[ 1 ] ), array[ n ], i; for( i = 0; i n; i++ ) array[ i ] = i; . }
Пробуйте и наслаждайтесь
Заблокирован
Сообщение от Olej 
Стандарт C99 вводит VLA (Variable Length Array)
Да, это верно. Но это не автоматический рост массива. Размер массива задается при его объявлении. Он не растет после этого. Как описано в теме, ты набрасываешь разное кол-во элементов. Заранее ты их кол-во не знаешь. Так вот, когда ты понял, что n тебе уже не хватает, чтобы набросить еще элементов, то что ты будешь делать с этим VLA?
Сообщение от Olej 
Пробуйте и наслаждайтесь
Нет, спасибо, я VLA стараюсь избегать в коде на С. Там где предполагаю максимальный размер, просто выделю на стеке побольше. Там, где не знаю заранее размер, лучше выделю динамически. Но это чисто субъективное предпочтение.
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
Сообщение от nimazzzy 
Но это не автоматический рост массива. Размер массива задается при его объявлении. Он не растет после этого. Как описано в теме, ты набрасываешь разное кол-во элементов. Заранее ты их кол-во не знаешь. Так вот, когда ты понял, что n тебе уже не хватает, чтобы набросить еще элементов, то что ты будешь делать с этим VLA?
Про динамическое изменение размер массива «по ходу» нигде в вопросе не звучит.
К тому моменту, когда выясняется требуемый размер N, вызывается отдельная функция (не main()) в которой и разместится требуемый массив, и проделается всё что надо с его элементами (в самой этой функции и в скоь угодно длинной цепочке последующих вызовов).
В очень многих случаях это решает потребность.
Сообщение от nimazzzy 
Нет, спасибо, я VLA стараюсь избегать в коде на С.
А я стараюсь избегать жирной свинины.
Это уже всё — вопросы личных вкусов.
Заблокирован
Сообщение от Olej 
Про динамическое изменение размер массива «по ходу» нигде в вопросе не звучит.
Это твое восприятие. Для меня как раз звучит. В противном случае, можно просто создать массив на стеке. Получится то же самое.
Сообщение от Olej 
К тому моменту, когда выясняется требуемый размер N
Использую твою фразу. Про то, что требуемый размер заранее известен фраза нигде не звучит. В теме написано в первом предложении, что нужно создать массив. И уже вторым предложением: «потом туда набрасывать разное количество элементов в зависимости от ситуации». То есть, ситуация меняется после создания массива, а не до. Мне это явно говорит о том, что «разное кол-во» используется уже после того, как массив мы создали.
Добавлено через 3 минуты
Сообщение от Olej 
и в скоь угодно длинной цепочке последующих вызовов).
Это не так. Стек не резиновый. Твое приложение просто упадет, если n, или размер данных в массиве будет большим. Так играться со стеком просто опасно и не принято.
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
Сообщение от nimazzzy 
В противном случае, можно просто создать массив на стеке.
«просто» — это как?
VLA — это и есть массив на стеке.
Сообщение от nimazzzy 
Это не так. Стек не резиновый. Твое приложение просто упадет, если n, или размер данных в массиве будет большим. Так играться со стеком просто опасно и не принято.
Не надо ля-ля . вьюношо
P.S. . и сейчас пойдёт подростковый трёп про говнокод, кодестайл etc. . и другие глупости, вычитанные из плохо понятых книжек.
Только я подобные предметы не обсуждаю . см. выше про жирную свинину.
Заблокирован
Сообщение от Olej 
«просто» — это как?
Это обычный массив на стеке.
Сообщение от Olej 
VLA — это и есть массив на стеке.
Да, с фиксированным кол-вом элементов. В нем не получится разместить разное кол-во элементов в зависимости от ситуации. Но я рад, что ты считаешь это решением. Альтернативная точка зрения — это всегда хорошо. Может, автору пригодится.
Сообщение от Olej 
Не надо ля-ля .
Если ты не в курсе как работает стек, то не мне тебя учить. Подтягивай уровень знаний. Пока подтягиваешь, не путай, пожалуйста, людей. Я писал не тебе, а автору, чтобы человек знал, что делает.
Повторю для ТС. Не верь фразе
проделается всё что надо с его элементами (в самой этой функции и в скоь угодно длинной цепочке последующих вызовов).
Твое приложение просто упадет с переполнением стека. И легко может это сделать без той самой цепочки вызовов.
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
Сообщение от nimazzzy 
не мне тебя учить.
Вот уж действительно хоть что умное сказал.
Сообщение от nimazzzy 
не путай, пожалуйста, людей. Я писал не тебе, а автору, чтобы человек знал, что делает.
Повторю для ТС.
И я пишу для автора вопроса!
— что есть куда проще способы в новых стандартах языка C;
Заблокирован
Сообщение от Olej 
— что есть куда проще способы в новых стандартах языка C;
Есть еще ограничения компилятора, некоторые vla не поддерживают. Как пример Visual C++.
Сообщение от Olej 
— и что не нужно принимать за чистую монету всё
Да, это верно. Можно самому просто проверить. Берем такой код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#include struct Student { char firstName[64]; char secondName[128]; unsigned short rate[20]; char* subj[20]; }; void func(int arraySize) { struct Student vlaArray[arraySize]; vlaArray[arraySize-1].rate[10] = 5; vlaArray[1].rate[1] = 2; printf("%d %d\n", vlaArray[arraySize-1].rate[10], vlaArray[1].rate[1]); } int main() { int size; scanf("%d", &size); func(size); return 0; }
Запускаем с разными размерами и смотрим на результат:
[admin@localhost ~]$ ./a.out 8000 5 2 [admin@localhost ~]$ ./a.out 22000 Segmentation fault (core dumped)
Факты говорят за себя.
Нарушитель
1169 / 856 / 251
Регистрация: 30.06.2015
Сообщений: 4,461
Записей в блоге: 50
Сообщение от Zla9_Kolu4ka 
Мне надо создать массив из неизвестного количества ячеек, а потом туда набрасывать разное количество элементов в зависимости от ситуации, как это можно сделать?
например вот так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include #include #include int main(void){ setlocale(LC_ALL ,"RU"); char *a=NULL; char b; int i=0; do{ b=getchar(); i++; a=(char*)realloc(a,i); if(a!=NULL) a[i-1]=b; else {free(a); printf("Невозможно выделить массив!");return(0);} }while(b!='\n'); a[i-1]='\0'; printf("%s\n",a); free(a); return(0); }
Можно сделать функцию, которая будет принимать количество «закидываемых» элементов, их тип, и указатель на область данных.
Заблокирован
Сообщение от CoderHuligan 
if(a!=NULL) a[i-1]=b; else
![]()
![]()
11125 / 6083 / 1663
Регистрация: 18.10.2014
Сообщений: 15,286
Сообщение от Olej 
что есть куда проще способы в новых стандартах языка C
Они то как бы и есть, но и в самом деле, примеров осмысленного безопасного использования VLA в практическом коде — раз два и обчелся. Эта тема поднималась не раз в обсуждении практической применимости VLA комитетом по стандартизации. В результате в стандарте С11 было принято решение «понизить» VLA до статуса необязательной (условной) фичи языка С. Стандарт формально больше не требует от реализаций языка С поддержки VLA. Реализациям разрешается не поддерживать VLA, определяя при этом макро __STDC_NO_VLA__ как 1.
По этой же причине изначальное намерение ввести поддержку некоего подобия VLA в C++ было отвергнуто и arrays of runtime bound не прошли в C++14.
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
Сообщение от TheCalligrapher 
Стандарт формально больше не требует от реализаций языка С поддержки VLA.
То, что он «не требует» — так это он не требует от разработчиков компилятора. Какие новые компиляторы C вы знаете в разработке? . кроме GCC и Clang, которые всё это давно поддерживают.
Сообщение от TheCalligrapher 
Они то как бы и есть, но и в самом деле, примеров осмысленного безопасного использования VLA в практическом коде — раз два и обчелся.
Чем отличаются (очень грубый пример):
1 2 3 4
int main { int array[ 10000 ]; . }
1 2 3 4
int main { int array[ atoi( argv[ 1 ] ) ]; . }
1 2 3 4
int main { int *array = (int*)alloca( atoi( argv[ 1 ] ) * sizeof( int ) ); . }
В GCC есть и ещё способы-расширения создавать массивы динамического размера.
![]()
![]()
11125 / 6083 / 1663
Регистрация: 18.10.2014
Сообщений: 15,286
Сообщение от Olej 
То, что он «не требует» — так это он не требует от разработчиков компилятора.
Разумеется. От кого же еще?
Сообщение от Olej 
Чем отличаются (очень грубый пример):
Тем, что (если закрыть глаза на использование нестандартной функциональности alloca ) второй и третий пример пытаются выделять непредсказуемый и потенциально неограниченный объем локальной памяти, что является исключительно плохой практикой программирования. Несмотря на то, что «лимиты хорошего тона» на выделение памяти в стеке существенно выросли с 70-80-х годов прошлого века, не следует заниматься разухабистым выделением больших (или непредсказуемых) блоков стековой памяти, если вы хотите, чтобы ваш код рассматривали всерьез.
Ваш первый пример, с локальным int array[ 10000 ] — сразу же без разговоров идет в топку именно по этой причине.
И именно по этой причине VLA рассматриваются как «почти всегда» бесполезная фича языка. Если заранее известно, что блок памяти достаточно мал, чтобы быть выделенным в стеке, то в 99 случаях из 100 можно просто выделить блок максимального фиксированного размера. «Экономия памяти» через VLA или alloca в такой ситуации практически ничего не дает. Если же блок может быть большим, то тогда и VLA и alloca неприемлемы.
Придумать случаи, когда экономия памяти через VLA/ alloca (по сравнению с блоком фиксированного размера) действительно работает — можно. Но в реальной жизни они исключительно редки. Именно по этой причине и VLA и alloca отнесены к разряду «сомнительных» практик программирования и переведены в разряд опциональных свойств языка.
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Как создать метод с неизвестным количеством параметров?
Даже не знаю как объяснить. Предположим если я хочу создать метод с неизвестным количеством.
Массив с неизвестным заранее количеством элементов
Задача: Создать программу, которая позволит ввести неограниченное количество значений и сохранит их.
Перебрать массив с неизвестным количеством элементов
Здравствуйте! Существует массив с неизвестным количеством элементов: ‘ms_1′,’ms_2′,’ms_3’. ‘ms_x’.
Организовать динамический массив с заранее неизвестным количеством элементов
Вот задался вопросом: Как организовать динамический массив с заранее неизвестным кол-вом эл-тов? .