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

Возможно ли реализовать аналог функции Read из Паскаля? - C++

Восстановить пароль Регистрация
 
Андрей Xomach
8 / 8 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 09:10     Возможно ли реализовать аналог функции Read из Паскаля? #1
Здравствуйте. Возможно ли в C++ реализовать аналог функции read() из паскаля. Хотя бы с условием, что все входные данные одного типа. Без передачи указателя
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.08.2014, 09:10     Возможно ли реализовать аналог функции Read из Паскаля?
Посмотрите здесь:

Аналог функции fscanf (C++) C++
C++ Аналог VB-функции Like
C++ Помогите реализовать программу, возможно за денежное вознаграждение
C++ аналог функции IsDelimiter
возможно ли реализовать клиент и сервер на разных машинах в одной ЛВС? C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
BlackIce
309 / 171 / 64
Регистрация: 18.01.2014
Сообщений: 387
12.08.2014, 09:19     Возможно ли реализовать аналог функции Read из Паскаля? #2
Чем работа с потоками не устраивает?

C++
1
2
3
4
int a;
double b;
std::string c;
std::cin >> a >> b >> c;
Андрей Xomach
8 / 8 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 09:34  [ТС]     Возможно ли реализовать аналог функции Read из Паскаля? #3
BlackIce, так получилось, что сейчас мне нужно передать аргументы именно через запятую и без "&"
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
12.08.2014, 09:39     Возможно ли реализовать аналог функции Read из Паскаля? #4
Цитата Сообщение от Андрей Xomach Посмотреть сообщение
так получилось, что сейчас мне нужно передать аргументы именно через запятую
А конкретнее? С примером кода.
Андрей Xomach
8 / 8 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 09:42  [ТС]     Возможно ли реализовать аналог функции Read из Паскаля? #5
C++
1
2
3
4
int a, b, c, d;
read (a, b, c, d); // можно даже read <int> (a, b, c, d), хотя сложно представить код, где это потребуется
string s, g;
read (s, g);
естественно, этот read() должен в итоге использовать cin
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
12.08.2014, 09:48     Возможно ли реализовать аналог функции Read из Паскаля? #6
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Да написать-то можно, я только в упор не понимаю зачем.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <string>
 
template <class T>
void Read(T& item) {
    std::cin >> item;
}
 
template <class T, class... Args>
void Read(T& item, Args&&... args) {
    Read(item);
    Read(args...);
}
 
int main() {
    int a, b;
    std::string str;
    
    Read(a, b, str);
    
    std::cout << a << " " << b << " " << str;
}
http://ideone.com/ABUA3o
Андрей Xomach
8 / 8 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 09:52  [ТС]     Возможно ли реализовать аналог функции Read из Паскаля? #7
C++
1
2
3
4
5
template <class T, class... Args>
void Read(T& item, Args&&... args) {
    std::cin >> item;
    Read(args...);
}
0x10, вау... Что-то новенькое. Огромное вам спасибо. Понять бы теперь, что это за магия такая
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
12.08.2014, 09:56     Возможно ли реализовать аналог функции Read из Паскаля? #8
Магия называется Variadic Templates, требует компилятор с поддержкой С++11 и, я почти уверен, для Вашей задачи необходимости в таких извращениях нет. Поэтому и спрашивал: зачем?
Андрей Xomach
8 / 8 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 10:04  [ТС]     Возможно ли реализовать аналог функции Read из Паскаля? #9
0x10, наверное, просто из любопытства
Еще год-два назад в рамках олимпиадного программирования захотелось избавиться от
C++
1
2
type a, b, c, d;
cin >> a >> b >> c >> d;
и преобразовать это в
C++
1
get (type, a, b, c, d);
some_name
Вежливость-главное оружие
 Аватар для some_name
219 / 219 / 55
Регистрация: 19.02.2013
Сообщений: 1,419
12.08.2014, 10:52     Возможно ли реализовать аналог функции Read из Паскаля? #10
Попробуйте вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "stdafx.h"
#include <iostream>
 
template <class T>
void read(T arg0, ...){ 
    T* ptrArg = (T*)&arg0;
    while(*ptrArg != 0){
        std::cin >> (**ptrArg);     
        ++ptrArg;        
    }
}
 
int main()
{    
    double a = 0, b = 0, c = 0;
    read<double*>(&a, &b, &c, 0);
    std::cout <<"  "<< a <<"  "<< b <<"  "<< c;
    return 0;
}
Добавлено через 7 минут
0x10, я вот только понять не могу, как вы по стеку двигаетесь?
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
12.08.2014, 11:04     Возможно ли реализовать аналог функции Read из Паскаля? #11
Цитата Сообщение от some_name Посмотреть сообщение
Попробуйте вот так:
Работа с указателями сводит на нет всю безопасность относительно типов.

Цитата Сообщение от some_name Посмотреть сообщение
я вот только понять не могу, как вы по стеку двигаетесь?
"Движения по стеку" нет. В строке 12 происходит разворачивание пакета аргументов args и поиск наиболее подходящей функции. Пока в пакете > 1 аргумента вызывается эта же функция Read и первый элемент пакета связывается с ее первым аргументом. Когда в пакете остается один элемент, вызывается версия Read, принимающая единственный аргумент.
Voivoid
 Аватар для Voivoid
580 / 256 / 12
Регистрация: 31.03.2013
Сообщений: 1,284
12.08.2014, 11:09     Возможно ли реализовать аналог функции Read из Паскаля? #12
Цитата Сообщение от 0x10 Посмотреть сообщение
Работа с указателями сводит на нет всю безопасность относительно типов.
Это ты в каком смысле?
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
12.08.2014, 11:13     Возможно ли реализовать аналог функции Read из Паскаля? #13
Цитата Сообщение от Voivoid Посмотреть сообщение
Это ты в каком смысле?
На этапе компиляции никак не контролируется, что все аргументы, переданные в функцию, будут одного типа, а она это предполагает, пытаясь перемещаться по стеку аргументов путем смещения указателя.
Андрей Xomach
8 / 8 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 13:44  [ТС]     Возможно ли реализовать аналог функции Read из Паскаля? #14
0x10, стоп, можно глупый вопрос?
Ведь template создает новую версию функции для различных аргументов шаблона, так? Но тогда данная реализация приведет к тому, что будет создано по 1 функции read для каждого числа аргументов. То есть, если я вызову read от 5 аргументов, это создаст 4 версии функции read, не считая стандартной.
+ к тому, рекурсивная передача аргументов будет занимать квадратное время относительно числа входных данных, нет?
Конечно, даже если я тут и прав, все это несущественно в данном конкретном примере (время на считывание уйдет много больше), но все-таки, разве рекурсивный вызов шаблонной функции не есть зло?
some_name
Вежливость-главное оружие
 Аватар для some_name
219 / 219 / 55
Регистрация: 19.02.2013
Сообщений: 1,419
12.08.2014, 14:19     Возможно ли реализовать аналог функции Read из Паскаля? #15
Цитата Сообщение от 0x10 Посмотреть сообщение
разворачивание пакета аргументов args
так а пакет из себя что представляет?
и во что он разворачивается?
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
12.08.2014, 14:23     Возможно ли реализовать аналог функции Read из Паскаля? #16
Цитата Сообщение от Андрей Xomach Посмотреть сообщение
по 1 функции read для каждого числа аргументов
Да, но все это происходит на этапе компиляции, поэтому рекурсивные вызовы могут быть поинлайнены.
Что касается передачи аргументов, я уже второй раз забываю про std::forward, в связи с чем исправляюсь:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <string>
#include <utility>
 
template <class T>
void Read(T& item) {
    std::cin >> item;
}
 
template <class T, class... Args>
void Read(T& item, Args&&... args) {
    Read(item);
    Read(std::forward<Args>(args)...);
}
 
int main() {
    int a, b;
    std::string str;
    
    Read(a, b, str);
    
    std::cout << a << " " << b << " " << str;
}
Цитата Сообщение от some_name Посмотреть сообщение
так а пакет из себя что представляет?
и во что он разворачивается?
На уровне ассемблера не покажу, но суть - список аргументов. Т.е. вызов f(args...) аналогичен f(a, b, c, d), где (a..d) - аргументы, указанные при вызове функции.
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
15.08.2014, 19:33     Возможно ли реализовать аналог функции Read из Паскаля? #17
Цитата Сообщение от 0x10 Посмотреть сообщение
На уровне ассемблера не покажу
Все-таки показать надо, чтобы не быть голословным. Из кода выше уберем все лишнее, чтобы было проще читать ассемблерный выхлоп. Итого останется:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void DummyFunction(int item);
 
template <class T>
void Read(T& item) {
    DummyFunction(item);
}
 
template <class T, class... Args>
void Read(T& item, Args&&... args) {
    Read(item);
    Read(args...);
}
 
int main() {
    int a, b, c, d;
    Read(a, b, c, d);
}
Сначала собираем без оптимизации:
g++ -std=c++11 -O0 -S main.cpp
Assembler
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    .file   "main.cpp"
    .text
    .globl  main
    .type   main, @function
main:
.LFB2:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    leaq    -4(%rbp), %rcx
    leaq    -8(%rbp), %rdx
    leaq    -12(%rbp), %rsi
    leaq    -16(%rbp), %rax
    movq    %rax, %rdi
    call    _Z4ReadIiIRiS0_S0_EEvRT_DpOT0_
    movl    $0, %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE2:
    .size   main, .-main
    .section    .text._Z4ReadIiIRiS0_S0_EEvRT_DpOT0_,"axG",@progbits,_Z4ReadIiIRiS0_S0_EEvRT_DpOT0_,comdat
    .weak   _Z4ReadIiIRiS0_S0_EEvRT_DpOT0_
    .type   _Z4ReadIiIRiS0_S0_EEvRT_DpOT0_, @function
_Z4ReadIiIRiS0_S0_EEvRT_DpOT0_:
.LFB3:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $32, %rsp
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    movq    %rdx, -24(%rbp)
    movq    %rcx, -32(%rbp)
    movq    -8(%rbp), %rax
    movq    %rax, %rdi
    call    _Z4ReadIiEvRT_
    movq    -32(%rbp), %rdx
    movq    -24(%rbp), %rcx
    movq    -16(%rbp), %rax
    movq    %rcx, %rsi
    movq    %rax, %rdi
    call    _Z4ReadIiIRiS0_EEvRT_DpOT0_
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE3:
    .size   _Z4ReadIiIRiS0_S0_EEvRT_DpOT0_, .-_Z4ReadIiIRiS0_S0_EEvRT_DpOT0_
    .weak   _Z4ReadIiJRiS0_S0_EEvRT_DpOT0_
    .set    _Z4ReadIiJRiS0_S0_EEvRT_DpOT0_,_Z4ReadIiIRiS0_S0_EEvRT_DpOT0_
    .section    .text._Z4ReadIiEvRT_,"axG",@progbits,_Z4ReadIiEvRT_,comdat
    .weak   _Z4ReadIiEvRT_
    .type   _Z4ReadIiEvRT_, @function
_Z4ReadIiEvRT_:
.LFB4:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rax
    movl    (%rax), %eax
    movl    %eax, %edi
    call    _Z13DummyFunctioni
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE4:
    .size   _Z4ReadIiEvRT_, .-_Z4ReadIiEvRT_
    .section    .text._Z4ReadIiIRiS0_EEvRT_DpOT0_,"axG",@progbits,_Z4ReadIiIRiS0_EEvRT_DpOT0_,comdat
    .weak   _Z4ReadIiIRiS0_EEvRT_DpOT0_
    .type   _Z4ReadIiIRiS0_EEvRT_DpOT0_, @function
_Z4ReadIiIRiS0_EEvRT_DpOT0_:
.LFB5:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $32, %rsp
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    movq    %rdx, -24(%rbp)
    movq    -8(%rbp), %rax
    movq    %rax, %rdi
    call    _Z4ReadIiEvRT_
    movq    -24(%rbp), %rdx
    movq    -16(%rbp), %rax
    movq    %rdx, %rsi
    movq    %rax, %rdi
    call    _Z4ReadIiIRiEEvRT_DpOT0_
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE5:
    .size   _Z4ReadIiIRiS0_EEvRT_DpOT0_, .-_Z4ReadIiIRiS0_EEvRT_DpOT0_
    .weak   _Z4ReadIiJRiS0_EEvRT_DpOT0_
    .set    _Z4ReadIiJRiS0_EEvRT_DpOT0_,_Z4ReadIiIRiS0_EEvRT_DpOT0_
    .section    .text._Z4ReadIiIRiEEvRT_DpOT0_,"axG",@progbits,_Z4ReadIiIRiEEvRT_DpOT0_,comdat
    .weak   _Z4ReadIiIRiEEvRT_DpOT0_
    .type   _Z4ReadIiIRiEEvRT_DpOT0_, @function
_Z4ReadIiIRiEEvRT_DpOT0_:
.LFB6:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    movq    -8(%rbp), %rax
    movq    %rax, %rdi
    call    _Z4ReadIiEvRT_
    movq    -16(%rbp), %rax
    movq    %rax, %rdi
    call    _Z4ReadIiEvRT_
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE6:
    .size   _Z4ReadIiIRiEEvRT_DpOT0_, .-_Z4ReadIiIRiEEvRT_DpOT0_
    .weak   _Z4ReadIiJRiEEvRT_DpOT0_
    .set    _Z4ReadIiJRiEEvRT_DpOT0_,_Z4ReadIiIRiEEvRT_DpOT0_
    .ident  "GCC: (Ubuntu 4.9-20140406-1ubuntu1) 4.9.0 20140405 (experimental) [trunk revision 209157]"
    .section    .note.GNU-stack,"",@progbits

Разбирать весь код достаточно нудно, нам хватит заметить, что сгенерено несколько вариантов функции Read:
Код
$ cat main.s | grep Read | grep function
	.type	_Z4ReadIiIRiS0_S0_EEvRT_DpOT0_, @function
	.type	_Z4ReadIiEvRT_, @function
	.type	_Z4ReadIiIRiS0_EEvRT_DpOT0_, @function
	.type	_Z4ReadIiIRiEEvRT_DpOT0_, @function
И всего один вызов нашей заглушки DummyFunction - в 76 строке ассемблерного кода.
Первый уровень оптимизации:
g++ -std=c++11 -O1 -S main.cpp
Assembler
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
    .file   "main.cpp"
    .section    .text._Z4ReadIiEvRT_,"axG",@progbits,_Z4ReadIiEvRT_,comdat
    .weak   _Z4ReadIiEvRT_
    .type   _Z4ReadIiEvRT_, @function
_Z4ReadIiEvRT_:
.LFB4:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    (%rdi), %edi
    call    _Z13DummyFunctioni
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE4:
    .size   _Z4ReadIiEvRT_, .-_Z4ReadIiEvRT_
    .text
    .globl  main
    .type   main, @function
main:
.LFB2:
    .cfi_startproc
    subq    $24, %rsp
    .cfi_def_cfa_offset 32
    movq    %rsp, %rdi
    call    _Z4ReadIiEvRT_
    leaq    4(%rsp), %rdi
    call    _Z4ReadIiEvRT_
    leaq    8(%rsp), %rdi
    call    _Z4ReadIiEvRT_
    leaq    12(%rsp), %rdi
    call    _Z4ReadIiEvRT_
    movl    $0, %eax
    addq    $24, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE2:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.9-20140406-1ubuntu1) 4.9.0 20140405 (experimental) [trunk revision 209157]"
    .section    .note.GNU-stack,"",@progbits

У нас осталась одна функция Read, которая вызывается по одному разу для каждого аргумента. Уже тут нет рекурсивных вызовов. Если же использовать флаг -O2, то и эта функция будет заинлайнена:
g++ -std=c++11 -O2 -S main.cpp
Assembler
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
    .file   "main.cpp"
    .section    .text.unlikely,"ax",@progbits
.LCOLDB0:
    .section    .text.startup,"ax",@progbits
.LHOTB0:
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB2:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    xorl    %edi, %edi
    call    _Z13DummyFunctioni
    xorl    %edi, %edi
    call    _Z13DummyFunctioni
    xorl    %edi, %edi
    call    _Z13DummyFunctioni
    xorl    %edi, %edi
    call    _Z13DummyFunctioni
    xorl    %eax, %eax
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE2:
    .size   main, .-main
    .section    .text.unlikely
.LCOLDE0:
    .section    .text.startup
.LHOTE0:
    .ident  "GCC: (Ubuntu 4.9-20140406-1ubuntu1) 4.9.0 20140405 (experimental) [trunk revision 209157]"
    .section    .note.GNU-stack,"",@progbits

Получено на компиляторе:
Код
$ g++ --version
g++ (Ubuntu 4.9-20140406-1ubuntu1) 4.9.0 20140405 (experimental) [trunk revision 209157]
DrOffset
6427 / 3801 / 881
Регистрация: 30.01.2014
Сообщений: 6,601
15.08.2014, 19:47     Возможно ли реализовать аналог функции Read из Паскаля? #18
Цитата Сообщение от Андрей Xomach Посмотреть сообщение
разве рекурсивный вызов шаблонной функции не есть зло?
Нет, это не зло Гораздо более серьезные вещи, чем продемонстрировал 0x10 корректно встраиваются как правило без какого-либо оверхеда (естественно если оптимизация включена).
Voivoid
 Аватар для Voivoid
580 / 256 / 12
Регистрация: 31.03.2013
Сообщений: 1,284
15.08.2014, 19:50     Возможно ли реализовать аналог функции Read из Паскаля? #19
Цитата Сообщение от DrOffset Посмотреть сообщение
Нет, это не зло
Я бы даже сказал, что рекурсивный вызов любой функции это не зло, если конечно выполняется tail call оптимизация
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.08.2014, 17:01     Возможно ли реализовать аналог функции Read из Паскаля?
Еще ссылки по теме:

Аналог функции SetLength C++
C++ Реализовать аналог класса std::string с помощью vector
Реализовать аналог функции Magic (Matlab) на С++ C++

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

Или воспользуйтесь поиском по форуму:
Андрей Xomach
8 / 8 / 0
Регистрация: 22.01.2012
Сообщений: 59
23.08.2014, 17:01  [ТС]     Возможно ли реализовать аналог функции Read из Паскаля? #20
DrOffset, Voivoid, с -Os или -O0 все-таки зло наверное
Yandex
Объявления
23.08.2014, 17:01     Возможно ли реализовать аналог функции Read из Паскаля?
Ответ Создать тему
Опции темы

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