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

Перехват потоков ввода/вывода - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 25, средняя оценка - 4.80
LVV
56 / 56 / 3
Регистрация: 15.02.2010
Сообщений: 239
23.02.2013, 15:42     Перехват потоков ввода/вывода #1
Проблема в следующем:
Имеется консольное приложение, например такое:
C++
1
2
3
4
5
6
7
8
9
10
11
//1.exe
#include <iostream>
using namespace std;
int main() 
{ 
int a,b;
cin >> a >> b;
 
cout << a+b;
return 0;
}
или такое:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//1.exe
#include <fstream>
using namespace std;
int main() 
{ 
int a,b;
    ifstream f1("1.in");
    f1 >> a >> b;
    f1.close();
 
    ofstream f2("1.out");
    f2 << a + b;
    f2.close();
return 0;
}
Запускается exe-шник другим приложением, например так:
C++
1
2
3
4
5
6
7
8
//z.exe
#include <cstdlib>
using namespace std;
int main() 
{ 
    system ("start 1.exe");
return 0;
}
Вопрос: как перехватить потоки ввода/вывода, чтобы задавать исходные данные и считывать результат родительским файлом.
Например, так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//z.exe
#include <cstdlib>
using namespace std;
int main() 
{ 
int a,b,c;
a=2;
b=3;
????("1.exe") << a << b;
c << ????("1.exe");
return 0;
}
 
//это чушь полная, просто для иллюстрации вопроса
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
23.02.2013, 15:47     Перехват потоков ввода/вывода #2
гуглите пайпы
popen: win, lin
LVV
56 / 56 / 3
Регистрация: 15.02.2010
Сообщений: 239
23.02.2013, 15:58  [ТС]     Перехват потоков ввода/вывода #3
Гуглил. Но всё неконкретно...
C++
1
2
3
4
5
6
7
8
FILE *_popen(
   const char *command,
   const char *mode 
);
FILE *_wpopen(
   const wchar_t *command,
   const wchar_t *mode 
);
Какие библиотеки подключать, как всё это выглядит, применительно к моему конкретному случаю... ???
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
23.02.2013, 16:02     Перехват потоков ввода/вывода #4
Цитата Сообщение от LVV Посмотреть сообщение
Какие библиотеки подключать
в табличке requirements на мсдн
Цитата Сообщение от LVV Посмотреть сообщение
как всё это выглядит, применительно к моему конкретному случаю... ???
гуглите, разбирайтесь, пишите
LVV
56 / 56 / 3
Регистрация: 15.02.2010
Сообщений: 239
24.02.2013, 01:08  [ТС]     Перехват потоков ввода/вывода #5
Ну, для файла, типа:
C++
1
2
3
4
5
6
7
8
//1.exe
#include <iostream>
using namespace std;
int main()
{
сout<< "Hello World!";
return 0;
}
перехват потока вывода можно осуществить так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <string>
using namespace std;
int main()
{
   char   b[128];
   FILE   *p;
 
   p=_popen( "1.exe", "rt" );
 
string s;
while(fgets(b, 128, p))
{
  s+= b;
}
cout << s;
 
return 0;
}
Но как сделать то же самое для потока вівода в текстовій файл???
И как сделать перехват потока ввода?
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,570
Записей в блоге: 17
24.02.2013, 04:57     Перехват потоков ввода/вывода #6
Пример Из консоли в Memo правда для Builder но думаю не проблема понять суть...
Байт
 Аватар для Байт
13951 / 8782 / 1221
Регистрация: 24.12.2010
Сообщений: 15,891
24.02.2013, 09:09     Перехват потоков ввода/вывода #7
C
1
2
system ("start 1.exe >x.txt");
 // Далее все читаешь из x.txt }
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.02.2013, 19:59     Перехват потоков ввода/вывода
Еще ссылки по теме:

C++ Как сделать правильный перехват ввода?
C++ Перенаправление файловых потоков, перехват системных вызовов
C++ Итераторы: зачем используется оператор инкремента для потоков вывода?

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

Или воспользуйтесь поиском по форуму:
LVV
56 / 56 / 3
Регистрация: 15.02.2010
Сообщений: 239
24.02.2013, 19:59  [ТС]     Перехват потоков ввода/вывода #8
Цитата Сообщение от Байт Посмотреть сообщение
C
1
2
system ("start 1.exe >x.txt");
 // Далее все читаешь из x.txt }
Спасибо, но не то.
Предположим, у меня файл 1.ехе читает данные из одного текстового файла и выводит результаты в другой текстовы файл.
Например, так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//1.exe
#include <fstream>
using namespace std;
int main() 
{ 
int a,b;
    ifstream f1("1.in");
    f1 >> a >> b;
    f1.close();
 
    ofstream f2("1.out");
    f2 << a + b;
    f2.close();
return 0;
}
Мне нужно перехватить эти потоки, чтобы не было обращения к жесткому диску, чтобы данные задавала другая (родительская) программа и результат получала она же.

Для стандартного ввода-вывода я нашел примерчик: http://www.sources.ru/cpp/using_anonymous_pipes.shtml
Чуть подправил, всё заработало.
Вот этот код:
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <string>
#include <iostream>
#pragma hdrstop
//#include <condefs.h>
#define bzero(a) memset(a,0,sizeof(a)) //для сокращения писанины
using namespace std;
 
bool IsWinNT(void);  //проверка запуска под NT
void ErrorMessage(char *);  //вывод подробной информации об ошибке
 
 
 
