@RaphaeI

Почему при передаче произволного количества аргументов в функцию появляются лишние аргументы?

Решаю из книги Бьёрна Страуструпа следующую задачу: Напишите программу, подобную той, что выдает "Hello, world". Она получает имя (name) как параметр командной строки и выдает "Hello, name". Измените программу так, чтобы она получала
произвольное число имен и всем им выдавала свое приветствие: "Hello, ...".

Написал такую функцию:
void privet(char* name ...) {
	char** ptr = &name;
	va_list ap;
	va_start(ap,name);
	int i = 0;
	for (;;) {
		char* p = va_arg(ap,char*);
		if (p == 0) break;
		cout << ptr[i] << " " << i << endl;
		i++;
	}
	va_end(ap);
}


При ее вызове с тремя аргументами privet("Nagib", "Habib", "Gena"); печатаются пять (4 и 5 выглядят так: ag/).
При вызове с пятью аргументами privet("Nagib", "Habib", "Gena", "Vova", "Sasha"); печатаются все пять, но компилятор выдает ошибку о завершении программы.

Пишу в Dev C++ 5.11
  • Вопрос задан
  • 150 просмотров
Решения вопроса 1
myjcom
@myjcom Куратор тега C++
задание от Страуструпа не про это (пример использования и
ответ на почему там же)
а про это

++

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main(int argc, char* argv[])
{
  if(argc > 0)
  {
    vector<string> args(&argv[1], &argv[argc]);
    for(const auto& n : args)
    {
      cout << "Hello " << n << "\n";
    }
  }
}


или
//...
for(int i = 1; i < argc; ++i)
{
  cout << "Hello " << argv[i] << "\n";
}
//...



Она получает имя (name) как параметр командной строки и выдает "Hello, name". Измените программу так, чтобы она получала произвольное число имен и всем им выдавала свое приветствие: "Hello, ...".


т.е.
hello.exe name1 name2 name3
из командной строки выдает
Hello name1
Hello name2
Hello name3


P.S.
Уровень сложности 1.5 по классификации Страуструпа, как бы намекает.
на Variadic functions там есть
другое упражнение

13. (*3) Напишите функцию обработки ошибок, первый параметр который подобен форматирующей
строке-параметру printf() и содержит форматы %s, %c и %d. За ним может следовать произвольное
количество числовых параметров. Функцию printf() не используйте. Если смысл формата %s и
других форматов вам неизвестен, обратитесь к $$10.6. Используйте stdarg.h.



Крайне полезно обратить внимание на
Alternatives && Notes

Как вариант

#include <iostream>

template<typename... Arg>
auto say_hello(std::ostream& os, Arg... args)
{
  ((os << args << "\n") , ...);
}

int main(int argc, char* argv[])
{
  say_hello(std::cout, "Name", "Name1", "Name2");
  std::cin.get();
}

Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@vanyamba-electronics
void privet(int n, ...)
{
  va_list ap;
  va_start(ap, n);
  for (int i = 0; i != n; i++)
  {
    const char* p = va_arg(ap, const char*);
    cout << "Hello, " << p << endl;
  }
  va_end(ap);
}

int main() {
    privet(3, "Nagib", "Habib", "Gena"); 
    return 0;
}
Ответ написан
Комментировать
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Написал такую функцию:
void privet(char* name ...) {
  char** ptr = &name;
  va_list ap;
  va_start(ap,name);
  int i = 0;
  for (;;) {
    char* p = va_arg(ap,char*);
    if (p == 0) break;
    cout << ptr[i] << " " << i << endl;
    i++;
  }
  va_end(ap);
}

Плохо написал. Если уж ты передаёшь параметры через многоточие и получаешь их через p = va_arg(ap,char*), то и используй p, который получил, а не ptr.

При ее вызове с тремя аргументами privet("Nagib", "Habib", "Gena")

А NULL в конец кто добавит за тебя, раз уж ты его в функции проверяешь?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы