Помогите разобраться с функцией GetAsyncKeyState()
Мне надо прописать каким-то образом в условии, что кнопка была до этого нажата и в данный момент нажата - тогда делать то. И что кнопка была не нажата и в данный момент нажата - тогда делать сё.
Данная программа открывает бесконечный цикл из первых эн чисел последовательности Фибоначчи и гоняет эту последовательность по кругу до тех пор пока пользователь не нажмёт клавишу 0. Собственно сама клавиша принципиальна, нужна именно она, код её 0x30.
GetAsyncKeyState() определяет, нажата ли клавиша на момент вызова и была ли нажата клавиша после предыдущего вызова функции.
Некоторое описание функции есть тут help.prognoz.com/ru/mergedProjects/UiLib/interf... но оно не на Си.
Ещё тут есть на дэлфи vwsb.blogspot.ru/2008/10/api-delphi.html
И вот ещё по поиску нашлась книга букс.гугл.ру Программирование игр для Microsoft Windows. Советы профессионала, 2-е издание, про функцию

Но всё равно не пойму как с ней в данном случае работать...
p.s. не знаю почему не отобразились инклуды, подключал эстэдио, локейл и виндоус

Мне надо прописать каким-то образом в условии, что кнопка была до этого нажата и в данный момент нажата - тогда делать то. И что кнопка была не нажата и в данный момент нажата - тогда делать сё.
Данная программа открывает бесконечный цикл из первых эн чисел последовательности Фибоначчи и гоняет эту последовательность по кругу до тех пор пока пользователь не нажмёт клавишу 0. Собственно сама клавиша принципиальна, нужна именно она, код её 0x30.
GetAsyncKeyState() определяет, нажата ли клавиша на момент вызова и была ли нажата клавиша после предыдущего вызова функции.
Некоторое описание функции есть тут help.prognoz.com/ru/mergedProjects/UiLib/interf... но оно не на Си.
Ещё тут есть на дэлфи vwsb.blogspot.ru/2008/10/api-delphi.html
И вот ещё по поиску нашлась книга букс.гугл.ру Программирование игр для Microsoft Windows. Советы профессионала, 2-е издание, про функцию

Но всё равно не пойму как с ней в данном случае работать...
#include
#include
#include
int func1(int N){
if(N == 1) {
printf("0 \n");
}
else if(N == 2){
printf("0 \n");
printf("1 \n");
}
}
int func2(int a, int b, int c, int N) {
int i;
printf("0 \n");
printf("1 \n");
for(i = 0; i < N-2; ++i){
c=a+b;
a=b;
b=c;
printf("%d\n", c);
}
printf("\n");
}
int main() {
setlocale (LC_ALL, "Rus");
int a=0;
int b=1;
int c;
int N;
int i;
printf("Введите N=");
scanf("%d", &N);
while(2 > 1) {
func1(N);
func2(a,b,c,N);
if( тут надо условие с функцией GetAsyncKeyState(0x30) такое, что в результате его выполнения программа шла в тело
ифа тогда и только тогда, когда клавиша 0 была до этого момента нажата и в данный момент нажата) {
break;
}
if( тут надо условие с функцией GetAsyncKeyState(0x30) такое, что в результате выполнения программа шла в тело
ифа тогда и только тогда, когда клавиша 0 была до этого момента не нажата и в данный момент нажата) {
break;
}
}
}
p.s. не знаю почему не отобразились инклуды, подключал эстэдио, локейл и виндоус

Студия ошибку выдает или что?
Ссылка на MSDN, описана спецификация функции. Она возвращает значение типа short, которое можно анализировать. В вашем примере предлагают сделать побитовое И с битовой маской 0x8000. Не умеете пользоваться #define?
p.s. не знаю почему не отобразились инклуды
Потому что они в угловых скобках, которые парсер дайри пытается распознать как теги.
Есть же кнопка CODE... там всё должно отображаться...
Почитаю про битовые маски, впервые этот термин попался просто. Ещё один вопрос - а что за значение такое short? Мне доводилось лишь использовать short int i в цикле фора при работе с небольшими массивами, причем понимал это как короткое целое число, мол память не заполнять - целое число может принимать 2^32 значения (32 ячейки), а короткое в два раза меньше. То есть short - это по умолчанию и есть short int или что-то иное? В инете не нашел...
А пишу не в студии, а в дэвке - Dev-Cpp 5.11 TDM-GCC 4.9.2 Setup и компилирую этим Compiler Name: TDM-GCC 4.9.2 32-bit Debug и ради интереса этим Compiler Name: TDM-GCC 4.9.2 32-bit Release. Один раз заметил интересную штуку между ними и с того момента все программы смотрю то в одном, то в другом)
dixie_flatline, с previous_state и current_state понравилось, надо попробовать... А слово нажата чем заменить? 0 - нажата, 1 - не нажата или иначе?
В общем поэкспериментировать надо.
All_ex, надо запомнить) Я просто воспользовался советом, что в шапке сообщества Можно скопировать полученный там код вместе с подсветкой сюда (для этого его нужно выделить, скопировать исходный код выделенного фрагмента и поместить его в вашу запись с тегом
p.s. я с этой штукой полмесяца уж сижу, лабу сдавать надо, а так и не разобрался как с этим работать всем
Да, все верно.
выглядит так GetAsyncKeyState(0x30) & 0x8000, но что оно значит?
& — это побитовое И. Переведите оба числа в двоичную систему счисления и выполните операцию И побитово, т.е. для каждого бита отдельно. Получившееся в результате значение и будет результатом операции. В отличие от логического И (&&), где перед сравнением числовые значения приводятся к логическому типу (не ноль в true, ноль в false), а после этого выполняется операция.
например так GetAsyncKeyState(0x30) & 0x8000 == 0
Ну как-то так, да. Надо спецификацию уточнить, с чем именно сравнивать в смысле
битовые маски, впервые этот термин попался просто.
Они используются в операционных системах семейства UNIX, например, для задания прав доступа к файлу. Поскольку язык С изначально был задуман как системный для юникса, в нем такой способ получения результата довольно популярен. Получается очень экономно, на целую кучу вариантов расходуется только один байт.
Ещё один вопрос - а что за значение такое short
Краткое название short int.
целое число может принимать 2^32 значения (32 ячейки)
Чаще всего да, но в стандарте языка размер типа int не указан. Он зависит от компилятора, поэтому для лучшей переносимости программ, когда размер типа критичен (как в этой задаче), рекомендуется использовать более строго заданные типы short и long. Про типы можете здесь почитать, но это для студии только.
Побитовое И — это бинарная операция, действие которой эквивалентно применению логического И к каждой паре битов, которые стоят на одинаковых позициях в двоичных представлениях операндов. Другими словами, если оба соответствующих бита операндов равны 1, результирующий двоичный разряд равен 1; если же хотя бы один бит из пары равен 0, результирующий двоичный разряд равен 0.
Если я вызвал гетасинк и впервые нажимаю 0, то получаю в соответствии если старший значащий бит установлен, клавиша находится в нажатом состоянии
1 xxxxx xxxxx xxxx0 & 1 00000 00000 00000 = 1 aaaaa aaaaa aaaa0
Если я вызвал второй раз гетасинк и опять нажал на 0, то в соответствии если старший значащий бит установлен, клавиша находится в нажатом состоянии, а если самый младший значащий бит установлен, клавиша была нажата после предыдущего вызова получим
1 xxxxx xxxxx xxxx1 & 1 00000 00000 00000 = 1 bbbbb bbbbb bbbb0.
И непонятно с чем сравнивать... А что самое отвратное, так ещё и старший и младший биты после данных операций одинаковые
То есть после указанных операций мы просто получим два каких то числа 1 aaaaa aaaaa aaaa0 и 1 bbbbb bbbbb bbbb0...
Вот код
То есть я ввожу что хочу, хоть 10, хоть 100 и цикл идёт бесконечно, а не однократно мол я 0 уже нажимал. Вроде работает и славно. Но писать надо дальше, мне надо потом всё это зациклить, чтоб после остановки нулём программа повторялась.
Делаю так, тут я код поправил малость, запихал весь счёт последовательности в одну функцию, тем самым при вводе 1, избавился от 0 0 1 и получил требуемый 0.
Но проблема в том, что перед тем как остановить всё это дело, то есть во время работы бесконечного цикла пользователь может нажимать что попало, и вот это всё потом выводится. Скажем если бы цикл останавливался не нулём, а скажем двойкой, то после остановки двойка автоматически будет вводится, и если потом введём например 5, он будет считать первые 25 чисел. А мне вот эти все автоматически закинутые символы вовсе не нужны, более того в результате непонимания как это всё работает, я не могу даже найти инструкцию в результате которой это всё происходит - то ли сканэф это, то ли гетасинк. Как убрать этот поток тоже не знаю, никогда с таким не сталкивался. Откуда и мысль, что если всё нормально сделать ручками, может нормально и будет...
Вот что на выходе
Возвращаемые значения:
0 - клавиша не нажата и не была нажата при предыдущем вызове этой функции.
1 - не нажата, но была нажата в прошлый вызов.
-32767 - нажата, но не была нажата в прошлый вызов.
-32768 - нажата, и была нажата в прошлый вызов.
Написал
И всё та же ерундень! Почему она пишет то, что нажал, если функция должна срабатывать лишь на состояние клавиши, что в её аргументе. И до сканэфа там далеко, перед ним же принтэф отрабатывается, а цикл тормозится до инструкции принтэф. Как-нибудь можно убирать весь этот поток нажимаемых клавиш в попытках остановить цикл, почитстить как-нибудь его или сразу как-то прописать, что вот это вся информация нам не нужна ?
Ну так добавьте в условие проверки нажатия клавиши еще и чтение в какую-нибудь левую переменную. Перед брейком.
Вот пишут, что она делает две операции.
1) Старший бит возвращаемого значения установлен в 1, если указанная клавиша была нажата в момент вызова функции. Если этот бит равен 0, клавиша не была нажата.
2) Младший бит возвращаемого значения установлен в 1, если указанная клавиша была нажата с момента последнего вызова функции GetAsyncKeyState.
Проверяю её работу на этой программке
Функция GetAsyncKeyState вызывается нажатием клавиш как понимаю.
Допустим вначале нажал 1 (0 xxxxx xxxxx xxxx0), затем 0 (1 xxxxx xxxxx xxxx1) и 5 (0 xxxxx xxxxx xxxx0), то есть на экране "Введите N=205" и фактически произошло три вызова функции GetAsyncKeyState. Нажимаю Enter, получаю бесконечный цикл, таким образом в условие if не заходим, таким образом значение 0 xxxxx xxxxx xxxx0 = 0 00000 00000 00000 = 0 (т.е. x=0). Так как надо зайти в if чтобы остановить цикл, вызываю в четвёртый раз функцию GetAsyncKeyState, нажимая на 0 (1 xxxxx xxxxx xxxx1), и цикл останавливается, так как очевидно, что число 1 xxxxx xxxxx xxxx1 отлично от 0 00000 00000 00000 = 0 нуля.
Если же по новой перезапустить программу и сразу ввести 10, то есть вначале нажал 1 (0 xxxxx xxxxx xxxx0), затем 0 (1 xxxxx xxxxx xxxx1), то сразу уходим в цикл.
Таким образом фактически получаем, что функция GetAsyncKeyState может возвращать только три числа - 0 xxxxx xxxxx xxxx0, 1 xxxxx xxxxx xxxx1 и если сразу бы ввели 0, то получили бы 1 xxxxx xxxxx xxxx0. Применяя битовые операции к этим возвращаемым значениям и сравнивая с тем или иным числом мы и будем задавать условия.
Например для бесконечного вывода и остановки можно использовать "побитовое и" GetAsyncKeyState(0x30) & 0x8000 !=0. Но если поставить это условие if(GetAsyncKeyState(0x30) & 0x8000) и ввести 10 (1 xxxxx xxxxx xxxx1 & 1 00000 00000 00000 = 1 00000 00000 00000 = 32768), то программа не идёт в if. Что здесь не так?