//----------------------------------------------------------------------
 
void main()
 
{
 
  char buf[1024];           //буфер ввода/вывода
 
  char bufin[5]={'2',' ','4',13};           //буфер ввода
  //cout << bufin;
 
  STARTUPINFO si;
  SECURITY_ATTRIBUTES sa;
  SECURITY_DESCRIPTOR sd;        //структура security для пайпов
  PROCESS_INFORMATION pi;
 
  HANDLE newstdin,newstdout,read_stdout,write_stdin;  //дескрипторы
                                                      // пайпов
 
 
  if (IsWinNT())        //инициализация security для Windows NT
  {
    InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, true, NULL, false);
    sa.lpSecurityDescriptor = &sd;
  }
 
  else sa.lpSecurityDescriptor = NULL;
 
  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  sa.bInheritHandle = true;       //разрешаем наследование дескрипторов
 
 
   if (!CreatePipe(&newstdin,&write_stdin,&sa,0))   //создаем пайп
                                                   // для stdin
  {
    ErrorMessage("CreatePipe");
    getch();
    return;
  }
 
  if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) //создаем пайп
                                                  // для stdout
  {
    ErrorMessage("CreatePipe");
    getch();
    CloseHandle(newstdin);
    CloseHandle(write_stdin);
    return;
  }
 
 
 
  GetStartupInfo(&si);      //создаем startupinfo для
                            // дочернего процесса
 
  
  //Параметр dwFlags сообщает функции CreateProcess
  //как именно надо создать процесс.
 
  //STARTF_USESTDHANDLES управляет полями hStd*.
  //STARTF_USESHOWWINDOW управляет полем wShowWindow.
 
  si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_HIDE;
  si.hStdOutput = newstdout;
  si.hStdError = newstdout;   //подменяем дескрипторы для
  si.hStdInput = newstdin;    // дочернего процесса
 
      LPCWSTR app_spawn = L"1.exe";  // пример,
                                                     //замените на то,
                                                     // что вам нужно
 
 
 
  //создаем дочерний процесс
 
  if (!CreateProcess(app_spawn,NULL,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
                     NULL,NULL,&si,&pi))
  {
    ErrorMessage("CreateProcess");
  getch();
    CloseHandle(newstdin);
    CloseHandle(newstdout);
    CloseHandle(read_stdout);
    CloseHandle(write_stdin);
    return;
  }
 
 
 
  unsigned long exit=0;  //код завершения процесса
  unsigned long bread;   //кол-во прочитанных байт
  unsigned long avail;   //кол-во доступных байт
 
 
 
  bzero(buf);
 
  for(;;)      //основной цикл программы
  {
    GetExitCodeProcess(pi.hProcess,&exit); //пока дочерний процесс
                                            // не закрыт
    if (exit != STILL_ACTIVE)
      break;
    PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);
 
    //Проверяем, есть ли данные для чтения в stdout
 
    if (bread != 0)
    {
      bzero(buf);
      if (avail > 1023)
      {
        while (bread >= 1023)
        {
          ReadFile(read_stdout,buf,1023,&bread,NULL);  //читаем из
                                                       // пайпа stdout
          printf("%s",buf);
          bzero(buf);
        }
      }
 
      else {
        ReadFile(read_stdout,buf,1023,&bread,NULL);
        printf("%s",buf);
      }
    }
 
 
    if (kbhit())      //проверяем, введено ли что-нибудь с клавиатуры
        //ф-я kbhit() возвращает истину, если в момент ее вызова нажата клавиша.
    {
      bzero(buf);//обнуляем buf
      *buf = (char)getche();
      
      //printf("%c",*buf);
 
      WriteFile(write_stdin,buf,1,&bread,NULL); //отправляем это в stdin
      
      if (*buf == '\r')//если возврат каретки
      {
         *buf = '\n';
        {
        printf("%c",*buf);
        WriteFile(write_stdin,buf,1,&bread,NULL); //формирум конец
                                                  //строки, если нужно
 
      }
    }
    //cout << bufin<< endl;
    //WriteFile(write_stdin,bufin,1,&bread,NULL);
}
  }
 
  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);
  CloseHandle(newstdin);            //небольшая уборка за собой
  CloseHandle(newstdout);
  CloseHandle(read_stdout);
  CloseHandle(write_stdin);
}
 
//----------------------------EOF-----------------------------------
 
//------------------------------------------------------------------
 
bool IsWinNT(void)  //проверка запуска под NT
{
  OSVERSIONINFO osv;
  osv.dwOSVersionInfoSize = sizeof(osv);
  GetVersionEx(&osv);
  return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
 
void ErrorMessage(char *str)  //вывод подробной информации об ошибке
{
 
  LPVOID msg;
 
  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // язык по умолчанию
    (LPTSTR) &msg,
    0,
    NULL
  );
 
  printf("%s: %s\n",str,msg);
  LocalFree(msg);
 
}
Помогите, кто разбирается. Здесь работает перехват потоков ввода/вывода дочерней программы 1.ехе, но в родительской программе ввод данных осуществляется с клавиатуры, а мне нужно, чтобы данные были определены в переменных (массиве).
Где и что тут "подшаманить", если, например, точно известно, что вводить нужно два значения.
Ясно, что нужно менять строки 146-160. Но как?
Yandex
Объявления
24.02.2013, 19:59     Перехват потоков ввода/вывода
Ответ Создать тему
Опции темы

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