Вот часть моего кода:
У меня проблемы с выяснением, как передать массив через perfectTest int. У меня есть варианты, что если n равно -1, то это выдает, что это недостающее число, если n равно 0, то это выдает, что это идеальное число, а если n равно 1, то это выдает, что это обильное число. номер, но мне нужно включить массивы в этом. Мне нужны советы.
//prototype
int perfectTest(int n);//function
int perfectTest(int n)
{ bool perfect;
int answer;
int perfectSum = 0;
perfect = false;
for(int i=1; i<=n/2; i++)
{
if(n % i==0)
perfectSum = i;
}
if(perfectSum == n)
perfect = true;
answer = perfectSum;
}//main function
int main()
{
char option;
int n, m;
bool InService = true;
char perfectTestingOption;
int perfectNum;
bool perfect = true;
int factor;while (InService == true)
{
cout << "\t\t\nWelcome! Choose an option below\n" << endl;
cout << "A = Perfect number testing" << endl;
cout << "B = Greatest common divisors and least common multiples" << endl;
cout << "C = Factorization of natural numbers" << endl;
cout << "Q = Quit the program\n" << endl;
cout << "Enter your choice:" << endl;
cin >> option;
if (option == 'A' || 'a')
{
cout << "\t\t\nWhich option would you like?\n" << endl;
cout << "1" << endl;
cout << "2" << endl;
cout << "3" << endl;
cout << "4" << endl;
cin >> perfectTestingOption;
if (perfectTestingOption == '1')
{
cout << "Enter a positive integer to check if it is a perfect number." << endl;
cin >> perfectNum;perfectTest(0);
for( );
if (n == -1)
{
cout << "That number is a deficient number" << endl;
}
else if (n == 0)
{
cout << "That number is a perfect number" << endl;
}
else if (n == 1)
{
cout << "That number is a abundant number" << endl;
}
else
{
cout << "Number is invalid" << endl;
}
}
Массив — это не что иное, как блок данных, адресуемый смещением от некоторого базового адреса в памяти. Если у вас есть базовый адрес, количество элементов и тип данных элементов, у вас будет достаточно информации для обработки данных как массива.
Вы можете объявить массивы напрямую —
int array[SIZE];
где SIZE
некоторое целое число, обозначающее количество элементов в массиве. Заметьте, что объявление этого стенографического плохая идея для больших значений SIZE
, так как этот синтаксис выделяет массив в стеке, который имеет жесткие ограничения по размеру относительно размера основной памяти.
Вместо этого вы можете выделить указатели и затем инициализировать их, чтобы они указывали на некоторое пространство кучи —
int * array = new int[SIZE];
Это выделяет некоторую память для блока целых динамично и дает вам адрес первого «слота». Оказывается, этого достаточно, поскольку синтаксис скобок в следующем бите функционирует как оператор смещения.
Чтобы получить доступ к отдельным элементам, после объявления переменной массива:
int foo = array[idx]
где idx
это какой-то инт. Например, если idx
были бы равны 1 (либо заменяя его литералом 1, либо переменной или выражением, оцениваемым до целого числа 1), мы получили бы целое число в слоте 1 слота справа от первого элемента. Напомним, что первый элемент в массиве в C (++) имеет индекс 0, потому что программисты сумасшедшие и любят индексировать вещи по 0 (и потому, что оператор скобки обозначает смещение с адреса первого элемента).
Как мы передаем массивы в функции? Достаточно передать их адреса памяти, если мы знаем тип данных каждого элемента массива, а также длину массива. Очень важно передать и проверить длину массива! Невыполнение этого может привести к ужасным последствиям, поскольку вы выходите за границы вашего массива и начинаете перезаписывать другие значения в вашей программе. (Более сложные структуры данных и другие языки программирования могут выполнять проверку границ автоматически. Поскольку мы используем пустые массивы, проверка границ наш обязанность.)
Давайте вернемся к исходной проблеме сейчас. Предположим, у нас есть функция int f(int i)
это делает что-то классное с тем, что приходит. Мы хотим «массивизировать» эту функцию, чтобы она также брала массивы и возвращала массивы.
Мы собираемся воспользоваться тем фактом, что мы точно знаем, какова длина нашего массива, поскольку размер выходного массива в нашем случае равен размеру входного массива. Поэтому нам не нужно беспокоиться о передаче этого числа из функции с массивами, хотя для этого есть простые методы.
Мы делаем что-то вроде этого:
int * __f(int * __i, int ilen)
{
int * output = new int[ilen];
for(int offset = 0; offset < ilen; offset++)
{
output[offset] = f(__i[offset]);
}
return output;
}
Эта функция принимает целочисленный массив, содержащий ilen
целые, и выводит результат применения f
каждому. Обратите внимание, что эта функция выделяет новую память, что вам придется delete[]
потом. С некоторой простой модификацией вы можете изменить эту функцию, чтобы модифицировать массив на месте.
Давайте разберем это построчно:
int * __f(int * __i, int ilen)
Функция подписи. Это говорит мне, что я беру адрес в массив ilen
и возвращает адрес другого такого массива.
int * output = new int[ilen];
Выделение новой памяти для нашего выхода. Если вы закончили с блоком памяти foo
, вам следует delete[] foo
когда вы закончите; в противном случае память остается выделенной и занимает место, пока ваша программа не завершится. Читайте о динамическом распределении памяти, если вы хотите узнать больше.
for(int offset = 0; offset < ilen; offset++)
{
output[offset] = f(__i[offset]);
}
Для каждого элемента в нашем массиве (индексируется offset
счетчик), выполняем f
на соответствующем элементе входного массива __i
и установите правильный элемент output
массив к результату.
return output;
Наконец, мы возвращаем массив, который мы создали. Технически мы возвращаем int *
, но это просто причудливый способ сказать «адрес памяти одного или нескольких целых».
Я использовал синтаксис указателя (*
) на протяжении всей этой рецензии. Глубокое понимание указателей требует времени для развития многих людей (включая меня; я не получал указатели в течение нескольких лет!). Вкратце, хотя:
int * foo
содержит адрес памяти Этот адрес памяти, семантически, предназначен для указания на int
, В действительности же адрес — это просто адрес. (Адрес памяти — это число, которое соответствует определенной ячейке в памяти. Вы можете рассматривать ячейки памяти как непрерывные адреса; то есть, с нашей точки зрения, ячейка 100 является «смежной» с ячейкой 101. Когда мы нумеруем память, мы используйте размер ячейки 1 байт. Адрес большей конструкции, такой как 4-байтовый int
или массив int
s, это адрес первого элемента.)foo
, затем foo
само по себе относится к адрес хранится в. Если мы хотим значение, к которому foo
очки, мы говорим *foo
, *
в этом контексте является разыменовать оператор: он берет адрес памяти и возвращает то, что там живет.bar
, мы говорим &bar
, &
в этом контексте является адрес- оператор: он принимает переменную и говорит вам, где он живет.foo + 3
является совершенно действительным адресом памяти. БУДЬТЕ ОСТОРОЖНЫ! Каждая «1», которую вы добавляете и вычитаете, — это не одна ячейка памяти, а число ячеек памяти, равное размеру типа, инкапсулируемого массивом. В нашем случае, так как int
4 байт на большинстве современных платформ, foo + 3
добавляет 3 * 4 = 12 ячеек памяти к адресу foo
не 3.foo[n]
работает для любого значения n, как и следовало ожидать.Других решений пока нет …