Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.83/18: Рейтинг темы: голосов - 18, средняя оценка - 4.83
9 / 9 / 0
Регистрация: 22.01.2012
Сообщений: 59
1

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

12.08.2014, 09:10. Показов 3245. Ответов 20
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте. Возможно ли в C++ реализовать аналог функции read() из паскаля. Хотя бы с условием, что все входные данные одного типа. Без передачи указателя
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.08.2014, 09:10
Ответы с готовыми решениями:

Существует ли аналог функции Trunc из Паскаля
Добрый день. Нужно r1 вернуть в целую часть, когда k2 дробная. В паскале использовался trunc, а...

Реализовать аналог функции Sign
Можно-ли реализовать аналог функции Sign, по данному псевдокоду: проверка: если x равно нулю то...

Реализовать аналог функции Magic (Matlab) на С++
Нужно переписать функцию MatLab которая называется magic на с++

Аналог проводника. Реализовать фильтрацию файлов и другие функции
Здравствуйте,нужна ваша помощь,потому что на C # не пишу а сдать работу нужно срочно.Разбираться не...

20
317 / 179 / 73
Регистрация: 18.01.2014
Сообщений: 387
12.08.2014, 09:19 2
Чем работа с потоками не устраивает?

C++
1
2
3
4
int a;
double b;
std::string c;
std::cin >> a >> b >> c;
0
9 / 9 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 09:34  [ТС] 3
BlackIce, так получилось, что сейчас мне нужно передать аргументы именно через запятую и без "&"
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
12.08.2014, 09:39 4
Цитата Сообщение от Андрей Xomach Посмотреть сообщение
так получилось, что сейчас мне нужно передать аргументы именно через запятую
А конкретнее? С примером кода.
0
9 / 9 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 09:42  [ТС] 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
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
12.08.2014, 09:48 6
Лучший ответ Сообщение было отмечено Андрей Xomach как решение

Решение

Да написать-то можно, я только в упор не понимаю зачем.
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
2
9 / 9 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 09:52  [ТС] 7
C++
1
2
3
4
5
template <class T, class... Args>
void Read(T& item, Args&&... args) {
    std::cin >> item;
    Read(args...);
}
0x10, вау... Что-то новенькое. Огромное вам спасибо. Понять бы теперь, что это за магия такая
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
12.08.2014, 09:56 8
Магия называется Variadic Templates, требует компилятор с поддержкой С++11 и, я почти уверен, для Вашей задачи необходимости в таких извращениях нет. Поэтому и спрашивал: зачем?
1
9 / 9 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 10:04  [ТС] 9
0x10, наверное, просто из любопытства
Еще год-два назад в рамках олимпиадного программирования захотелось избавиться от
C++
1
2
type a, b, c, d;
cin >> a >> b >> c >> d;
и преобразовать это в
C++
1
get (type, a, b, c, d);
0
Вежливость-главное оружие
233 / 234 / 86
Регистрация: 19.02.2013
Сообщений: 1,446
12.08.2014, 10:52 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, я вот только понять не могу, как вы по стеку двигаетесь?
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
12.08.2014, 11:04 11
Цитата Сообщение от some_name Посмотреть сообщение
Попробуйте вот так:
Работа с указателями сводит на нет всю безопасность относительно типов.

Цитата Сообщение от some_name Посмотреть сообщение
я вот только понять не могу, как вы по стеку двигаетесь?
"Движения по стеку" нет. В строке 12 происходит разворачивание пакета аргументов args и поиск наиболее подходящей функции. Пока в пакете > 1 аргумента вызывается эта же функция Read и первый элемент пакета связывается с ее первым аргументом. Когда в пакете остается один элемент, вызывается версия Read, принимающая единственный аргумент.
0
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
12.08.2014, 11:09 12
Цитата Сообщение от 0x10 Посмотреть сообщение
Работа с указателями сводит на нет всю безопасность относительно типов.
Это ты в каком смысле?
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
12.08.2014, 11:13 13
Цитата Сообщение от Voivoid Посмотреть сообщение
Это ты в каком смысле?
На этапе компиляции никак не контролируется, что все аргументы, переданные в функцию, будут одного типа, а она это предполагает, пытаясь перемещаться по стеку аргументов путем смещения указателя.
0
9 / 9 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 13:44  [ТС] 14
0x10, стоп, можно глупый вопрос?
Ведь template создает новую версию функции для различных аргументов шаблона, так? Но тогда данная реализация приведет к тому, что будет создано по 1 функции read для каждого числа аргументов. То есть, если я вызову read от 5 аргументов, это создаст 4 версии функции read, не считая стандартной.
+ к тому, рекурсивная передача аргументов будет занимать квадратное время относительно числа входных данных, нет?
Конечно, даже если я тут и прав, все это несущественно в данном конкретном примере (время на считывание уйдет много больше), но все-таки, разве рекурсивный вызов шаблонной функции не есть зло?
0
Вежливость-главное оружие
233 / 234 / 86
Регистрация: 19.02.2013
Сообщений: 1,446
12.08.2014, 14:19 15
Цитата Сообщение от 0x10 Посмотреть сообщение
разворачивание пакета аргументов args
так а пакет из себя что представляет?
и во что он разворачивается?
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
12.08.2014, 14:23 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) - аргументы, указанные при вызове функции.
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
15.08.2014, 19:33 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]
2
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
15.08.2014, 19:47 18
Цитата Сообщение от Андрей Xomach Посмотреть сообщение
разве рекурсивный вызов шаблонной функции не есть зло?
Нет, это не зло Гораздо более серьезные вещи, чем продемонстрировал 0x10 корректно встраиваются как правило без какого-либо оверхеда (естественно если оптимизация включена).
0
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
15.08.2014, 19:50 19
Цитата Сообщение от DrOffset Посмотреть сообщение
Нет, это не зло
Я бы даже сказал, что рекурсивный вызов любой функции это не зло, если конечно выполняется tail call оптимизация
0
9 / 9 / 0
Регистрация: 22.01.2012
Сообщений: 59
23.08.2014, 17:01  [ТС] 20
DrOffset, Voivoid, с -Os или -O0 все-таки зло наверное
0
23.08.2014, 17:01
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.08.2014, 17:01
Помогаю со студенческими работами здесь

Аналог READ и DATA в VB 2008
Всем доброго времени суток! В Basic оператор READ читает данные из оператора DATA. В VB 2008...

Аналог type паскаля в c#
Здраствуйте. В c# можно както сделать тип по аналогии паскалевского type TTyp = (ttName1, ttName2,...

Аналог графики Паскаля?
Доброго здравия, бояре программисты) Учусь в школе,где учитель заставляет программировать на...

Есть ли в Си аналог GraphABC из Паскаля?
Собственно, сабж. Надо по данным из файла нарисовать график. В паскале надо было просто подрубить...


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

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