What I want to do is to output the text when there is a certain sentence and give it a specific time interval so that it is output as if typing.
This was handled by using the Sleep() function when printing a string.
However, when the space bar (or any key) is pressed while a sentence is being printed, I want the remaining sentences to be output at once without a time delay.
Because there are people who want to read text quickly.
(I'm making a text-based game.)
And from the next sentence, the string should be output with a time interval back to the original.
So, I wrote the code as below, but if I press the space bar once, all the sentences following it are printed at once without a time interval.
My guess is that once the spacebar is pressed, it works as if the spacebar is pressed continuously after that.
How can I solve this?
#include <stdio.h>
#include <Windows.h>
#include <conio.h>
#include <iostream>
using namespace std;
bool space;
void type(string str)
{
for (int i = 0; str[i] != '\0'; i++) {//Print until \0 appears
printf("%c", str[i]);
if (GetAsyncKeyState(VK_SPACE) & 0x8000) {//When the user presses the spacebar
space = true;//Turn AABSD into true
}
if (space) {//If the space bar is pressed
Sleep(0);//Print all the letters of a sentence without a break
}
else {//If the space bar is not pressed
Sleep(500);//Print at 0.5 second intervals per character
}
}
space = false;
}
int main(void)
{
space = false;
type("Hello, World!\n");
type("Hello, World!\n");
type("Hello, World!\n");
type("Hello, World!\n");
type("Hello, World!\n");
type("Hello, World!\n");
return 0;
}
At the end of type, you can loop until you see space being released:
void type(string str) {
...
while (space) {
space = (GetAsyncKeyState(VK_SPACE) & 0x8000);
Sleep(10);
}
}
Sleeping for 10 milliseconds at a time prevents pressing space from overheating your computer.
Related
The description of the problems:
I code a program that prints out some information frequently.
I want to input some commands during the program running.
std::out will flush out my input.
For examples:
>>> ./my_program
[sensorA] initial...ok
[sensorB] initial...ok
ge //!< I want to input 'get' here but the next output break it
[motorA] self-check...ok
t //!< break it into two spice
Expected:
>>> ./my_program
[sensorA] initial...ok
[sensorB] initial...ok
[motorA] self-check...ok
get //!< always fixed here whenever I input
Thanks a lot !
Appreciation
Firstly, I show my Great appreciation to Sam Varshavchik
Primary Result I found
Sam gave me the hints to use Curses Library. I read the doc and now finish the basic function.
My method is to create to sub-windows(output_win and input_win). User input show in input_win whereas program information print on output_win.
Let me share my code:
#include <iostream>
#include <string>
#include <curses.h>
#include <thread>
#include <atomic>
#include <chrono>
#include <unistd.h>
using namespace std;
WINDOW* win;
WINDOW* output_win;
WINDOW* input_win;
int row = 0, col = 0;
std::atomic<bool> flag(false);
string buf;
void ninit()
{
win = initscr();
getmaxyx(win, row, col);
cbreak();
noecho();
nonl();
intrflush(stdscr, FALSE);
keypad(stdscr, TRUE);
refresh();
}
void nprintf(string str)
{
touchwin(win);
str += '\n';
wprintw(output_win, str.c_str());
wrefresh(output_win);
}
void nprintf(const char* fmt, ...)
{
touchwin(win);
va_list ap;
va_start(ap, fmt);
vw_printw(output_win, fmt, ap);
va_end(ap);
wrefresh(output_win);
}
void nmonitor()
{
while(1)
{
char x = getch();
if(x != '\r')
{
touchwin(win);
buf += x;
waddch(input_win, x);
}
else
{
nprintf(buf);
touchwin(input_win);
flag = true;
wclear(input_win);
}
wrefresh(input_win);
}
}
string nget()
{
while(!flag)
usleep(100);
string cmd = buf;
flag = false;
buf = "";
return cmd;
}
////////////////////////////////
void print_thread()
{
while(1)
{
static int i = 0;
nprintf("no.%d\n", i++);
usleep(100000);
}
}
int main()
{
ninit();
fflush(stdin);
output_win = subwin(win, row - 1, col, 0, 0);
scrollok(output_win, true);
input_win = subwin(win, 1, col, row - 1, 0);
std::thread pthr(print_thread);
std::thread nthr(nmonitor);
string cmd;
while(1)
{
cmd = nget();
if(cmd == "quit")
break;
else
nprintf("[info] You input: %s\n", cmd.c_str());
}
getch();
endwin();
}
Environment Configure and Build
For Mac OSX:
brew install ncurses
For Ubuntu:
sudo apt-get install libcurses5-dev
To build:
g++ f04.cpp - f04 -lcurses # I try for 4 times so name it f04
Some bugs
Actually it has some bugs, here I found:
when you input backspace, it will not delete a char but show a special char;
after inputting enter, output_win sometimes show some strange words.
I am a beginner and may need help.
(Maybe I will solve them soon.)
May it can help others indeed.
You can try the following:
Before you print something, read from stdin everything the user
entered so far.
If there was something in stdin, print '\r' (so that the next output will overwrite the text entered by the user).
Print your output.
Print the text the user entered so far (but without '\n').
Please also see:
Rewinding std::cout to go back to the beginning of a line
So I've been trying to make a program that sends a string of keystrokes over to the currently open window and whenever I run the code, it doesn't send whatever I want it to send it sends something completely different(i.e sending bob comes up as 22 or 2/2)
#include <iostream>
#include <vector>
#include <Windows.h>
int SendKeys(const std::string &msg);
int main() {
Sleep(5);
while(true) {
Sleep(500);
SendKeys("iajsdasdkjahdjkasd");
}
std::cin.get();
return 0;
}
int SendKeys(const std::string & msg)
{
std::vector<INPUT> bob(msg.size());
for(unsigned int i = 0; i < msg.size(); ++i)
{
bob[i].type = INPUT_KEYBOARD;
bob[i].ki.wVk = msg[i];
std::cout << bob[i].ki.wVk << std::endl;
auto key = SendInput(1, &bob[i], sizeof(INPUT) /* *bob.size() */);
}
return 0;
}
(forgive the horrible formatting)
The virtual key codes does not generally correspond to the ASCII alphabet.
If you read e.g. this MSDN reference for virtual key-codes you will see that e.g. lower-case 'a' (which has ASCII value 0x61) corresponds to VK_NUMPAD1 which is the 1 key on the numeric keyboard.
The upper-case ASCII letters do correspond to the correct virtual key codes, so you need to make all letters upper-case when assigning to bob[i].ki.wVk. For all other symbols and characters you need to translate the character to the virtual key code.
I'm trying to run a C++ program I've been writing from my school's Unix Command-Line based server. The program is supposed to use commands like pipe() and fork() to calculate an integer in the child process and send it to the parent process through a pipe. The problem I've come across is when I try to run the program after compiling it, nothing happens at all except for a '0' is inserted before the prompt. I don't completely understand forking and piping so I'll post the entire program in case the problem is in my use of those commands. There are probably errors because I haven't been able to successfully run it yet. Here is my code:
#include <cstdlib>
#include <iostream>
#include <string>
#include <array>
#include <cmath>
#include <unistd.h>
using namespace std;
// Return bool for whether an int is prime or not
bool primeChecker(int num)
{
bool prime = true;
for (int i = 2; i <= num / 2; ++i)
{
if (num%i == 0)
{
prime = false;
break;
}
}
return prime;
}
int main(int argc, char *argv[])
{
int *array;
array = new int[argc - 1]; // dynamically allocated array (size is number of parameters)
int fd[2];
int count = 0; // counts number of primes already found
int num = 1; // sent to primeChecker
int k = 1; // index for argv
int addRes = 0;
// Creates a pair of file descriptors (int that represents a file), pointing to a pipe inode,
// and places them in the array pointed to. fd[0] is for reading, fd[1] is for writing
pipe(fd);
while (k < argc)
{
if (primeChecker(num)) // if the current number is prime,
{
count++; // increment the prime number count
if (count == (stoi(argv[k]))) // if the count reaches one of the arguments...
{
array[k - 1] = num; // store prime number
k++; // increment the array of arguments
}
}
num++;
}
pid_t pid;
pid = fork();
if (pid < 0) // Error occurred
{
cout << "Fork failed.";
return 0;
}
else if(pid == 0) // Child process
{
for (int i = 0; i < (argc-1); i++)
{
// Close read descriptor (not used)
close(fd[0]);
// Write data
write(fd[1], &addRes, sizeof(addRes)); /* write(fd, writebuffer, max write lvl) */
// Close write descriptor
close(fd[1]);
}
}
else // Parent process
{
// Wait for child to finish
wait(0);
// Close write descriptor (not used)
close(fd[1]);
// Read data
read(fd[0], &addRes, sizeof(addRes));
cout << addRes;
// Close read descriptor
close(fd[0]);
}
return 0;
}
Here is what I'm seeing in the command window (including the prompt) when I try to compile and run my program:
~/cs3270j/Prog2$ g++ -o prog2.exe prog2.cpp
~/cs3270j/Prog2$ ./prog2.exe
0~/cs3270j/Prog2$
and nothing happens. I've tried different naming variations as well as running it from 'a.out' with no success.
tl;dr after compiling and attempting to execute my program, the Unix command prompt simply adds a 0 to the beginning of the prompt and does nothing else.
Any help that anybody could give me would be very much appreciated as I can't find any information whatsoever about a '0' appearing before the prompt.
Your program is doing exactly what you're telling it to do! You feed addRes into the pipe, and then print it out. addRes is initialized to 0 and never changed. In your child, you want to pass num instead. Also, you may want to print out a new line as well ('\n').
You never write anything to the pipe; writing is once per each command line argument, and ./prog2.exe does not supply any, so the loop never executes
If you passed one argument, you would write addRes; you never change addRes, so you'd get 0 in the parent
If you passed multiple arguments, you'd write one addRes then close the channel. This is not too bad since you never read more than one addRes anyway.
You print out your addRes (which is unchanged from its initialisation int addRes = 0) without a newline, which makes the next prompt stick right next to it (using cout << addRes << endl would print out a newline, making it prettier)
Is there any function that can wait for input until a certain time is reached? I'm making kind of Snake game.
My platform is Windows.
For terminal based games you should take a look at ncurses.
int ch;
nodelay(stdscr, TRUE);
for (;;) {
if ((ch = getch()) == ERR) {
/* user hasn't responded
...
*/
}
else {
/* user has pressed a key ch
...
*/
}
}
Edit:
See also Is ncurses available for windows?
I found a solution using kbhit() function of conio.h as follows :-
int waitSecond =10; /// number of second to wait for user input.
while(1)
{
if(kbhit())
{
char c=getch();
break;
}
sleep(1000); sleep for 1 sec ;
--waitSecond;
if(waitSecond==0) // wait complete.
break;
}
Try with bioskey(), this is an example for that:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <bios.h>
#include <ctype.h>
#define F1_Key 0x3b00
#define F2_Key 0x3c00
int handle_keyevents(){
int key = bioskey(0);
if (isalnum(key & 0xFF)){
printf("'%c' key pressed\n", key);
return 0;
}
switch(key){
case F1_Key:
printf("F1 Key Pressed");
break;
case F2_Key:
printf("F2 Key Pressed");
break;
default:
printf("%#02x\n", key);
break;
}
printf("\n");
return 0;
}
void main(){
int key;
printf("Press F10 key to Quit\n");
while(1){
key = bioskey(1);
if(key > 0){
if(handle_keyevents() < 0)
break;
}
}
}
Based on #birubisht answer I made a function which is a bit cleaner and uses NON-deprecated versions of kbhit() and getch() - ISO C++'s _kbhit() and _getch().
Function takes: number of seconds to wait for user input
Function returns: _ when user does not put any char, otherwise it returns the inputed char.
/**
* Gets: number of seconds to wait for user input
* Returns: '_' if there was no input, otherwise returns the char inputed
**/
char waitForCharInput( int seconds ){
char c = '_'; //default return
while( seconds != 0 ) {
if( _kbhit() ) { //if there is a key in keyboard buffer
c = _getch(); //get the char
break; //we got char! No need to wait anymore...
}
Sleep(1000); //one second sleep
--seconds; //countdown a second
}
return c;
}
How can I do so that I can display star(*) instead of plain text for password in C++.
I am asking for password and it is plain pass on the screen.
How can I convert them in to star(*) so that user can not see the password while entering.
This is what I have currently
char pass[10]={"test"};
char pass1[10];
textmode(C40);
label:
gotoxy(10,10);
textcolor(3);
cprintf("Enter password :: ");
textcolor(15);
gets(pass1);
gotoxy(10,11);
delay(3000);
if(!(strcmp(pass,pass1)==0))
{
gotoxy(20,19);
textcolor(5);
cprintf("Invalid password");
getch();
clrscr();
goto label;
}
Thanks
You need to use an unbuffered input function, like getch () provided by curses library, or a console library of your OS. Calling this function will return the pressed key character, but will not echo. You can manually print * after you read each character with getch (). Also you need to write code if backspace is pressed, and appropriately correct the inserted password.
Here is a code which once i wrote with the curses. Compile with gcc file.c -o pass_prog -lcurses
#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#define ENOUGH_SIZE 256
#define ECHO_ON 1
#define ECHO_OFF 0
#define BACK_SPACE 127
char *my_getpass (int echo_state);
int main (void)
{
char *pass;
initscr ();
printw ("Enter Password: ");
pass = my_getpass (ECHO_ON);
printw ("\nEntered Password: %s", pass);
refresh ();
getch ();
endwin ();
return 0;
}
char *my_getpass (int echo_state)
{
char *pass, c;
int i=0;
pass = malloc (sizeof (char) * ENOUGH_SIZE);
if (pass == NULL)
{
perror ("Exit");
exit (1);
}
cbreak ();
noecho ();
while ((c=getch()) != '\n')
{
if (c == BACK_SPACE)
{
/* Do not let the buffer underflow */
if (i > 0)
{
i--;
if (echo_state == ECHO_ON)
printw ("\b \b");
}
}
else if (c == '\t')
; /* Ignore tabs */
else
{
pass[i] = c;
i = (i >= ENOUGH_SIZE) ? ENOUGH_SIZE - 1 : i+1;
if (echo_state == ECHO_ON)
printw ("*");
}
}
echo ();
nocbreak ();
/* Terminate the password string with NUL */
pass[i] = '\0';
endwin ();
return pass;
}
There's nothing in C++ per se to support this. The functions in your example code suggest that you are using curses, or something similar; if so, check the cbreak and nocbreak functions. Once you've called cbreak, it's up to you to echo the characters, and you can echo whatever you like (or nothing, if you prefer).
#include<iostream.h>
#include<conio.h>
#include<stdio.h>
void main()
{
clrscr();
char a[10];
for(int i=0;i<10;i++)
{
a[i]=getch(); //for taking a char. in array-'a' at i'th place
if(a[i]==13) //cheking if user press's enter
break; //breaking the loop if enter is pressed
printf("*"); //as there is no char. on screen we print '*'
}
a[i]='\0'; //inserting null char. at the end
cout<<endl;
for(i=0;a[i]!='\0';i++) //printing array on the screen
cout<<a[i];
sleep(3); //paused program for 3 second
}