Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.67/15: Рейтинг темы: голосов - 15, средняя оценка - 4.67
126 / 83 / 44
Регистрация: 18.11.2018
Сообщений: 299
1

Функция с переменным числом параметров через указатели

16.02.2021, 15:24. Показов 2873. Ответов 26

Author24 — интернет-сервис помощи студентам
Здравствуйте! Есть задача: найти среднее гармоническое числового ряда двумя способами: через передачу количества параметров как параметра функции и через использование признака конца списка параметров. Спасибо пользователю SmallEvil за помощь в решении: Среднее гармоническое элементов числового ряда. Функции с переменным числом параметров. Решение верное, но сделано при помощи va_list, а нужно использовать указатели, я нашел подобный метод в интернете:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
unsigned summ(unsigned char num, unsigned first, ...) {
    unsigned sum = 0;
    unsigned testsum = 0;
    unsigned *p = &first;
    while (num--) {
        testsum += *p;
        if (testsum >= sum) {
            sum = testsum;
        } else {
            exit(UNSIGNED_OVERFLOW);
        }
        p++;
    }
    return sum;
}
 
void main() {
    int sum = summ(5, 1u, 2u, 3u, 4u, 5u);
    printf("summ = %u\n", sum);
    sum = summ(7, 0u, 27u, 0u, 4u, 5u, 60u, 33u);
    printf("summ = %u\n", sum);
    getch();
}
Источник: https://learnc.info/c/vararg_functions.html

Реализовав задачу подобным методом, у меня выходил неккоректный результат, после чего решил реализовать простую функцию, которая бы выводила аргументы функции, чтобы посмотреть, как работает функция:

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 <iostream>
#include <conio.h>
#include <cmath>
 
using namespace std;
 
double Args(int n, int first, ...)
{
    int* args = &first;
    for (int i = n; i > 0; i--)
    {
        cout << *args << endl;
        args++;
    }
}
 
int main()
{
    setlocale (0, "Russian");
    
    cout << Args(4, 1, 2, 3, 4);
    
    _getch();
    return 0;
}
По идее она должна выводить: 1234, но у меня же она выводит такой результат: 10200. С чем может быть связана эта проблема? Вроде как делаю по шаблону, который должен работать корректно, но выходит ахинея.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.02.2021, 15:24
Ответы с готовыми решениями:

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

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

Передать в функцию с переменным числом параметров УКАЗАТЕЛИ на другие функции
void sum(int first, ...) { void (*l)() = (&amp;first+1); //ведь там в стеке все аргументы ...

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

26
126 / 83 / 44
Регистрация: 18.11.2018
Сообщений: 299
17.02.2021, 17:46  [ТС] 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от hoggy Посмотреть сообщение
согласишься пройти процедуры?
Интересный вопрос, вероятнее всего нет. Но тут уж кому как, кто-то и на вакцинацию от COVID-19 ходит

Цитата Сообщение от hoggy Посмотреть сообщение
"вроде как - жену, а меня - как следует" (ц) Любовница.
Само собой я не уверен стопроцентно в качественной работе этой программы, просто проверил работу на простейших примерах, и результат выводится верный, следовательно вроде как работает, а всё остальное - лирика, запросил преподаватель указатели - вот ему через указатели. А так я бы их, конечно, не использовал, а пользовался va_list.

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Кстати, если бы эта тема не болталась в С++ форуме (по какой-то необъяснимой причине), а по праву находилась в форуме по С
А почему она должна находиться в разделе по C? Дисциплина называется программирование на C++, задание с курса, вот я в разделе C++ и создал.

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
double summ(const int* data)//0-терминированный массив
Здравствуйте, насколько я понял, вы используете массив в качестве параметра. Меня этот способ заинтересовал и я попытался реализовать через массив, вот, что у меня вышло:

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
26
27
28
29
30
31
32
33
34
35
double HarmonicMean2(double* arr)
{
    double summary = 0;
    int cnt = 0;
    double val = 0;
    cout << "\n\n";
    
    for (int i = 0; ; i++)
    {
        val = *arr;
        if (val == -1)
        {
            break;
        }
        else
        {
            val = *arr;
            summary += 1.0 / *arr;
            cnt++;
            cout << cnt << ". " << "Сумма: " << summary << endl;
            *(arr++);
        }
    }
    return cnt / summary;
}
 
int main()
{
    setlocale (0, "Russian");
    double array[] = {1, 1, 1, 1, 22, 33, 44, -1};
    cout << "\n\nСреднее гармоническое (второй способ): " << HarmonicMean2(array);
    
    _getch();
    return 0;
}
Только не могу понять, подходит ли такая реализация под условие?
0
1642 / 1091 / 487
Регистрация: 17.07.2012
Сообщений: 5,345
17.02.2021, 20:05 22
Неплохо б уточнить условие. Действительно ли нужна функция с переменным числом параметров(для таких задач по-моему смысла никакого, разве что потренироваться) ? Или все-таки хватит массива(в функцию передается указатель). Если функция с переменным кол-во параметров, то можно ли вместо ... и va_args использовать variadic templates ?
0
Вездепух
Эксперт CЭксперт С++
11695 / 6374 / 1724
Регистрация: 18.10.2014
Сообщений: 16,068
17.02.2021, 20:10 23
Цитата Сообщение от woolfskinny Посмотреть сообщение
вот, что у меня вышло:
Цитата Сообщение от woolfskinny Посмотреть сообщение
C++
1
double HarmonicMean2(double* arr)
C++
1
double HarmonicMean2(const double* arr)
Цитата Сообщение от woolfskinny Посмотреть сообщение
C++
1
2
3
    double summary = 0;
    int cnt = 0;
    double val = 0;
Объявления переменных зачем-то сгруппированы в начале функции. Зачем здесь переменная val?

Цитата Сообщение от woolfskinny Посмотреть сообщение
C++
1
for (int i = 0; ; i++)
Переменная i не играет в коде никакой роли. Зачем было ее заводить?

Цитата Сообщение от woolfskinny Посмотреть сообщение
C++
1
*(arr++);
Бессмысленное применение оператора *.

Цитата Сообщение от woolfskinny Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
        val = *arr;
        if (val == -1)
        {
            break;
        }
        else
        {
            val = *arr;
            ...
Зачем повторять присваивание val = *arr? В ветке else значение val не используется вообще, а идет работа напрямую с *arr? Почему? Может переменная val вообще не нужна?
1
126 / 83 / 44
Регистрация: 18.11.2018
Сообщений: 299
17.02.2021, 20:51  [ТС] 24
Цитата Сообщение от Новичок Посмотреть сообщение
разве что потренироваться)
Я думаю да, преподаватель примерно так и сказал, что указатели нужно использовать тут именно для того, чтобы научиться с ними работать и так далее.

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
1
double HarmonicMean2(const double* arr)
Почему нужно использовать именно const, это обязательно?

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Зачем здесь переменная val?
Да, действительно переменная val лишняя, можно было сделать просто вот так, насколько я понимаю:

C++
1
2
3
4
5
if (*arr == -1)
        {
            break;
        }
        else{...}
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Объявления переменных зачем-то сгруппированы в начале функции.
Не понял, а как иначе?

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Переменная i не играет в коде никакой роли. Зачем было ее заводить?
Чтобы был цикл в ходе которого считывался следующий элемент массива. Но сейчас понял, что можно было сделать подобным образом:

C++
1
2
3
4
5
6
7
    while (*arr != -1)
    {
        summary += 1.0 / *arr;
        cout << cnt << ". " << "Сумма: " << summary << endl;
        cnt++;
        arr++;
    }
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Зачем повторять присваивание val = *arr? В ветке else значение val не используется вообще, а идет работа напрямую с *arr?
Она лишняя, не знаю даже, к чему вводил её.

---
Исходя из всего этого написал так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
double HarmonicMean2(const double* arr)
{
    double summary = 0;
    int cnt = 0;
    cout << "\n\n";
    while (*arr != -1)
    {
        summary += 1.0 / *arr;
        cout << cnt << ". " << "Сумма: " << summary << endl;
        cnt++;
        arr++;
    }
    return cnt / summary;
}
0
1642 / 1091 / 487
Регистрация: 17.07.2012
Сообщений: 5,345
17.02.2021, 21:25 25
Цитата Сообщение от woolfskinny Посмотреть сообщение
cout << cnt << ". " << "Сумма: " << summary << endl;
Все лишние выводы из функции желательно убрать, у функции одна ответственность, посчитать среднее гармоническое и вернуть, все остальное она делать не должна. А summary лучше заменить на какой-то sum, потому что summary это не сумма(название переменной как бы сбивает с толку, хоть тут и кода несколько строчек, но лучше привыкать хорошо называть переменные).
0
126 / 83 / 44
Регистрация: 18.11.2018
Сообщений: 299
17.02.2021, 21:39  [ТС] 26
Цитата Сообщение от Новичок Посмотреть сообщение
Все лишние выводы из функции желательно убрать
Вообще они особо и не нужны в коде, я сделал эти выводы для того, чтобы отследить, как работает программа и показать преподавателю потом это для наглядности.
Цитата Сообщение от Новичок Посмотреть сообщение
потому что summary это не сумма
Цитата Сообщение от Новичок Посмотреть сообщение
что summary это не сумма
М-да, действительно ведь.. Я почему-то был убежден в обратном всё это время

Цитата Сообщение от Новичок Посмотреть сообщение
но лучше привыкать хорошо называть переменные
Да, хорошо, спасибо, буду стараться так делать.
0
Вездепух
Эксперт CЭксперт С++
11695 / 6374 / 1724
Регистрация: 18.10.2014
Сообщений: 16,068
17.02.2021, 22:15 27
Лучший ответ Сообщение было отмечено woolfskinny как решение

Решение

Цитата Сообщение от woolfskinny Посмотреть сообщение
Почему нужно использовать именно const, это обязательно?
Ну, допустим, завтра кто-то захочет использовать вашу функцию с массивом const double array[] = { .... } и не сможет это сделать.

Если ваша функция не модифицирует данные в массиве, то лучше ссылаться на эти данные с const.

Цитата Сообщение от woolfskinny Посмотреть сообщение
Не понял, а как иначе?
Ну как же? Переменную i ведь вы объявили не в начале функции, а локально - в цикле for. Точно так же и переменную val можно объявить локально - внутри цикла for, а не в начале функции

C++
1
double val = *arr;
Цитата Сообщение от woolfskinny Посмотреть сообщение
Чтобы был цикл в ходе которого считывался следующий элемент массива.
Для того, чтобы просто "был цикл" можно просто написать for (;;). Для этого не нужно заводить никаких фиктивных переменных.

Добавлено через 6 минут
Цитата Сообщение от woolfskinny Посмотреть сообщение
Исходя из всего этого написал так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
double HarmonicMean2(const double* arr)
{
    double summary = 0;
    int cnt = 0;
    cout << "\n\n";
    while (*arr != -1)
    {
        summary += 1.0 / *arr;
        cout << cnt << ". " << "Сумма: " << summary << endl;
        cnt++;
        arr++;
    }
 
    return cnt / summary;
}
Это не принципиальное замечание, но многие люди придерживаются такого соглашения: не менять исходные значения параметров функции внутри функции. Это зачастую существенно облегчает пошаговую отладку - всегда можно легко посмотреть, что же именно было передано функции изначально. По этой причине можно было бы посоветовать поступить так

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
double HarmonicMean2(const double* arr)
{
  double summary = 0;
  int cnt = 0;
  cout << "\n\n";
 
  const double* element = arr;
  while (*element != -1)
  {
    summary += 1.0 / *element;
    cout << cnt << ". " << "Сумма: " << summary << endl;
    cnt++;
    element++;
  }
 
  return cnt / summary;
}
А теперь можно заметить, что переменная cnt является необязательной

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
double HarmonicMean2(const double* arr)
{
  double summary = 0;
  cout << "\n\n";
 
  const double* element = arr;
  while (*element != -1)
  {
    summary += 1.0 / *element;
    cout << element - arr << ". " << "Сумма: " << summary << endl;
    element++;
  }
  return (element - arr) / summary;
}
и избегать цикла for тоже совсем не обязательно

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
double HarmonicMean2(const double* arr)
{
  double summary = 0;
  cout << "\n\n";
 
  const double* element = arr;
  for (; *element != -1; ++element)
  {
    summary += 1.0 / *element;
    cout << element - arr << ". " << "Сумма: " << summary << endl;
  }
 
  return (element - arr) / summary;
}
1
17.02.2021, 22:15
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.02.2021, 22:15
Помогаю со студенческими работами здесь

Функция с переменным числом параметров
Задача посчитать сокрытые сумму сокрытых аргументов ф-ции. #include&lt;iostream&gt; #include&lt;conio.h&gt;...

Функция с переменным числом параметров
хелп ми вообще дуб дубом Задание Функция с переменным числом параметров Конкретное задание...

Функция с переменным числом параметров в С++
Помогите пожалуйста подправить код. Задание: найти минимальный элемент в списке параметров с...

Функция с переменным числом параметров
У меня есть функция с переменным числом параметров типа std::string. При дебаггинге заметил, что...

Функция с переменным числом параметров
Разработать функцию с переменным числом параметров, каждый из которых является структурой, имеющей...

Функция с переменным числом параметров
В функцию с переменным числом параметров поступают символы, конец списка - ноль-символ '\ 0'. Найти...


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

Или воспользуйтесь поиском по форуму:
27
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru