Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Qt и кроссплатформенное программирование С/С++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.10.2022, 09:50   #1
erslgoeirjh
Форумчанин
 
Регистрация: 19.05.2009
Сообщений: 153
По умолчанию Не работает scanf в консольном окне

Я работаю в Qt Creator 4.12.2 .
В моём диалоговом интерфейсном приложении я открыл консольное окно (средствами WinAPI, так как сделать это средствами Qt я не знаю):

Код:
::AllocConsole();
freopen("CONIN$","rt",stdin);
freopen("CONOUT$","wt",stdout);
freopen("CONOUT$","wt",stderr);
HANDLE  hStdin, hStdout, hStderr;
hStdin = GetStdHandle(STD_INPUT_HANDLE);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
hStderr = GetStdHandle(STD_ERROR_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO  csbiInfo;
GetConsoleScreeenBufferInfo(hStdout,&csbiInfo);
COORD  dwSize = csbiInfo.dwSize;
dwSize.Y = 9999;
SetConsoleScreenBufferSize(hStdin,dwSize);
SetConsoleScreenBufferSize(hStdout,dwSize);
SetConsoleScreenBufferSize(hStderr,dwSize);
В этом консольном окне осуществляется ввод-вывод текстовой информации.
И вот у меня код для ввода-вывода текстовой информации:

Код:
char  answer[2], alphaisequal[80];

sprintf(alphaisequal,"Коэффициент сходимости alpha равен %.5f . Хотите изменить (y/n)?\n\n",alphacoef);
printf("%s",alphaisequal);
printf(" ");
scanf("%s",answer);
Вывод текста работает, но вот почему-то не работает функция scanf — программа просто переходит дальше, не ожидая ввода этого значения.
Как исправить эту ошибку?

Последний раз редактировалось erslgoeirjh; 19.10.2022 в 14:27.
erslgoeirjh вне форума Ответить с цитированием
Старый 19.10.2022, 10:32   #2
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Если вы запускаете окно из консоли, тогда лучше использовать AttachConsole вместо AllocConsole.
А почему вы для stdout и stderr открываете CONIN$, а не CONOUT$?
Как вариант используйте API функцию ReadConsole вместо scanf - вы все равно считываете строку.
macomics вне форума Ответить с цитированием
Старый 19.10.2022, 14:28   #3
erslgoeirjh
Форумчанин
 
Регистрация: 19.05.2009
Сообщений: 153
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
А почему вы для stdout и stderr открываете CONIN$, а не CONOUT$?
Извиняюсь, описка.
erslgoeirjh вне форума Ответить с цитированием
Старый 19.10.2022, 16:17   #4
erslgoeirjh
Форумчанин
 
Регистрация: 19.05.2009
Сообщений: 153
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
Как вариант используйте API функцию ReadConsole вместо scanf - вы все равно считываете строку.
Функция ReadConsole работает:

Код:
TCHAR  wanswer[4];
DWORD  dwCount = 0;
//...
HANDLE  hStdin = GetStdHandle(STD_INPUT_HANDLE);
//...
ReadConsole(hStdin,&wanswer,wcslen(wanswer),&dwCount,NULL);
В результате чего считывается строка wanswer типа TCHAR.

Весь вопрос--как преобразовать эту строку wanswer типа TCHAR в строку s типа char* ?
erslgoeirjh вне форума Ответить с цитированием
Старый 20.10.2022, 07:56   #5
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 980
По умолчанию

erslgoeirjh, лучше, конечно, сделать проект юникодным (utf16), и явно вызывать
ReadConsoleW,
использовать wchar_t, std::wstring

но если сильно надо конвертить, велкам WideCharToMultiByte

TCHAR - это не тип, если что, это макрос
Алексей1153 вне форума Ответить с цитированием
Старый 20.10.2022, 15:33   #6
erslgoeirjh
Форумчанин
 
Регистрация: 19.05.2009
Сообщений: 153
По умолчанию

Цитата:
Сообщение от Алексей1153 Посмотреть сообщение
но если сильно надо конвертить, велкам WideCharToMultiByte
Я написал:

Код:
TCHAR  wanswer[4];
char  answer[10];
DWORD  dwCount = 3;

//...

ReadConsole(hStdin,wanswer,wcslen(wanswer),&dwCount,NULL);
length = WideCHarToMultiByte(CP_ACP,0,wanswer,-1,0,0,0,0);
WideCharToMultiByte(CP_ACP,0,wanswer,-1,answer,length,0,0);
Там, где стоит ReadConsole, в консольном окне я ввожу n и нажимаю ввод (то есть у меня получается строка "n\n"). В результате чего в переменной answer после выполнения функции WideCharToMultiByte у меня не "n\n", а какая-то ерунда.

В чём причина этого? Как исправить эту ошибку?
erslgoeirjh вне форума Ответить с цитированием
Старый 20.10.2022, 20:34   #7
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 980
По умолчанию

Цитата:
Сообщение от erslgoeirjh Посмотреть сообщение
TCHAR wanswer[4];
не инициализирован

Цитата:
Сообщение от erslgoeirjh Посмотреть сообщение
wcslen(wanswer)
поэтому - неопределённое поведение

далее:
dwCount - тут будет количество введённых символов. Не нужно надеяться на завершающий нуль

если прочитать доку, то должно быть примерно так
(не тестировал!)

Код:
wchar_t  wanswer[4]{};
char  answer[std::size(wanswer)]{};

DWORD  dwCount{};
if(ReadConsoleW(hStdin, wanswer, std::size(wanswer), &dwCount, {}))
{
	auto sz = WideCharToMultiByte(CP_ACP, 0, wanswer, dwCount, 0     , 0 , 0, 0);
	/**/      WideCharToMultiByte(CP_ACP, 0, wanswer, dwCount, answer, sz, 0, 0);
	//также нужно докинуть нуль-терминатор
	*std::rbegin(answer)='\0';
}
Алексей1153 вне форума Ответить с цитированием
Старый 20.10.2022, 20:41   #8
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 980
По умолчанию

с STL чуток попроще
Код:
std::wstring W;
std::string  A;

DWORD dwCount{};
W.resize(4);
if(ReadConsoleW(hStdin, W.data(), W.size(), &dwCount, {}))
{
	W.resize(dwCount);
	auto     sz = WideCharToMultiByte(CP_ACP, 0, W.c_str(), W.size(), 0       , 0       , 0, 0);
	A.resize(sz); WideCharToMultiByte(CP_ACP, 0, W.c_str(), W.size(), A.data(), A.size(), 0, 0);
}

//A - результат
Алексей1153 вне форума Ответить с цитированием
Старый 25.10.2022, 10:33   #9
erslgoeirjh
Форумчанин
 
Регистрация: 19.05.2009
Сообщений: 153
По умолчанию

Я сделал следующим образом:

Код:
HANDLE  hStdin = CreateFileW(GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,nullptr,OPEN_EXISTING,0,nullptr);
DWORD  oldMode;
GetConsoleMode(hStdin,&oldMode);
SetConsoleMode(hStdin,oldMode|ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT);
//...
ReadConsoleW(hStdin,wanswer,sizeof(wanswer),&dwCount,NULL);
auto  sz = WideCharToMultiByte(CP_ACP,0,wanswer,dwCount,answer,sz,0,0);
answer[sz-2] = '\0';
В результате чтение данных из консольного окна работает.
erslgoeirjh вне форума Ответить с цитированием
Старый 25.10.2022, 10:39   #10
erslgoeirjh
Форумчанин
 
Регистрация: 19.05.2009
Сообщений: 153
По умолчанию

Чтение данных из консольного окна у меня работает.

Но как правильно выводить русский текст в консольном окне? А то я вывожу русский текст с помощью обычной функцией printf — и в результате чего у меня в консольном окне выводится абракадабра (при этом числа и латинский текст выводится нормально). Как исправить эту ошибку?
erslgoeirjh вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вопрос по выводам символов в консольном окне erslgoeirjh Visual C++ 7 24.05.2017 14:43
scanf cocacola Общие вопросы C/C++ 1 10.07.2014 05:09
Как сделать перенаправления пользователя в новом окне. windows.open не работает Rost93 JavaScript, Ajax 2 22.06.2012 19:04
Не правильно работает функция scanf() ichigo9911 Общие вопросы C/C++ 2 26.02.2012 21:57