Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
Полярный
476 / 448 / 158
Регистрация: 11.09.2011
Сообщений: 1,156
1

Не понимаю манипуляторы. Как они работают?

08.02.2012, 11:51. Показов 2048. Ответов 16

Author24 — интернет-сервис помощи студентам
Здравствуйте. Столкнулся с непониманием манипуляторов. Вот код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
ostream& tab (ostream& output)          //Manipulator
{
    return output << "\t";
}
 
int main(int argc, char *argv[])
{
    cout << tab;
    cout << "Hello";       //How (?!?!) does it converts to: tab(cout), if it really does?
    //...................
    cout << endl;
    //...................
    tab(cout);             //I understand
    cout << "Hello ";
    system("PAUSE > NULL");
    return EXIT_SUCCESS;
}
Не понятно как cout << tab преобразуется в tab(cout).
Да и вообще не понятно, скажем как работает cout.precision(int)
Прошу объяснить, спасибо.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.02.2012, 11:51
Ответы с готовыми решениями:

Для чего нужны сужающие преобразования как они работают и на сколько они важны?
Я читаю одну книгу и застрял на одной теме &quot;Преобразования&quot;, и там есть такой вот код double х...

Find, replace Как они работают?
#include &lt;iostream&gt; #include &lt;string&gt; using namespace std; int main(){ string s1;...

Подскажите что такое классы и как они работают
Значит, написал я программу, отправил учителю, а в ответ получил: 1. Программа по-прежнему не...

Виртуальные функции, таблицы виртуальных методов, как они работают?
подскажите пожалуйста,где лучше посмотреть про начинку виртуальных функций,т.е. про таблицы...

16
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
08.02.2012, 11:57 2
C++
1
 cout.operator <<( tab );
Так понятнее?
1
Полярный
476 / 448 / 158
Регистрация: 11.09.2011
Сообщений: 1,156
08.02.2012, 12:09  [ТС] 3
Цитата Сообщение от villu Посмотреть сообщение
Так понятнее?
Не совсем. Пример конечно работает, но не понимаю почему. Ведь оно по моей идее должно преобразываться в
C++
1
operator<<(cout,tab);
Что получается, оператор << не перегружается здесь что ли?
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
08.02.2012, 12:23 4
dimcoder, для потоков вывода определён оператор <<, который принимает указатель на функцию. В теле он просто-напросто вызывает эту функцию и возвращает результат её выполнения.

Добавлено через 41 секунду
Цитата Сообщение от dimcoder Посмотреть сообщение
Ведь оно по моей идее должно преобразываться в
Нет, оно рассматривается компилятором так, как указал villu.
1
Полярный
476 / 448 / 158
Регистрация: 11.09.2011
Сообщений: 1,156
08.02.2012, 12:32  [ТС] 5
Цитата Сообщение от silent_1991 Посмотреть сообщение
определён оператор <<
}{м, то есть прототип функции вызова функций для cout записан так:
C++
1
2
3
4
5
6
7
class basic_ostream
{
   public:
   //blablabla
   void operator<< ((ostream&) * (ostream&));
   void operator<< ((const ostream &) *(ostream&))
}
Или как он/они все точно выглядит? Где их точно можно посмотреть?
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
08.02.2012, 12:36 6
который принимает указатель на функцию.
Именно. Причем функцию, которая принимает
ostream& и возвращает ostream&

Для интереса попробуй сделать в том же коде

C++
1
wcout << tab; //
а после измени функцию так
C++
1
2
3
ostream& tab ( ostream& output, int t = 10 ) { ... }
....
cout << tab;
В этих случаях будет вызван другой вариант вызова operator << (). Скорее всего, с (void *) (может зависеть от реализации STL)

Добавлено через 2 минуты
Цитата Сообщение от dimcoder Посмотреть сообщение
Где их точно можно посмотреть?
в файле ostream пользуемой библиотеки. в студии, например тут c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\ostream
1
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
08.02.2012, 12:42 7
dimcoder, реализация gcc:
C++
1
2
3
4
5
6
7
8
      __ostream_type&
      operator<<(__ostream_type& (*__pf)(__ostream_type&))
      {
    // _GLIBCXX_RESOLVE_LIB_DEFECTS
    // DR 60. What is a formatted input function?
    // The inserters for manipulators are *not* formatted output functions.
    return __pf(*this);
      }
Добавлено через 4 минуты
Цитата Сообщение от villu Посмотреть сообщение
Причем функцию, которая принимает
ostream& и возвращает ostream&
Это я как-то само собой подразумевал, иначе ответом на вопрос это не являлось бы.
1
Полярный
476 / 448 / 158
Регистрация: 11.09.2011
Сообщений: 1,156
08.02.2012, 12:52  [ТС] 8
silent_1991,
villu, спасибо за ответы, но пока остались вопросы.

Цитата Сообщение от silent_1991 Посмотреть сообщение
Причем функцию, которая принимает
ostream& и возвращает ostream&
А если я не хочу каскадной записи? Вот допустим так:
http://liveworkspace.org/code/... bb26138fdd

Откуда здесь 1?

И как работает функция setw(int) из iomanip? Как создать такой манипулятор?
C++
1
cout << setw(6) << 289;

Цитата Сообщение от villu Посмотреть сообщение
В этих случаях будет вызван другой вариант вызова operator << (). Скорее всего, с (void *) (может зависеть от реализации STL)
У меня ошибку пишет.
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
08.02.2012, 13:00 9
dimcoder, тут тоже, скорее всего, вызывается версия с void *, потому что ваш "манипулятор" не соответствует сигнатуре функции, указатель на которую принимает остримовский оператор <<, т.е. манипулятора здесь не получается.

Цитата Сообщение от dimcoder Посмотреть сообщение
setw(int)
Тут уже другая схема, тут всё завязано на классах. Вот пример манипулятора, который выводит переданное ему число табуляций:

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
#include <iostream>
 
class tab
{
public:
    tab(size_t count):
    m_count(count)
    {
    }
 
    friend std::ostream& operator<<(std::ostream& stream, const tab& tab_manip)
    {
        for (size_t i = 0; i < tab_manip.m_count; ++i)
            stream << '\t';
 
        return stream;
    }
 
private:
    size_t m_count;
};
 
int main()
{
    std::cout << tab(3) << "Hello" << std::endl;
 
    return 0;
}
http://liveworkspace.org/code/... 153abe3179

Добавлено через 2 минуты
dimcoder, вот так, если сильно не хочется каскадной записи:
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
#include <iostream>
 
class tab
{
public:
    tab(size_t count):
    m_count(count)
    {
    }
 
    friend /*std::ostream&*/ void operator<<(std::ostream& stream, const tab& tab_manip)
    {
        for (size_t i = 0; i < tab_manip.m_count; ++i)
            stream << '\t';
 
        //return stream;
    }
 
private:
    size_t m_count;
};
 
int main()
{
    //std::cout << tab(3) << "Hello" << std::endl;
 
    std::cout << tab(3);
    std::cout << "Hello" << std::endl;
 
    return 0;
}
1
Полярный
476 / 448 / 158
Регистрация: 11.09.2011
Сообщений: 1,156
08.02.2012, 13:49  [ТС] 10
Спасибо большое за хороший пример. Вроде понял.
Остался вопрос, как реализован setprecision(int)
C++
1
2
3
#include <iomanip>
//...
cout << setprecision(3) << 3.234;
http://liveworkspace.org/code/... a1cdbae12f

Я так понимаю класс содержащий setprecision является другом cout'a?

Или все таки можно описать класс чтобы можно было делать так:
C++
1
2
myClass multyplyByTen;
cout << multiplyByTen << 3;  //Ну типа умножили на десять и вывели
c выводом 30

Хотя врядли получиться, ведь приоритет слева направо и сначала вызовется cout.operator<< (multiplyByTen).
Я прав?
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
08.02.2012, 13:52 11
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
  struct _Setprecision { int _M_n; };
 
  /**
   *  @brief  Manipulator for @c precision.
   *  @param  n  The new precision.
   *
   *  Sent to a stream object, this manipulator calls @c precision(n) for
   *  that object.
  */
  inline _Setprecision 
  setprecision(int __n)
  { return { __n }; }
 
  template<typename _CharT, typename _Traits>
    inline basic_istream<_CharT, _Traits>& 
    operator>>(basic_istream<_CharT, _Traits>& __is, _Setprecision __f)
    { 
      __is.precision(__f._M_n); 
      return __is; 
    }
 
  template<typename _CharT, typename _Traits>
    inline basic_ostream<_CharT, _Traits>& 
    operator<<(basic_ostream<_CharT, _Traits>& __os, _Setprecision __f)
    { 
      __os.precision(__f._M_n); 
      return __os; 
    }
1
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
08.02.2012, 14:11 12
Ой говнокод говнокодистый какой-то... Но работает.
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
#include <iostream>
 
class MultiplyByTenManip
{
public:
    MultiplyByTenManip(std::ostream *stream = 0):
    m_stream(stream)
    {
    }
 
    template<typename T>
    std::ostream& operator <<(const T& value)
    {
        return *m_stream << value * 10;
    }
 
    friend MultiplyByTenManip operator <<(std::ostream& stream, const MultiplyByTenManip& manip);
 
private:
    std::ostream *m_stream;
};
 
MultiplyByTenManip operator <<(std::ostream& stream, const MultiplyByTenManip&)
{
    return MultiplyByTenManip(&stream);
}
 
MultiplyByTenManip multiply_by_ten;
 
int main()
{
    std::cout << multiply_by_ten << 42 << std::endl;
 
    return 0;
}
http://liveworkspace.org/code/... 85b8645862

Главное - не пытаться ничего выводить прямо в multiply_by_ten, минуя поток... А то неприятно выводить что-то по нулевому адресу, считая его адресом потока
2
576 / 559 / 47
Регистрация: 16.12.2011
Сообщений: 1,389
08.02.2012, 14:18 13
А как сделать, чтобы на 10 умножались все последующие числа, а не только первое?
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
08.02.2012, 14:31 14
I.M., а вот так вряд ли получится сделать, тут, скорее всего, действительно надо быть другом потока...
0
Полярный
476 / 448 / 158
Регистрация: 11.09.2011
Сообщений: 1,156
08.02.2012, 14:31  [ТС] 15
Цитата Сообщение от silent_1991 Посмотреть сообщение
Ой говнокод говнокодистый какой-то...
Не, ну после вырезки из iomanip от forever - ваш код для меня - луч солнца в темном лесу.

Цитата Сообщение от I.M. Посмотреть сообщение
А как сделать, чтобы на 10 умножались все последующие числа, а не только первое?
Правда потом х выведешь что нибудь другое "каскадом"

http://liveworkspace.org/code/... cf9a7c5073
0
214 / 116 / 14
Регистрация: 30.05.2011
Сообщений: 1,772
08.02.2012, 14:35 16
I.M., создавать свой класс производный от ostream и подсовывать его операторам <<, которые придется перегрузить. ну а внутри класса уже скидывать в cout.

т.е. cout<<multi(10)<<1<<2<<3;

где то я делал пример с шифрованием потока. шас поищу.

Добавлено через 2 минуты
ВОТ ссылка на манипулятор криптующий поток с ключом char*, криптуется весь последующий вывод, до тех пор пока криптование не будет отменено


C++
1
cout<<crypto_in("346767")<<" Hellow friend,how are you?"<<stop_crypt<<" Hellow friend, how are you?";
вывод
1
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
08.02.2012, 15:50 17
AzaKendler, мне тоже в голову пришёл вариант с "операторными скобками", но без наследования. Сейчас попробую накидать...

Добавлено через 6 минут
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>
 
class MultiplyByTenManipException : std::exception
{
public:
    virtual ~MultiplyByTenManipException() throw()
    {
    }
 
    virtual const char *what() const throw()
    {
        return "impossible output the value bypassing stream";
    }
};
 
class MultiplyByTenEndManip
{
};
 
class MultiplyByTenBeginManip
{
public:
    MultiplyByTenBeginManip(std::ostream *stream = 0):
    m_stream(stream)
    {
    }
    
    template<typename T>
    MultiplyByTenBeginManip operator <<(T value)
    {
        if (m_stream == 0)
            throw MultiplyByTenManipException();
 
        *m_stream << value * 10;
 
        return *this;
    }
 
    MultiplyByTenBeginManip operator <<(const char *str)
    {
        *m_stream << str;
 
        return *this;
    }
 
    std::ostream& operator <<(const MultiplyByTenEndManip&)
    {
        return *m_stream;
    }
 
    friend MultiplyByTenBeginManip operator <<(std::ostream& stream, const MultiplyByTenBeginManip& manip)
    {
        return MultiplyByTenBeginManip(&stream);
    }
 
private:
    std::ostream *m_stream;
};
 
MultiplyByTenBeginManip multiply_by_ten_begin;
MultiplyByTenEndManip multiply_by_ten_end;
 
int main()
{
    std::cout << multiply_by_ten_begin << 42 << "  " << 3.7 << multiply_by_ten_end << std::endl;
 
    return 0;
}
http://liveworkspace.org/code/... 5612280b8a

Добавлено через 7 минут
Ну и под конец кретиффчег - манипулятор, применяющий к последовательности значений (вплоть до "закрывающего" манипулятора) некоторую функцию (правда получилось не совсем так, как хотелось, ну да ладно):

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <iostream>
 
class TransformManipulatorException : std::exception
{
public:
    virtual ~TransformManipulatorException() throw()
    {
    }
 
    virtual const char *what() const throw()
    {
        return "impossible output the value bypassing stream";
    }
};
 
class TransformManipulatorEnd
{
};
 
template<typename Function>
class TransformManipulatorBegin;
 
template<typename Function>
TransformManipulatorBegin<Function> operator <<(std::ostream& stream,
    const TransformManipulatorBegin<Function>& manip);
 
template<typename Function>
class TransformManipulatorBegin
{
public:
    TransformManipulatorBegin(Function *func, std::ostream *stream = 0):
    m_func(func),
    m_stream(stream)
    {
    }
    
    template<typename T>
    TransformManipulatorBegin operator <<(T value)
    {
        if (m_stream == 0)
            throw TransformManipulatorException();
 
        *m_stream << m_func(value);
 
        return *this;
    }
    
    TransformManipulatorBegin<Function> operator <<(const char *str)
    {
        if (m_stream == 0)
            throw TransformManipulatorException();
 
        *m_stream << str;
 
        return *this;
    }
    
    std::ostream& operator <<(const TransformManipulatorEnd&)
    {
        return *m_stream;
    }
 
    friend TransformManipulatorBegin<Function> operator << <Function>(std::ostream& stream,
        const TransformManipulatorBegin<Function>& manip);
 
private:
    Function *m_func;
    std::ostream *m_stream;
};
 
template<typename Function>
TransformManipulatorBegin<Function> operator <<(std::ostream& stream,
    const TransformManipulatorBegin<Function>& manip)
{
    return TransformManipulatorBegin<Function>(manip.m_func, &stream);
}
 
int func(int val)
{
    return val * 10;
}
 
double func2(double val)
{
    return val / 2.0;
}
 
int main()
{
    std::cout << TransformManipulatorBegin<int(int)>(func)
                 << 10 << "  " << 42
                 << TransformManipulatorEnd()
              << std::endl;
    
    std::cout << TransformManipulatorBegin<double(double)>(func2)
                 << 10.8 << "  " << 42.22
                 << TransformManipulatorEnd()
              << std::endl;
 
    return 0;
}
http://liveworkspace.org/code/... a9d0809b32
2
08.02.2012, 15:50
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.02.2012, 15:50
Помогаю со студенческими работами здесь

Постигаю c++ и не могу в здешние циклы, а ещё в тип char кто знает как они работают подскажите
Есть сия код. Массив 7 столбцов на 5 строк (5 доярок(строки), 6 дней(столбцы), и 7 столбец...

Что такое "bool " и #include <algorithm>? Кто знает , как они работают ?
Вот код: #include &quot;stdafx.h&quot; #include &lt;algorithm&gt; #include &lt;iostream&gt; #include &lt;conio.h&gt; ...

Энкодеры. Как они работают?
Есть пульт управления на 433Мгц. Первая кнопка включает/выключает первую лампу, вторая...

не понимаю как реализовать одновременную работу процессов, как сделать так, что бы они одновременно проверяли доступен ресурс или нет
Здравствуйте! Подскажите, как можно одновременно запустить проверку условия. Я пытаюсь написать...


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

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