Напишите программу, которая выводит 10 заданных чисел в две строки, одну для нечетных и одну для четных чисел. Используйте массивы.
После объявления входного массива для 10 чисел, которые вводит пользователь, я попытался объявить отдельные массивы для нечетных и четных значений, которые позже будут отсортированы циклом for.
Я застреваю, когда мне нужно присвоить эти значения н нечетным или четным массивам.
int input[10];
int odd[]{};
int even[]{};
int n;
for(n=0;n<10;n++)
{
if ((input[n])%2==0)
{
odd[n] = n;
}
else
{
even[n] = n;
}
Размер массива в стеке должен быть известен во время компиляции, иначе компилятор не знает, сколько места ему нужно выделить.
Пожалуйста, разверните "Я застрял". С какой конкретной проблемой вы сталкиваетесь?
Вам нужно иметь динамический массив для odd
и even
.
Кроме того, вы ошиблись, если модуль равен нулю, число четное, а не нечетное. И вы хотите добавить input[n]
, а не n
.
Я думаю, вам следует использовать контейнеры STL вместо необработанных массивов, это упростит задачу.
Вы можете сделать следующее:
std::array<int, 10> input {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // fill the array with anything you want
std::vector<int> odd, even;
for(unsigned int n = 0; n < input.size(); ++n)
{
(input[n]%2) ? (odd.push_back(input[n])) : (even.push_back(input[n]));
}
Вы можете заменить тернарный условный оператор condition ? action_if_true : action_if_false
на:
if (input[n]%2)
odd.push_back(input[n]);
else
even.push_back(input[n]);
Я надеюсь, что это может помочь.
Как сказал ваханчо в комментарии, и odd[]
, и even[]
являются статическими массивами. Это означает, что после создания вы не можете изменить размер ни одного из них. Более того, при объявлении массива размер не может быть «динамическим», т.е. int odd[n];
допустим только тогда, когда n
является константой времени компиляции (обратите внимание, что некоторые компиляторы предлагают его как расширение, но это не стандарт C++).
Итак, здесь мы немного застряли, и большинство рассмотрит возможность использования обычных std::vector
, которые имеют переменный размер.
К сожалению, в своем вопросе вы указали «Использовать массивы». Эрф, вернемся к исходной точке.
Давайте немного подумаем и вспомним, что массивы можно рассматривать как указатели. На следующем изображении мы определяем массив arr[5]
. Тогда arr
- это указатель на адрес 1000, первое значение вашего массива:
Спойлер: с этим свойством можно создать динамический массив. Итак, давайте определим указатель для наших двух массивов нечетных и четных чисел и объявим связанный с ними размер:
int * odd_array = NULL;
int * even_array = NULL;
int odd_array_size = 0, even_array_size = 0;
Теперь идея состоит в том, чтобы увеличить размер хорошего массива, когда мы найдем нечетное или четное число, и использовать функцию C void* realloc(void* ptr, size_t size)
, предлагаемую <cstdlib>
, чтобы увеличить размер, выделенный для вашего массива. В вашем случае вы, вероятно, захотите сделать это, когда перебираете свой массив input
. Вот пример того, что вы можете иметь в вашем случае:
for (int n = 0; n < 10; n++)
{
if ((input_array[n]) % 2 != 0) // We find an odd number
{
odd_array_size++; // Increase the size of the array
odd_array = (int*)realloc(odd_array, odd_array_size * sizeof(int)); // Reallocate more memory
odd_array[odd_array_size-1] = input_array[n]; // Add the value in your new allocated memory
}
else
{
// Same here, but in the case of an even number
even_array_size++;
even_array = (int*)realloc(even_array, even_array_size * sizeof(int));
even_array[even_array_size-1] = input_array[n];
}
}
При этом вы получаете два массива odd_array
и even_array
, заполненные соответственно нечетными и четными числами ваших input_array
, которые имеют соответствующие размеры odd_array_size
и even_array_size
.
Это в основном способ C сделать это. Вы, вероятно, можете рассмотреть умные указатели (чтобы быть в безопасности при освобождении памяти) и, если вам это разрешено, std::vectors
какие из них являются лучшим способом справиться с этой проблемой. Так что не забудьте освободить свои два массива в конце вашей программы, если вы используете это.
Я надеюсь, что это будет полезно и ясно, не стесняйтесь спрашивать меня о разъяснениях в комментариях, если это необходимо.
«ни инициализировать их с помощью переменной, как могли бы наивно подумать новички (с синтаксисом типа intod[n])», это либо неправильно, либо вводит в заблуждение, по крайней мере, неясно. Нет ничего плохого в int odd[n];
, пока n
является константой времени компиляции.
@formerlyknownas_463035818 Насколько я знаю и как указано в Эта тема, int odd[n];
недопустимо в правильном C++, если n
является переменной. Тем не менее, эта же ссылка объясняет различные методы инициализации массива с переменной. Но я не думаю, что один из них является последовательным в нашем случае
«переменные» обычно также называют «переменными», когда они на самом деле являются константами. const size_t n = 10; int odd[n];
отлично подходит, я думаю, вы имеете в виду int n = 10; int odd[n];
, что не является стандартным С++
не поймите меня неправильно, я просто придираюсь, особенно к «с синтаксисом типа intod[n]», потому что с синтаксисом определенно нет ничего плохого
@formerlyknownas_463035818 Это именно то, о чем я говорю, но я не знаю, как это лучше объяснить. Не стесняйтесь редактировать, если считаете, что это делает мой ответ слишком неясным
отредактировано, я не думаю, что это сделало весь вопрос «слишком неясным», хотя это добавило немного путаницы уже в начале ответа, поэтому я подумал, что это стоит исправить
Для этого вам не нужно динамическое размещение. Мы можем просто сделать два массива и заполнить их по мере необходимости.
static constexpr std::size_t N = 10;
const int input[N] = { /* user input here */ };
int odd[N] = {};
int even[N] = {};
std::size_t countOdd = 0;
std::size_t countEven = 0;
for (std::size_t i = 0; i < N; i++)
{
if (input[i] % 2 == 0)
even[countEven++] = input[i];
else
odd[countOdd++] = input[i];
}
В конце N
и odd
всего будет ровно even
(10) элементов, «пропавших без вести» (с некоторым неизвестным распределением), но кого это волнует? Десять автоматических запоминающих устройств int
! Это ничего. ? Пока мы отслеживаем, сколько шансов и сколько четов нас «заботит», все в порядке.
Теперь для двухстрочного вывода:
for (std::size_t i = 0; i < countOdd; i++)
std::cout << odd[i] << ' ';
std::cout << '\n';
for (std::size_t i = 0; i < countEven; i++)
std::cout << even[i] << ' ';
std::cout << '\n';
Легкий!
Я использовал std::size_t
там, где это уместно для индексов массива, а не int
, но вы можете пока игнорировать это, если хотите. Я также исправил вашу операцию по модулю, и вы сохраняли индексы четных/нечетных значений, а не сами значения.
Полный пример программы:
#include <iostream>
#include <cstddef> // for std::size_t
int main()
{
static constexpr std::size_t N = 10;
const int input[N] = { 1,5,9,14,3,99,82,42,43,70};
int odd[N] = {};
int even[N] = {};
std::size_t countOdd = 0;
std::size_t countEven = 0;
for (std::size_t i = 0; i < N; i++)
{
if (input[i] % 2 == 0)
even[countEven++] = input[i];
else
odd[countOdd++] = input[i];
}
for (std::size_t i = 0; i < countOdd; i++)
std::cout << odd[i] << ' ';
std::cout << '\n';
for (std::size_t i = 0; i < countEven; i++)
std::cout << even[i] << ' ';
std::cout << '\n';
}
// g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
// 1 5 9 3 99 43
// 14 82 42 70
Что делать, если пользователю нужно ввести тысячи значений? Я имею в виду, что это хорошо работает в нашем сценарии с известным вводом фиксированного размера, но может ли ваше решение быть адаптировано к более общему сценарию (например, к неизвестному размеру ввода). И не может ли «потерянная» память быть проблемой, если нам нужен массив большего размера?
@DrosvarG Да, может, но ОП сказал 10.
@LightnessRacesinOrbit Спасибо за решение, оно помогло мне решить проблему. Однако я хотел бы знать, можно ли решить проблему, используя аналогичные несложные методы для значений, которые больше и с помощью которых мы не тратим впустую память массива, как указал DrosvarG. Заранее спасибо.
@LightnessRacesinOrbit Кроме того, в самом проблемном примере новые массивы, нечетные и четные, распределяют значения прямо по индексу 1 вместо 0, учитывая, что значение countOdd и countEven установлено на 0 и имеет приращение 1 в если петля?
@nocomment Нет, это постинкремент, поэтому 0
идет первым
Хорошая уловка, позволяющая избежать динамического распределения или любого дополнительного хранилища, состоит в том, чтобы разделить набор. Это проявляется в таких алгоритмах, как быстрая сортировка, поэтому каждый ученый-компьютерщик должен изучить его.
Все, что вам нужно сделать, это начать с двух индексов или указателей, один движется вперед, а другой назад. Пока элемент находится в правильном разделе, переместите указатель за ним. Как только оба указателя нашли элементы в неправильном разделе, поменяйте их местами и продолжите. Как только указатели сойдутся, разделение будет завершено.
Или, если вы хотите оставить ввод без изменений, это позволяет вам сделать одно выделение, равное размеру всего ввода, без перераспределения или перемещения уже обработанных элементов в новый буфер.
Спасибо за ваш ответ. Не могли бы вы рассказать подробнее или привести примеры изложенного выше, так как я новичок и не совсем понимаю?
Боюсь, вы не можете сделать это таким образом. Ваш массив
int odd[]
не является динамическим. Вы должны использовать контейнеры STL или знать размер массивовodd
иeven
во время компиляции.