Открыть сразу несколько окон консоли - C (СИ)
Формулировка задачи:
Нужно, чтобы программа запускалась, и открывала 2 окна консоли, в одном выводила "Hello, world", а в другом "Hello, user". Как такое организовать?
Решение задачи: «Открыть сразу несколько окон консоли»
textual
Листинг программы
#include <windows.h>
#include <string.h>
#include <stdio.h>
#define MAX_BUF 256
#define MAX_CONSOLE 2
static char* ptr_to_str(DWORD_PTR p, char* s);
static DWORD_PTR str_to_ptr(const char* s, int* e);
struct pipe {
HANDLE hin;
HANDLE hout;
};
BOOL pipe_connect(pipe* p, char* app);
void pipe_close(pipe* p);
BOOL pipe_write(const pipe* p, const char* s, DWORD n);
int main(void){
static struct pipe pipes[MAX_CONSOLE];
int i, k;
char s[MAX_BUF];
DWORD n;
//путь к клиенту
char path[MAX_PATH] = "client.exe";
//запуск консолей
for(i = 0; i < MAX_CONSOLE; ++i){
if(! pipe_connect(&pipes[i], path)){
fprintf(stderr, "error pipes[%d], pipe_connect\n", i);
return 1;
}
}
puts("\t\t\t\1\1\1 RUN SERVER");
//по переменке отправлять сообщение двум консолям
k = 0;
while(1){
printf("enter msg: ");
scanf("%255[^\n]", s);
fflush(stdin);
n = strlen(s) + 1;
if(n > 1){
//выход команда exit
if(! strcmp(s, "exit")){
for(i = 0; i < MAX_CONSOLE; ++i)
pipe_write(&pipes[i], s, n);
break;
}
//отправка k-консоле сообщение
if(! pipe_write(&pipes[k], s, n))
printf("error console[%d], pipe_write\n", k);
}
k ^= 1;
}
for(i = 0; i < MAX_CONSOLE; ++i)
pipe_close(&pipes[i]);
return 0;
}
//установка связи с клиентом
BOOL pipe_connect(pipe* p, char* app){
char path[MAX_PATH + 1], s[32];
SECURITY_ATTRIBUTES attr;
PROCESS_INFORMATION pi;
STARTUPINFOA si;
attr.nLength = sizeof(attr);
attr.bInheritHandle = TRUE;
attr.lpSecurityDescriptor = NULL;
if(! CreatePipe(&p->hin, &p->hout, &attr, MAX_BUF + 1))
return FALSE;
sprintf(path, "%s %s", app, ptr_to_str((DWORD_PTR)p->hin, s));
memset(&pi, 0, sizeof(pi));
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
if(! CreateProcessA(NULL, path, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
return FALSE;
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return TRUE;
}
//запись
BOOL pipe_write(const pipe* p, const char* s, DWORD n){
DWORD w = 0;
BOOL r = WriteFile(p->hout, s, n, &w, NULL);
return (r && (w == n));
}
//закрытие
void pipe_close(pipe* p){
if(p->hout != NULL)
CloseHandle(p->hout);
if(p->hin != NULL)
CloseHandle(p->hin);
p->hout = p->hin = NULL;
}
//преобразование целого числа в строку
static char* ptr_to_str(DWORD_PTR p, char* s){
char ds[32];
int j, i = 0;
char* t = s;
do {
ds[i++] = (char)(p % 10) + '0';
} while((p /= 10) != 0);
for(j = i - 1; j >= 0; --j)
*s++ = ds[j];
*s = '\0';
return t;
}
Объяснение кода листинга программы
- Переменные:
- path (путь к клиенту)
- s (строка для чтения пользовательского ввода)
- n (длина строки для чтения пользовательского ввода)
- k (переменная для выбора консоли для отправки сообщения)
- i (переменная для перебора консолей)
- ptr_to_str (статическая функция для преобразования целого числа в строку)
- pipe_connect (функция для установки связи с клиентом)
- pipe_write (функция для записи в консоль клиента)
- pipe_close (функция для закрытия соединения с клиентом)
- main (главная функция программы)
- Функция main выполняет следующие действия:
- Создает две переменные типа struct pipe для подключения к двум консолям
- Запускает две консоли с помощью функции pipe_connect
- Выводит сообщение
RUN SERVERпосле запуска двух консолей - В цикле запрашивает у пользователя ввод строки и отправляет её в выбранную консоль
- Закрывает все соединения с помощью функции pipe_close
- Функция pipe_connect выполняет следующие действия:
- Создает два дескриптора файла для чтения и записи из/в консоль клиента
- Создает процесс для запуска клиента с помощью функции CreateProcessA
- Закрывает дескрипторы файлов, связанные с процессом клиента
- Возвращает TRUE, если процесс клиента успешно запущен
- Функция pipe_write выполняет следующие действия:
- Использует функцию WriteFile для записи строки в консоль клиента
- Возвращает TRUE, если запись прошла успешно и количество записанных байт соответствует указанному значению
- Функция ptr_to_str выполняет следующие действия:
- Преобразует целое число в строку, используя алгоритм деления на 10 и остатка от деления
- Возвращает указатель на начало строки
- Функция pipe_close выполняет следующие действия:
- Закрывает оба дескриптора файла, связанных с выбранной консолью
- Устанавливает оба указателя на NULL
- В цикле главного функционала программы пользователю предлагается ввести строку для отправки в выбранную консоль. Если введенная строка равна
exit, программа завершается. Если введенная строка не равнаexit, программа выбирает следующую консоль для отправки сообщения.