-44 / 2 / 3
Регистрация: 22.12.2015
Сообщений: 508
1

Найти сумму четных элементов, переданных в функцию c переменным числом параметров

10.04.2019, 16:16. Показов 3308. Ответов 17
Метки нет (Все метки)

Смотрите, задание стоит просто и понятно: написать функцию, количество параметров которой не определено. И нужно найти сумму четных элементов переданных в функцию значений.

Написал такую программу:
C++
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 "pch.h"
#include <iostream>
 
using namespace std;
 
double sum(double k, ...)
{
    int i = 0;
 
    double *p = &k;
    double res = *p;
 
    for (i = 1; (*p) != 0; i++)
    {
        res += *(++p);
    }
 
    return res;
}
 
int main()
{
    setlocale(LC_ALL, "Russian");
    cout << "Результат: " << sum(3, 6, 2, 3);
}
Постарался, для начала, просто сложить все элементы. В итоге - дичь. Помогите, пожалуйста, подправить, чтобы работало
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.04.2019, 16:16
Ответы с готовыми решениями:

Функция с переменным числом параметров, как узнать кличество переданных параметров?
Добрый вечер, можно не использовать int n, а каким то другим способом узнать количество переданных...

Написать функцию с переменным числом параметров, найти сумму чисел по заданной формуле
помогите решить указанную задачу, используя функции с переменным числом параметров. 1. Написать...

В функции с переменным числом параметров найти сумму всех элементов каждого массива
Bвести три массива чисел типа double . Первый элемент массива - количество чисел в массиве , их не...

Написать функцию sum с переменным числом параметров, которая находит сумму чисел типа int
Написать функцию sum с переменным числом параметров, которая находит сумму чисел типа int. Написать...

17
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
10.04.2019, 16:23 2
Цитата Сообщение от Imperion Посмотреть сообщение
Помогите, пожалуйста, подправить, чтобы работало
C++
1
2
3
4
5
6
7
8
template <typename... Args>
auto sum(Args&&... args) {
    return (args + ...);
}
 
int main() { 
    std::cout << sum(5, 4, 3, 2);
}
0
-44 / 2 / 3
Регистрация: 22.12.2015
Сообщений: 508
10.04.2019, 16:53  [ТС] 3
Боюсь, что это не совсем то, что нужно
Я нашел такую функцию:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void MyFunc(double a, ...)
{
    double *P = &a;
    double max = *P;
 
    int i = 1;
 
    while (*P != 0)
    {
        if ((i % 2 != 0) && (*P > max))
        {
            max = *P;
        }
 
        P = P + 1;
        i++;
    }
 
    cout << "max = " << max;
}
Результат выводится нормально
Переделал здесь всего ничего и получилось следующее
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void MyFunc(double a, ...)
{
    double *P = &a;
    double max = *P;
 
    int i = 1;
 
    while (*P != 0)
    {
        max += *P;
 
        P = P + 1;
        i++;
    }
 
    cout << "max = " << max;
}
А выводится вообще каждый раз разная фигня почему-то и это при том, что значения передаваемые в функцию неизменны.
C++
1
MyFunc(10.0, 20.0, 30.0, 50.0, 0);
Изображения
   
0
Модератор
Эксперт С++
12777 / 10232 / 6149
Регистрация: 18.12.2011
Сообщений: 27,398
10.04.2019, 17:33 4
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
double MyFunc(double a, ...)
{
    double *P = &a;
    double sum = 0;
    while (*P != 0)
    {
        sum += *P;
        P++;
    }
    return sum;
}
int main()
{
    cout << "summ = " << MyFunc(10.0, 20.0, 30.0, 50.0, 0)<<endl;
    system("pause");
}
0
-44 / 2 / 3
Регистрация: 22.12.2015
Сообщений: 508
10.04.2019, 17:38  [ТС] 5
Капец... Все равно выводит хрень какую-то...
Изображения
 
0
-44 / 2 / 3
Регистрация: 22.12.2015
Сообщений: 508
10.04.2019, 17:40  [ТС] 6
Более того, я попробовал отследить значение *P и получил вот такой результат
Миниатюры
Найти сумму четных элементов, переданных в функцию c переменным числом параметров  
0
5772 / 3196 / 1323
Регистрация: 07.02.2019
Сообщений: 8,063
10.04.2019, 17:41 7
Цитата Сообщение от zss Посмотреть сообщение
while (*P != 0)
а как же epsilon
0
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
10.04.2019, 18:14 8
Imperion,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <cstdarg>
 
int even_sum(int count, ...) {
    int sum = 0;
    va_list args;
    va_start(args, count);
    for (int i = 0; i < count; ++i) {
        int num = va_arg(args, int);
        num & 1 ? 0 : sum += num;
    }
    va_end(args);
    return sum;
}
 
int main() { 
    std::cout << even_sum(4, 5, 4, 3, 2);
}
Добавлено через 4 минуты
Цитата Сообщение от zss Посмотреть сообщение
C++
1
2
3
4
5
while (*P != 0)
* * {
* * * * sum += *P;
* * * * P++;
* * }
Это UB же.
Мы же не массив перебираем.

Добавлено через 17 минут
Imperion, вообще это все баловство, надо использовать шаблоны раз мы в разделе С++.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
template<typename Head>
auto even_sum(Head&& head) {
    return head;
}
 
template <typename Head, typename... Tail>
auto even_sum(Head&& head, Tail&&... tail) {
    return (head & 1 ? 0 : head) + even_sum(tail...);
}
 
int main() { 
    std::cout << even_sum(5, 4, 3, 2);
}
2
-44 / 2 / 3
Регистрация: 22.12.2015
Сообщений: 508
10.04.2019, 18:23  [ТС] 9
Цитата Сообщение от Azazel-San Посмотреть сообщение
Imperion, вообще это все баловство, надо использовать шаблоны раз мы в разделе С++.
Я бы лично решил задачу вообще через массив. Но это не моя прихоть, поэтому приходится делать так, как того требуют

Добавлено через 4 минуты
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <cstdarg>
 
int even_sum(int count, ...) {
    int sum = 0;
    va_list args;
    va_start(args, count);
    for (int i = 0; i < count; ++i) {
        int num = va_arg(args, int);
        num & 1 ? 0 : sum += num;
    }
    va_end(args);
    return sum;
}
 
int main() { 
    std::cout << even_sum(4, 5, 4, 3, 2);
}
Это реализовано, насколько я понимаю, так, что первый параметр - число элементов. Но требуется сделать с параметром окончания списка. Т.е. например, передается ряд элементов, в конце ноль. Вот пока мы не достигнем нуля - нужно суммировать все значения
1
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
10.04.2019, 18:35 10
Цитата Сообщение от Imperion Посмотреть сообщение
Но требуется сделать с параметром окончания списка. Т.е. например, передается ряд элементов, в конце ноль. Вот пока мы не достигнем нуля - нужно суммировать все значения
Где так сказанно? Дайте задание целиком.
Мы не можем так сделать, ну то как вы делали уж точно.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void MyFunc(double a, ...)
{
    double *P = &a; // это скорее всего UB, мы здесь получим адрес, НО во 1х здесь идет вызов по значению
    // а значит и параметр функции "а" будет сохранен не в памяти на стеке, а в регистре!
    double max = *P;
 
    int i = 1;
 
    while (*P != 0)
    {
        max += *P;
 
        P = P + 1; // и сдесь что вы делаете тоже скорее всего UB
        // никакой гарантии что параметры функции будут идти последовательно нету
        // как и того что они вообще будут на стеке
        i++;
    }
 
    cout << "max = " << max;
}
1
-44 / 2 / 3
Регистрация: 22.12.2015
Сообщений: 508
10.04.2019, 18:41  [ТС] 11
Напишите функцию с переменным числом параметров.
Само задание: найти сумму четных элементов, переданных в функцию.
Решите задачу двумя способами: через передачу количества параметров как па-раметр функции и через использование признака конца списка пара-метров.

В методичке есть вот такой пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream.h>
float arifm(int k, ...);
void main () { //среднее арифметическое чисел
cout << "\n(4+6)/2=" << arifm(4,6,0);
cout << "\n(1+2+3+4)/4=" << arifm(1,2,3,4,0);
}
float arifm(int k, ...) {
int *p=&k;//настроили указатель на параметр k
float s=*p; //значение первого параметра присвоили s
int i;
for(i=1;(*p)!=0;i++) //пока нет конца списка
s+=*(++p);
return s/(i-1);
}
Но если я пытаюсь найти сумму, а для этого видоизменяю код ф-ции так:
C++
1
2
3
4
5
6
7
8
double arifm(double k, ...) {
    double *p = &k;//настроили указатель на параметр k
    double s = *p; //значение первого параметра присвоили s
    int i;
    for (i = 1; (*p) != 0; i++) //пока нет конца списка
        s += *(++p);
    return s / (i - 1);
}
снова начинает выводиться фиг пойми что
0
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
10.04.2019, 18:55 12
Цитата Сообщение от Imperion Посмотреть сообщение
через использование признака конца списка пара-метров
И что здесь имеется в ввиду под списком параметров?
Цитата Сообщение от Imperion Посмотреть сообщение
Но если я пытаюсь найти сумму, а для этого видоизменяю код ф-ции так:
С точки зрения С++ это UB, т.е. поведение вашей программы не определено.
0
-44 / 2 / 3
Регистрация: 22.12.2015
Сообщений: 508
10.04.2019, 18:56  [ТС] 13
Цитата Сообщение от Azazel-San Посмотреть сообщение
И что здесь имеется в ввиду под списком параметров?
Ну просто перечень значений. Например, у нас есть функция f, в которой количество передаваемых элементов не определено. Мы можем в нее передать 3 параметра: f(1, 2, 3), можем 5: f(1,2,3,4,5) и т.д.
0
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
10.04.2019, 23:44 14
Лучший ответ Сообщение было отмечено Imperion как решение

Решение

Цитата Сообщение от Imperion Посмотреть сообщение
через использование признака конца списка пара-метров
Проблема в том что нету никакого конца списка.
Все что вы делаете это перебираете параметры функции через указатель по стеку, в надежде что они там будут, и будут там лежать сразу и непрерывно.
Но, это немного не так работает. Это может сработать только для х86 и если соглашение о вызове функции будет cdecl, которое гарантирует что параметры функции будут лежать на стеке.
Собирать надо под х86 только и только в студии, а код содержит UB!
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
 
#ifdef _MSC_VER
#    define __noinline __declspec(noinline)
#    define __cdecl __cdecl
#else
#    define __noinline __attribute__((noinline))
#    define __cdecl __attribute__((__cdecl__))
#endif
 
__noinline double __cdecl even_sum(double value, ...) {
    double* p_arg = &value;
    double  sum = 0;
    for (; *p_arg != 0.0; ++p_arg) {
        int(*p_arg) & 1 ? 0 : sum += *p_arg;
    }
    return sum;
}
 
int main() { std::cout << even_sum(1.0, 2.0, 3.0, 4.0, 0.0); }
1
-44 / 2 / 3
Регистрация: 22.12.2015
Сообщений: 508
12.04.2019, 10:41  [ТС] 15
Azazel-San, а могли бы вы расписать комментарии к коду? Потому что, если честно, мало что понятно)
0
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
12.04.2019, 11:24 16
Лучший ответ Сообщение было отмечено Imperion как решение

Решение

Imperion,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 
// препроцессорные директивы, она же условная компиляция
// это проверка на то какой это компилятор, тк у каждого свои настройки
#ifdef _MSC_VER // смотрим а не визуал студия ли это, если да то
#  define __noinline __declspec(noinline) // определяем штуку которая запретит компилятору встраивать функцию
#  define __cdecl __cdecl // а здесь что бы она вызывала в соглашении с cdecl, что бы переменные лежали на стеке
#else // в инном случае все тоже но для других компиляторов
#  define __noinline __attribute__((noinline))
#  define __cdecl __attribute__((__cdecl__))
#endif
 
// здесь проставили атрибуты что бы не инлайнил и соглашение о вызове cdecl
__noinline double __cdecl even_sum(double value, ...) {
    double* p_arg = &value;
    double  sum = 0;
    for (; *p_arg != 0.0; ++p_arg) { // остальное по сути тоже что вы уже делали
        int(*p_arg) & 1 ? 0 : sum += *p_arg; // перебираем пока не встретили 0
    } // штука с & 1 это проверка на четность
    return sum;
}
2
-44 / 2 / 3
Регистрация: 22.12.2015
Сообщений: 508
12.04.2019, 11:58  [ТС] 17
Azazel-San, спасибо большое за помощь!
0
1550 / 875 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
13.04.2019, 02:21 18
Цитата Сообщение от Azazel-San Посмотреть сообщение
// это скорее всего UB, мы здесь получим адрес, НО во 1х здесь идет вызов по значению // а значит и параметр функции "а" будет сохранен не в памяти на стеке, а в регистре!
Механизм передачи параметров в машинных кодах совсем, вот вообще, не должен вас волновать (если мы о поведении программ с точки зрения языка C++). Мы всегда можем взять адрес чего бы то ни было, что имеет тип. И если время жизни этого чего бы то ни было не закончилось - никакого UB не будет. Что там происходит за кулисами - проблемы компилятора.

Цитата Сообщение от Azazel-San Посмотреть сообщение
Где так сказанно? Дайте задание целиком.
Мы не можем так сделать, ну то как вы делали уж точно.
С чего бы вдруг?
Второй параметр va_start() - имя параметра, после которого, собственно, и идут эти "параметры неизвестного количества". Он никак не связан с количеством этих самых параметров (а точнее аргументов). Вспомните printf() там единственный постоянный параметр - си-строка.
Т.о. желание ТС, ака "найти сумму четных элементов, переданных в функцию через использование признака конца списка параметров" будет выглядеть как-то так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int foo(int a, ...)
{
    if (a==0)
        return 0;
    if (a % 2)
        a = 0;
    va_list args;
    va_start(args, a);
    for (int arg = va_arg(args, int); arg != 0; arg = va_arg(args, int))
        if (arg % 2 == 0)
            a += arg;
    va_end(args);
    return a;
}
 
int main()
{
    std::cout << foo(1, 2, 3, 4, 0) << std::endl;
}
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.04.2019, 02:21
Помогаю со студенческими работами здесь

Напишите функцию с переменным числом параметров (среднее гармоническое элементов числового ряда)
Продемонстрировать вызов функции с различным числом параметров. Выполните вычисления для трех и...

Написать функцию sum с переменным числом параметров, которая находит сумму чисел типа int по формуле: S=a1*a2+a3*a4+a5*a
Всем доброго времени суток! Дана следующая задача: Написать функцию sum с переменным числом...

Массивы в функцию с переменным числом параметров
Как передать некоторое кол-во массивов в функцию с переменным числом параметров и вывести в функции...

Реализовать функцию с переменным числом параметров C++
Реализовать функцию с переменным числом параметров. Параметрами являются символы, определяющие,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru