Форум программистов, компьютерный форум CyberForum.ru

Как создать свой поток и связать его с консолью - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
07.03.2014, 10:41     Как создать свой поток и связать его с консолью #1
Собственно возник такой вопрос: читаю Саттера пробую создать свой класс символов не чувствительный к регистру. Автор пишет, что для вывода на консоль требуется использовать поток со своим типом сравнения символов.
В классе basic_string определен оператор:
C++
1
2
3
4
  template<typename _CharT, typename _Traits, typename _Alloc>
    basic_ostream<_CharT, _Traits>&
    operator<<(basic_ostream<_CharT, _Traits>& __os,
           const basic_string<_CharT, _Traits, _Alloc>& __str);
Вопрос как создать объект типа basic_ostream<char, MyChar> (MyChar - мой тип сравнения символов) и связать его с консолью?
Для потока нашел только один открытый конструктор
C++
1
2
3
      explicit 
      basic_ostream(__streambuf_type* __sb)
      { this->init(__sb); }
Как его использовать?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.03.2014, 10:41     Как создать свой поток и связать его с консолью
Посмотрите здесь:

Как создать свой собственный тип на C++? C++
Как создать поток в Linux? C++
C++ В окне перемещаются объекты, отталкиваясь от стенок окна. Каждый объект имеет свой поток, перемещающий его. Встретившись, объекты начинают двигаться
Нужно создать базу данных (создать пустой бинарный файл). Через поток. Поток бинарного файла описать в виде локальной переменной внутри функции. C++
Как создать свой формат файла на Visual C++ Win32, Или С# формой C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
aLarman
636 / 557 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
07.03.2014, 11:45     Как создать свой поток и связать его с консолью #2
а зачем его создавать?
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
07.03.2014, 11:48  [ТС]     Как создать свой поток и связать его с консолью #3
Цитата Сообщение от aLarman Посмотреть сообщение
а зачем его создавать?
Потому, что в стандартный поток вывести свою строку я не могу.
aLarman
636 / 557 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
07.03.2014, 12:04     Как создать свой поток и связать его с консолью #4
я может быть чего то не понял но попробую предложить, если нужен класс не чувствительных к регистру символов, то их нужно приводить к одному их регистров (нижний или верхний)
вот набросал
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
class CharNorReqister
{
public:
    CharNorReqister(char InX)
    {
        x = tolower(InX);
    }
    CharNorReqister():x(0)
    {
 
    }
    friend istream & operator>>(istream & is, CharNorReqister & X)
    {
        char a;
        is >> a;
        X.x = tolower(a);
        return is;
    }
    friend ostream & operator<<(ostream & os, CharNorReqister & X)
    {
        os << X.x;
        return os;
    }
private:
    char x;
};
дальше доопределить методы сравнений и операторы, или это не то?
DrOffset
6425 / 3799 / 880
Регистрация: 30.01.2014
Сообщений: 6,592
07.03.2014, 12:07     Как создать свой поток и связать его с консолью #5
Ilot,
C++
1
2
std::streambuf * buf = std::cout.rdbuf();
std::ostream out(buf);
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
07.03.2014, 12:07  [ТС]     Как создать свой поток и связать его с консолью #6
Цитата Сообщение от aLarman Посмотреть сообщение
или это не то?
Не то.
Есть класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct MyChar: public std::char_traits<char> {
    static bool
    eq(const char_type& __c1, const char_type& __c2)
    { return toupper(__c1) == toupper(__c2); }
 
    static bool
    lt(const char_type& __c1, const char_type& __c2)
    { return toupper(__c1) < toupper(__c2); }
    static int
    compare(const char_type* __s1, const char_type* __s2, size_t __n)
    { return memicmp(__s1, __s2, __n); }
    /*
    static const char_type*
    find(const char_type* __s, size_t __n, const char_type& __a)
    { return static_cast<const char_type*>(memchr(__s, __a, __n)); }
    */
};
 
//std::basic_ostream<char, MyChar> mcout;
typedef std::basic_string<char, MyChar> ci_string;
Надо сделать, что бы работало такое выражение:
C++
1
mcout << ci_string;
DrOffset
6425 / 3799 / 880
Регистрация: 30.01.2014
Сообщений: 6,592
07.03.2014, 12:13     Как создать свой поток и связать его с консолью #7
aLarman, он хочет через Traits.

Добавлено через 5 минут
Да, кстати придется делать и свой streambuf.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
07.03.2014, 12:41     Как создать свой поток и связать его с консолью #8
примерчик
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
07.03.2014, 14:53  [ТС]     Как создать свой поток и связать его с консолью #9
Tulosba, благодарю, однако вывести в стандартный поток это не проблема. Сложно ли создать свой поток и связать его с консолью, раз такая возможность предусмотренна в стандартной библиотеке и как это сделать? Вот собственно в чем вопрос.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
07.03.2014, 15:08     Как создать свой поток и связать его с консолью #10
Цитата Сообщение от Ilot Посмотреть сообщение
Сложно ли создать свой поток и связать его с консолью
Так ведь DrOffset всё написал уже выше.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
 
class mystream : public std::ostream
{
public:
    mystream()
    {
        rdbuf( std::cout.rdbuf() );
    }
};
 
int main() {
 
    mystream m;
    m << "Hello\n";
 
    return 0;
}
http://ideone.com/uvNq9M

Конструктор можно сделать даже так:
C++
1
mystream() : std::ostream( std::cout.rdbuf() ) { }
DrOffset
6425 / 3799 / 880
Регистрация: 30.01.2014
Сообщений: 6,592
07.03.2014, 15:09     Как создать свой поток и связать его с консолью #11
Ilot, я ж говорю, наследуйся от basic_streambuf (если хочешь собственный Traits, то streambuf от stdcout не подойдет, т.к. привязан к его Traits).
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
11.03.2014, 14:49  [ТС]     Как создать свой поток и связать его с консолью #12
Цитата Сообщение от DrOffset Посмотреть сообщение
Ilot, я ж говорю, наследуйся от basic_streambuf (если хочешь собственный Traits, то streambuf от stdcout не подойдет, т.к. привязан к его Traits).
Я знаю что cout не подойдет, поэтому и создал тему. Однако если файловый поток создать это как два пальца:
Кликните здесь для просмотра всего текста
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 <string.h>
#include <fstream>
struct MyChar: public std::char_traits<char> {
    static bool
    eq(const char_type& __c1, const char_type& __c2)
    { return toupper(__c1) == toupper(__c2); }
 
    static bool
    lt(const char_type& __c1, const char_type& __c2)
    { return toupper(__c1) < toupper(__c2); }
    static int
    compare(const char_type* __s1, const char_type* __s2, size_t __n)
    { return memicmp(__s1, __s2, __n); }
};
//std::basic_ostream<char, MyChar> mcout;
typedef std::basic_string<char, MyChar> ci_string;
int main()
{
    std::basic_ofstream<char, MyChar> mfout;
    mfout.open("C:\\rt.txt");
    ci_string str1("Masha");
    mfout << str1;
    return 0;
}

,то с созданием потока завязанного на консоль возникают определенные трудности. Понятно, что нужно создавать поток и передавать ему указатель на потоковый буфер, но вот так
C++
1
std::streambuf * buf = std::cout.rdbuf();
это сделать нельзя так как у меня должен быть буфер типа:
basic_streambuf<char, MyChar>
Интересно, а где создается объект cout? В заголовочниках нашел только:
C++
1
  extern ostream cout;
и ни одного намека на то где искать определение самого объекта.
Почитал немного о системном программировании в Win. Там пишут, что при создании консольного приложения для него создаются соответствующие потоки ввода/вывода. Другими словами выходит, что бы изменить поток вывода в консоль нужно юзать функции апи, а не стандартной библиотеки?
DrOffset
6425 / 3799 / 880
Регистрация: 30.01.2014
Сообщений: 6,592
11.03.2014, 18:46     Как создать свой поток и связать его с консолью #13
Цитата Сообщение от Ilot Посмотреть сообщение
это сделать нельзя так как у меня должен быть буфер типа:
basic_streambuf<char, MyChar>
Так ведь я же и говорю, что нужно сделать свой streambuf, который бы соответствовал твоему traits.
Надо отнаследоваться от basic_streambuf<char, MyChar>, подробности можно посмотреть тут.

Цитата Сообщение от Ilot Посмотреть сообщение
Интересно, а где создается объект cout?
Внутри С++ runtime.

Добавлено через 18 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class console_buffer
    : public std::basic_streambuf<char, MyChar>
{
//......
};
 
int main()
{
    console_buffer conBuf;
    std::basic_ostream<char, MyChar> conOut(&conBuf);
 
    conOut << "test";
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.04.2014, 19:51     Как создать свой поток и связать его с консолью
Еще ссылки по теме:

C++ Как создать свой архив, упаковывать и распаковывать?
Как создать свой символ C++
C++ Как создать свой целочисленный тип данных с пределом от 0 до 500

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

Или воспользуйтесь поиском по форуму:
DrOffset
6425 / 3799 / 880
Регистрация: 30.01.2014
Сообщений: 6,592
14.04.2014, 19:51     Как создать свой поток и связать его с консолью #14
Ilot,
Ну вот как-то так может выглядеть реализация:
Кликните здесь для просмотра всего текста
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
102
103
104
105
106
107
108
109
110
111
112
113
#include <streambuf>
#include <limits>
#include <cstdio>
 
class console_buffer
    : public std::basic_streambuf< char, std::char_traits<char> >
{
public:
    explicit console_buffer(FILE * file)
        : file_(file)
    {}
 
    ~console_buffer()
    {
        std::fflush(file_);
    }
 
protected:
    std::basic_streambuf<char, std::char_traits<char> > * setbuf(char * s, std::streamsize n)
    {
        size_t n_size_t = sizeof(std::streamsize) > sizeof(size_t)
                          ? static_cast<size_t>(
                                std::min(
                                    static_cast<std::streamsize>(std::numeric_limits<size_t>::max())
                                  , n
                                )
                            )
                          : static_cast<size_t>(n);
        std::setvbuf(file_, s, s == 0 && n == 0 ? _IONBF : _IOFBF, n_size_t);
        return this;
    }
 
    pos_type seekoff(off_type off
                     , std::ios_base::seekdir dir
                     , std::ios_base::openmode = std::ios_base::in | std::ios_base::out)
    {
        int whence;
        switch(dir)
        {
        case std::ios_base::beg:
            whence = SEEK_SET;
            break;
        case std::ios_base::cur:
            whence = SEEK_CUR;
            break;
        case std::ios_base::end:
            whence = SEEK_END;
            break;
        default:
            return pos_type(-1);
        }
        if(off <= std::numeric_limits<off_type>::max() && std::fseek(file_, off, whence) == 0)
        {
            std::fpos_t pos;
            std::fgetpos(file_, &pos);
            return pos_type(pos);
        }
        return pos_type(-1);
    }
 
    pos_type seekpos(pos_type pos
                     , std::ios_base::openmode = std::ios_base::in | std::ios_base::out)
    {
        std::fpos_t p(pos);
        return std::fsetpos(file_, &p) == 0 ? pos : pos_type(-1);
    }
 
    int sync()
    {
        return std::fflush(file_) == 0 ? 0 : -1;
    }
 
    std::streamsize showmanyc()
    {
        return -1;
    }
 
    int_type overflow(int_type c = traits_type::eof())
    {
        if(c == traits_type::eof())
        {
            std::ptrdiff_t unwritten = this->pptr() - this->pbase();
            if(unwritten != 0)
            {
                std::fflush(file_);
                if(this->pptr() - this->pbase() < unwritten)
                {
                    return traits_type::not_eof(c);
                }
                return traits_type::eof();
            }
            return traits_type::not_eof(c);
        }
        else
        {
            int result = putc(c, file_);
            return result != EOF ? result : traits_type::eof();
        }
    }
 
private:
    FILE * file_;
};
 
#include <ostream>
 
int main()
{
    console_buffer conBuf(stdout);
    std::basic_ostream<char, std::char_traits<char> > conOut(&conBuf);
 
    conOut << "TeSt";
}
Yandex
Объявления
14.04.2014, 19:51     Как создать свой поток и связать его с консолью
Ответ Создать тему
Опции темы

Текущее время: 21:20. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru