Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/15: Рейтинг темы: голосов - 15, средняя оценка - 4.73
0 / 0 / 0
Регистрация: 25.12.2012
Сообщений: 50

Рекурсивный расчёт математического выражения со скобками (рекурсивную функцию оформить в виде потока)

10.01.2016, 00:35. Показов 3159. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Помогите пожалуйста решить данную задачу:
Рекурсивный расчет математического выражения со скобками, рекурсивная функция оформляется в виде потока.

Добавлено через 1 час 35 минут
up!
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
10.01.2016, 00:35
Ответы с готовыми решениями:

Как рекурсивную функцию вычисления выражения оформить в виде потока?
Здравствуйте. Помогите затолкать рекурсивную функцию в поток под линукс <pthread.h> Есть прога, которая делает рекурсивный расчет...

Рекурсивный расчет математического выражения со скобками
Рекурсивный расчет математического выражения со скобками, рекурсивная функция оформляется в виде потока. Слышал что можно через двоичное...

Рекурсивный расчет математического выражения со скобками, в чем ошибка?
задача Рекурсивный расчет математического выражения со скобками, рекурсивная функция оформляется в виде потока.(прямой алгоритм без потока...

16
4 / 4 / 6
Регистрация: 14.10.2015
Сообщений: 26
10.01.2016, 00:52
Fighter215, юзайте поиск. Рекурсивный расчет математического выражения со скобками
0
0 / 0 / 0
Регистрация: 25.12.2012
Сообщений: 50
10.01.2016, 00:56  [ТС]
GoldenSpice, юзал, тему видел, но такой вариант мне не подходит. Далее нужно реализовать сервер/клиент, а парсинг через cin.get не прокатит там.
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
10.01.2016, 01:23
Цитата Сообщение от Fighter215 Посмотреть сообщение
а парсинг через cin.get не прокатит там
cin/cout можно заметинить на любой другой поток ввода/вывода.
Например, в качестве него может выступать и канал связи между двумя процессами.
0
0 / 0 / 0
Регистрация: 25.12.2012
Сообщений: 50
10.01.2016, 20:36  [ТС]
nonedark2008, я не мастак в c++, поэтому и прошу помощи.

Операционная система: Windows
Задание 1: Рекурсивный расчет математического выражения со скобками, рекурсивная функция оформляется в виде потока
Задание 2: Вычисление математического выражения со скобками. Клиент шлет на сервер выражение через консоль. Сервер выдает ответ. Протокол взаимодействия TCP;

Добавлено через 38 минут
up!

Добавлено через 16 минут
up!!
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
10.01.2016, 21:02
Цитата Сообщение от Fighter215 Посмотреть сообщение
Задание 1
Пишешь обычную рекурсивную функцию, которая принмает на вход строку со скобочным выражением и выдает результат. Чтобы запустить эту функцию в другом потоке можешь использовать, например std::thread.
Цитата Сообщение от Fighter215 Посмотреть сообщение
Задание 2
Пишешь две программы клиент и сервер.
Клиент подключается к серверу через сокет, передает строку с выражением и ждет результата.
Сервер ждет подключения от клиента. Как только подключение есть, он создает поток для этого подключения, который ждет выражение от клиента, вычисляет его и возращает результат.
Написать сервер чуть сложнее первого задания, а клиент и того проще.
Цитата Сообщение от Fighter215 Посмотреть сообщение
я не мастак в c++, поэтому и прошу помощи
Помимо c++ тут необходимо много чего: понимание потоков, процесов и знание сокетов под Windows.
На форуме помогают либо по мелочам, либо при интересной задаче.
Цитата Сообщение от Fighter215 Посмотреть сообщение
юзал, тему видел, но такой вариант мне не подходит. Далее нужно реализовать сервер/клиент, а парсинг через cin.get не прокатит там.
Сервер для клиента создает поток, получает от него строку с выражением, запихивает эту строку в скажем std::istringstream и получает поток ввода, который можно использовать вместо cin.
1
0 / 0 / 0
Регистрация: 25.12.2012
Сообщений: 50
10.01.2016, 21:05  [ТС]
nonedark2008, как это сделать в теория я понимаю. А вот с практикой одни проблемы.
0
10.01.2016, 21:14

Не по теме:

Цитата Сообщение от Fighter215 Посмотреть сообщение
А вот с практикой одни проблемы.
Тут помогают только с определенными проблемами, возникающими в ходе выполнения задачи.
Сомнительно что кто-то из жалости сделает за тебя всю твою работу.
Тебе нужно либо сделать/найти решение самостоятельно, задавая конкретные вопросы тут на форуме,
либо заказать программу за вознаграждение.

0
0 / 0 / 0
Регистрация: 25.12.2012
Сообщений: 50
10.01.2016, 21:30  [ТС]
nonedark2008, не все гонятся за вознаграждением. Люди уже ни раз помогали за спасибо. Тем более, что данная задача вроде не из сложных (хоть я и не могу её решить).

Добавлено через 13 минут
Клиент
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
#include "stdafx.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <iostream>
#include <locale.h>
 
#ifndef UNICODE
#define UNICODE
#endif
 
#define WIN32_LEAN_AND_MEAN
#define DEFAULT_BUFLEN 512
 
using namespace std;
 
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
 
int wmain()
{
    setlocale(LC_ALL, "RU");
    //----------------------
    // Initialize Winsock
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup function failed with error: %d\n", iResult);
        return 1;
    }
    //----------------------
    // Create a SOCKET for connecting to server
    SOCKET ConnectSocket;
    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ConnectSocket == INVALID_SOCKET) {
        wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port of the server to be connected to.
    sockaddr_in clientService;
    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
    clientService.sin_port = htons(27015);
 
    //----------------------
    // Connect to server.
    char path[MAX_PATH] = {0};
 
    cout << "Введите выражение: ";
    cin.getline (path, MAX_PATH);
 
    iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService));
    if (iResult == SOCKET_ERROR) {
        wprintf(L"connect function failed with error: %ld\n", WSAGetLastError());
        iResult = closesocket(ConnectSocket);
        if (iResult == SOCKET_ERROR)
            wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    wprintf(L"Connected to server.\n");
    
    iResult = send( ConnectSocket, path, sizeof(path), 0 );
    
    iResult = closesocket(ConnectSocket);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
 
    WSACleanup();
    return 0;
}


Сервер
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
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include "stdafx.h"
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>
#include <iostream>
#include <locale.h>
#include <sstream>
#ifndef UNICODE
#define UNICODE
#endif
// Need to link with Ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
 
using namespace std;
istringstream ist;
float number();
float factor();
float expr();
 
 
float number()
{
    int res = 0;
 
    while(true)
    {
        char c = ist.get();
        if(c >= '0' && c <= '9')
        res = res * 10 + c - '0';
        else
        {
            ist.putback(c);
            break;
        }
    }
return res;
}
float factor()
{
    float x;
    char c = ist.get();
    if(c == '(')
       {
           x = expr();
           ist.get();
       }
       else
       {
           ist.putback(c);
           x = number();
       }
    c = cin.get();
    switch(c)
    {
        case '*':
            return x * factor();
        case '/':
            return x / factor();
        default:
            ist.putback(c);return x;
    }
}
float expr()
{
    float x = factor();
    char c = ist.get();
    switch(c)
    {
        case '+':
            return x + expr();
        case '-':
            return x - expr();
        default:
            ist.putback(c);return x;
    }
}
int wmain(void)
{
    setlocale(LC_ALL, "RU");
    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;
    //----------------------
    // Initialize Winsock.
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup failed with error: %ld\n", iResult);
        return 1;
    }
    //----------------------
    // Create a SOCKET for listening for
    // incoming connection requests.
    SOCKET ListenSocket;
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port for the socket that is being bound.
    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = INADDR_ANY;
    service.sin_port = htons(27015);
 
    if (bind(ListenSocket,(SOCKADDR *) & service, sizeof (service)) == SOCKET_ERROR) {
        wprintf(L"bind failed with error: %ld\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    //----------------------
    // Listen for incoming connection requests.
    // on the created socket
    if (listen(ListenSocket, 1) == SOCKET_ERROR) {
        wprintf(L"listen failed with error: %ld\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    //----------------------
    // Create a SOCKET for accepting incoming requests.
    SOCKET AcceptSocket;
    wprintf(L"Waiting for client to connect...\n");
 
    //----------------------
    // Accept the connection.
    
 
 
    while(1)
    {
        AcceptSocket = accept(ListenSocket, NULL, NULL);
        if (AcceptSocket == INVALID_SOCKET) {
            wprintf(L"accept failed with error: %ld\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        } else
        wprintf(L"Client connected.\n");
    
        iResult = recv(AcceptSocket, recvbuf, recvbuflen, 0);
 
        float r;
        r = expr();
        cout << "Полученно выражение: " << r;
 
 
    }
    // No longer need server socket
    closesocket(ListenSocket);
 
    WSACleanup();
    return 0;
}

Все, что у меня есть на данные момент по 2-й задаче. Выражение на сервере принимаю, а вот как запустить обработку его через expr - не знаю.
0
10.01.2016, 21:36

Не по теме:

Цитата Сообщение от Fighter215 Посмотреть сообщение
не все гонятся за вознаграждением. Люди уже ни раз помогали за спасибо. Тем более, что данная задача вроде не из сложных
За спасибо люди предпочтут заняться чем-то поинтереснее.
Форум предназначен, чтобы одни люди учились у других,
это не какой-то облачный сервис по выдаче готовых решений.

Тем более, судя по твоим старым постам, ты уже должен уметь работать с сокетами с далекого 2013 года.
Ты вроде бы должен знать Си, а для решения этой задачи чего-то особенного не требуется.
Для работы с потоками есть куча примеров на этом форуме, воспользуйся поиском.
Расчет мат выражения за тебя уже поискал GoldenSpice.
Так что у тебя уже все есть. А на объяснение этого я потратил даже больше времени, чем необходимо для решения твоих двух задач =/

0
0 / 0 / 0
Регистрация: 25.12.2012
Сообщений: 50
10.01.2016, 21:41  [ТС]
nonedark2008, для тебя это просто, для меня - нет.
Я уже говорил, что этот самый расчет я не могу впихнуть в сервер, т.к. не понимаю как это сделать. В расчетах идет считывание через cin.get, я же имею полученную строку c выражением в переменной recvbuf. У вас есть время на обсуждение данной темы (на которое вы по вашем же словам потратили больше времени, чем надо на решение 2 задач) и просмотр моего профиля, но нет времени помочь в решении данных задач.
PS: Не все способны учиться на теории, иногда нужно увидеть практическое решение, дабы научиться решать подобное.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
10.01.2016, 21:41
Цитата Сообщение от Fighter215 Посмотреть сообщение
Люди уже ни раз помогали за спасибо
Да правильно вы говорите, - Зачем им время или деньги? Но помощь ведь это содействие в действии и поэтому, в ответ на:
Цитата Сообщение от Fighter215 Посмотреть сообщение
не все гонятся за вознаграждением
несмотря на то, что не все гонятся за вознаграждением, но не все и хотят помочь тем кто гонится за шарой.
Тут же программисты == умные люди. Это значит, что на понт не разведёшь. Поэтому и:
Цитата Сообщение от Fighter215 Посмотреть сообщение
up!
nonedark2008, помог ведь. Это же нужно и время и желание, действительно, помочь, чтобы так хорошо написать. И что? Глядя на вашу реакцию, боюсь вряд ли кто и захочет ещё.
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
10.01.2016, 21:44
Лучший ответ Сообщение было отмечено Fighter215 как решение

Решение

Цитата Сообщение от Fighter215 Посмотреть сообщение
а вот как запустить обработку его через expr - не знаю.
У тебя есть поток ввода istringstream ist;
Тебе нужно в него впихнуть полученную строку, например ist = istringstream(recvbuf);
Далее идет твое r = expr();.
После этого полученный результат нужно отправить обратно.
Переменная r занимает sizeof(float) байт, отправляешь их через send обратно клиенту.
Клиент получает массив sizeof(float) байт и преобразует его обратно во float любым способом.
1
0 / 0 / 0
Регистрация: 25.12.2012
Сообщений: 50
10.01.2016, 21:50  [ТС]
nonedark2008, огромное спасибо вам. Теперь одной проблемой меньше.
PS: там ещё была одна опечатка, где вместо ist использовался cin. Теперь все работает.
Но с 1-й задачей всё равно не до конца понимаю. Имя данный код, как запихнуть функцию в поток.
Кликните здесь для просмотра всего текста
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
#include "stdafx.h"
#include <iostream>
#include <thread>
using namespace std;
 
float number();
float factor();
float expr();
 
int main(void)
{
    float r;
    cout << "Enter number:";
    r = expr();
    cout << endl << "Resault = " << r << "\n" ;
    system("pause");
}
 
 
float number()
{
    int res = 0;
 
    while(true)
    {
        char c = cin.get();
        if(c >= '0' && c <= '9')
        res = res * 10 + c - '0';
        else
        {
            cin.putback(c);
            break;
        }
    }
return res;
}
float factor()
{
    float x;
    char c = cin.get();
    if(c == '(')
       {
           x = expr();
           cin.get();
       }
       else
       {
           cin.putback(c);
           x = number();
       }
    c = cin.get();
    switch(c)
    {
        case '*':
            return x * factor();
        case '/':
            return x / factor();
        default:
            cin.putback(c);return x;
    }
}
float expr()
{
    float x = factor();
    char c = cin.get();
    switch(c)
    {
        case '+':
            return x + expr();
        case '-':
            return x - expr();
        default:
            cin.putback(c);return x;
    }
}
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
10.01.2016, 22:15
Fighter215, тут сложнее.
У тебя уже есть заголовок <thread>, правда он пойдет только для C++11.
Для потоков есть простое описание правда на англ,
думаю можно нагуглить что-то схожее на русском.
Можно создать отдельную функцию, которая будет принимать копию строки, создаст для нее istringstream, а затем вызовет функцию expr, в которую его передаст.
Чтобы не делать istringstream глобальным, передавай его по указателю во все функции expr, factor, number.
А сама программа, считав строку, создаст поток для "отдельной функции", в которую переедаст строку и указатель/ссылку на переменную, куда нужно положить результат. Запустив поток, нужно подождать его завершения, после чего вывести результат.
0
0 / 0 / 0
Регистрация: 25.12.2012
Сообщений: 50
10.01.2016, 22:55  [ТС]
nonedark2008, вот вроде как понял суть, но никак не могу понять, как это реализовать.
C++
1
2
std::thread first (expr);
first.join();
вот так я запущу поток, но вот с выводом результата expr я не могу понять как это реализовать.

Если я сделаю процедуру
C++
1
2
3
4
5
void  test(){
    float r;
    r = expr();
    cout << endl << "Resault = " << r << "\n" ;
}
и запущу её в потоке, это же вроде как не будет соответствовать условию
рекурсивная функция оформляется в виде потока
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
10.01.2016, 23:03
Цитата Сообщение от Fighter215 Посмотреть сообщение
это же вроде как не будет соответствовать условию
Как-то будет, но желательно избавиться от cout'ов в потоках.
Можно сделать так:
C++
1
2
3
void  test(float &res){
    res = expr();
}
А затем:
C++
1
2
3
4
float res;
std::thread first (test, std::ref(res));
first.join();
cout << res << endl;
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.01.2016, 23:03
Помогаю со студенческими работами здесь

Вычисление математического ожидания оформить в виде процедуры
Вычисление математического ожидания оформить в виде процедуры!!!!!!!!!!!!

C(n,m)=n!/m! . Вычисление факториалов числа оформить как рекурсивную функцию
Составьте программу вычисления числа сочетаний по формуле: C(n,m)=n!/m! . Вычисление факториалов числа оформить как рекурсивную функцию.

Вычисление факториалов числа оформить как рекурсивную функцию
Составьте программу вычисления числа сочетаний по формуле C(n,m)= n!/m! . Вычисление факториалов числа оформить как рекурсивную функцию.

Вычисление факториалов числа оформить как рекурсивную функцию.
1. Составьте программу вычисления числа сочетаний по формуле: C(n,m)= n!/m! . Вычисление факториалов числа оформить как рекурсивную...

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


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru