How to get SDL to understand the difference between tapping a letter with caps lock on and caps lock off, or, shift + 'a' = 'A', or that shift + '1' = '!'...etc?
First add this command:
SDL_EnableUNICODE(SDL_ENABLE);
which basically allows SDL to recognise the difference between Uppercase and Lowercase and even the difference between holding Shiftand aa character (like shift + 'a' = 'A' or shift + '1' = '!')
After that , assuming you know how to extract regular keys (event.key.keysym.sym), just use event.key.keysym.unicode instead
For example:
#include <string>
#include <iostream>
using namespace std;
string stringinput()
{
string input;
SDL_EnableUNICODE( SDL_ENABLE );
SDL_Event uin;
while(!(uin.type==SDL_KEYDOWN&&uin.key.keysym.sym==SDLK_RETURN))
{
while(SDL_PollEvent(&uin))
{
if(uin.type==SDL_KEYDOWN)
{
if((uin.key.keysym.unicode>='A'&&uin.key.keysym.unicode<='Z')
||(uin.key.keysym.unicode>='a'&&uin.key.keysym.unicode<='z')
||(uin.key.keysym.unicode>='0'&&uin.key.keysym.sym<='9')
||(uin.key.keysym.unicode==SDLK_SPACE))
{
input+=((char)uin.key.keysym.unicode);
}
else
{
switch((unsigned int)uin.key.keysym.unicode)
{
case SDLK_BACKSPACE:
input.erase(input.size()-1);
break;
}
}
}
}
}
SDL_EnableUNICODE( SDL_DISABLE );
return input;
}
int main()
{
string mystring=stringinput();
cout<<mystring;
while(1);
return 0;
}
Related
In a StringTemplate how to temporarily suppress automatic indentation?
Suppose a template:
fooTemplate() ::= <<
I want this to be indented normally.
# I do not want this line to be indented.
>>
So you can understand the motivation.
I am generating C-lang code and I do not want the preprocessor instructions to be indented. e.g.
#if
To be clear the fooTemplate is not the only template.
It is called by other templates (which may nest several levels deep).
Introducing a special character into the template to temporarily disable indentation would be acceptable.
fooTemplate() ::= <<
I want this to be indented normally.
<\u0008># I do not want this line to be indented.
>>
I see that indentation is actually applied by the 'AutoIndentWriter' https://github.com/antlr/stringtemplate4/blob/master/doc/indent.md
I implemented my own 'SemiAutoIndentWriter' which looks for a magic character (\b in my case) in the stream.
When seen the magic character sets a 'suppressIndent' switch which causes indentation to be suppressed.
package org.stringtemplate.v4;
import java.io.IOException;
import java.io.Writer;
/** Just pass through the text. */
public class SemiAutoIndentWriter extends AutoIndentWriter {
public boolean suppressIndent = false;
public SemiAutoIndentWriter (Writer out) {
super(out);
}
#Override
public int write(String str) throws IOException {
int n = 0;
int nll = newline.length();
int sl = str.length();
for (int i=0; i<sl; i++) {
char c = str.charAt(i);
if ( c=='\b' ) {
suppressIndent = true;
continue;
}
// found \n or \r\n newline?
if ( c=='\r' ) continue;
if ( c=='\n' ) {
suppressIndent = false
atStartOfLine = true;
charPosition = -nll; // set so the write below sets to 0
out.write(newline);
n += nll;
charIndex += nll;
charPosition += n; // wrote n more char
continue;
}
// normal character
// check to see if we are at the start of a line; need indent if so
if ( atStartOfLine ) {
if (! suppressIndent) n+=indent();
atStartOfLine = false;
}
n++;
out.write(c);
charPosition++;
charIndex++;
}
return n;
}
Note that the '<\b>' is not a recognized special character by ST4 but '' is recognized.
Example:
var sentence = (hello there, I am Bob.)
var result = [
'he',
'el',
'll',
'lo',
' ',
'th',
'he',
'er',
're',
',',
' ',
'I',
' ',
'am',
' ',
'bo',
'ob',
'.']
I've found here working example, though it is in Javascript and I don't really know how to adopt it for Dart, and not sure how will behave once white space and punctuation is added in. Punctation and white space I need always split on its own not in combination with letters, I need them as well, as I will use them to add pauses in between words and sentences.
Thank you
var a = 12345678;
a= a.toString();
var arr=[];
for (var i =0; i<a.length-1; i++) {
arr.push(Number(a[i]+''+a[i+1]));
}
console.log(arr);
You could use regular expressions to split the sentence. For example:
void main() {
var exp = RegExp('([A-Za-z]{1,2}|[,!.?\s ])');
var str = "hello there, I am Bob.";
var matches = exp.allMatches(str);
for (var m in matches) {
print(m.group(0));
}
}
This looks for letters (A-Z or a-z) in groups of either 1 or 2, or single punctuation characters (,!.?) \s represents a white space.
Running the above would produce:
he
ll
o
th
er
e
,
I
am
Bo
b
.
Another approach
void main() {
var a = "1234!5678";
a = a.toString();
var arr = [];
for (var i = 0; i < a.length - 1; i++) {
if (a[i + 1] == '!') {
continue;
}
if (a[i] == '!') {
arr.add(a[i]);
continue;
}
arr.add(a[i] + '' + a[i + 1]);
}
print(arr);
}
I don't know dart much but I wrote this simple algorithm on dartpad and it works
If someone is having same issue, this is how I solved it
void main(String string) {
var test = "I Hello there I am Bob 23!";
List<String> nameArray = test.split('');
for (int curIndex = 0; curIndex < nameArray.length; curIndex++) {
if (curIndex >= 1 && nameArray[curIndex].contains(new RegExp(r'[a-zA-Z]')) && nameArray[curIndex-1].contains(new RegExp(r'[a-zA-Z]'))) {
print(nameArray[curIndex-1] + nameArray[curIndex]); // checks if current curIndex and previous curIndex are letters, if so returns previous and curent letters joined
} else {
if (curIndex >= 1 && nameArray[curIndex].contains(new RegExp(r'[a-zA-Z]')) && nameArray[curIndex+1].contains(new RegExp(r'[a-zA-Z]'))) {
null; // checks if curIndex and next curIndex are letters, if so returns null
}else{
print(nameArray[curIndex]);
}
}
}
}
Which returns
I
He
el
ll
lo
th
he
er
re
I
am
Bo
ob
2
3
!
I'm using boost::asio with ncurses for a command-line game. The game needs to draw on the screen at a fixed time interval, and other operations (e.g. networking or file operations) are also executed whenever necessary. All these things can be done with async_read()/async_write() or equivalent on boost::asio.
However, I also need to read keyboard input, which (I think) comes from stdin. The usual way to read input in ncurses is to call getch(), which can be configured to either blocking (wait until there is a character available for consumption) or non-blocking (return a sentinel value of there no characters available) mode.
Using blocking mode would necessitate running getch() on a separate thread, which doesn't play well with ncurses. Using non-blocking mode, however, would cause my application to consume CPU time spinning in a loop until the user presses their keyboard. I've read this answer, which suggests that we can add stdin to the list of file descriptors in a select() call, which would block until one of the file descriptors has new data.
Since I'm using boost::asio, I can't directly use select(). I can't call async_read, because that would consume the character, leaving getch() with nothing to read. Is there something in boost::asio like async_read, but merely checks the existence of input without consuming it?
I think you should be able to use the posix stream descriptor to watch for input on file descriptor 0:
ba::posix::stream_descriptor d(io, 0);
input_loop = [&](error_code ec) {
if (!ec) {
program.on_input();
d.async_wait(ba::posix::descriptor::wait_type::wait_read, input_loop);
}
};
There, program::on_input() would call getch() with no timeout() until it returns ERR:
struct Program {
Program() {
initscr();
ESCDELAY = 0;
timeout(0);
cbreak();
noecho();
keypad(stdscr, TRUE); // receive special keys
clock = newwin(2, 40, 0, 0);
monitor = newwin(10, 40, 2, 0);
syncok(clock, true); // automatic updating
syncok(monitor, true);
scrollok(monitor, true); // scroll the input monitor window
}
~Program() {
delwin(monitor);
delwin(clock);
endwin();
}
void on_clock() {
wclear(clock);
char buf[32];
time_t t = time(NULL);
if (auto tmp = localtime(&t)) {
if (strftime(buf, sizeof(buf), "%T", tmp) == 0) {
strncpy(buf, "[error formatting time]", sizeof(buf));
}
} else {
strncpy(buf, "[error getting time]", sizeof(buf));
}
wprintw(clock, "Async: %s", buf);
wrefresh(clock);
}
void on_input() {
for (auto ch = getch(); ch != ERR; ch = getch()) {
wprintw(monitor, "received key %d ('%c')\n", ch, ch);
}
wrefresh(monitor);
}
WINDOW *monitor = nullptr;
WINDOW *clock = nullptr;
};
With the following main program you'd run it for 10 seconds (because Program doesn't yet know how to exit):
int main() {
Program program;
namespace ba = boost::asio;
using boost::system::error_code;
using namespace std::literals;
ba::io_service io;
std::function<void(error_code)> input_loop, clock_loop;
// Reading input when ready on stdin
ba::posix::stream_descriptor d(io, 0);
input_loop = [&](error_code ec) {
if (!ec) {
program.on_input();
d.async_wait(ba::posix::descriptor::wait_type::wait_read, input_loop);
}
};
// For fun, let's also update the time
ba::high_resolution_timer tim(io);
clock_loop = [&](error_code ec) {
if (!ec) {
program.on_clock();
tim.expires_from_now(100ms);
tim.async_wait(clock_loop);
}
};
input_loop(error_code{});
clock_loop(error_code{});
io.run_for(10s);
}
This works:
Full Listing
#include <boost/asio.hpp>
#include <boost/asio/posix/descriptor.hpp>
#include <iostream>
#include "ncurses.h"
#define CTRL_R 18
#define CTRL_C 3
#define TAB 9
#define NEWLINE 10
#define RETURN 13
#define ESCAPE 27
#define BACKSPACE 127
#define UP 72
#define LEFT 75
#define RIGHT 77
#define DOWN 80
struct Program {
Program() {
initscr();
ESCDELAY = 0;
timeout(0);
cbreak();
noecho();
keypad(stdscr, TRUE); // receive special keys
clock = newwin(2, 40, 0, 0);
monitor = newwin(10, 40, 2, 0);
syncok(clock, true); // automatic updating
syncok(monitor, true);
scrollok(monitor, true); // scroll the input monitor window
}
~Program() {
delwin(monitor);
delwin(clock);
endwin();
}
void on_clock() {
wclear(clock);
char buf[32];
time_t t = time(NULL);
if (auto tmp = localtime(&t)) {
if (strftime(buf, sizeof(buf), "%T", tmp) == 0) {
strncpy(buf, "[error formatting time]", sizeof(buf));
}
} else {
strncpy(buf, "[error getting time]", sizeof(buf));
}
wprintw(clock, "Async: %s", buf);
wrefresh(clock);
}
void on_input() {
for (auto ch = getch(); ch != ERR; ch = getch()) {
wprintw(monitor, "received key %d ('%c')\n", ch, ch);
}
wrefresh(monitor);
}
WINDOW *monitor = nullptr;
WINDOW *clock = nullptr;
};
int main() {
Program program;
namespace ba = boost::asio;
using boost::system::error_code;
using namespace std::literals;
ba::io_service io;
std::function<void(error_code)> input_loop, clock_loop;
// Reading input when ready on stdin
ba::posix::stream_descriptor d(io, 0);
input_loop = [&](error_code ec) {
if (!ec) {
program.on_input();
d.async_wait(ba::posix::descriptor::wait_type::wait_read, input_loop);
}
};
// For fun, let's also update the time
ba::high_resolution_timer tim(io);
clock_loop = [&](error_code ec) {
if (!ec) {
program.on_clock();
tim.expires_from_now(100ms);
tim.async_wait(clock_loop);
}
};
input_loop(error_code{});
clock_loop(error_code{});
io.run_for(10s);
}
#include "pch.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <stdio.h>
using namespace std;
class LetterDistribution
{
public: char district, trace;
public: int random_num;
public : LetterDistribution(){}
public: LetterDistribution(char dis)
{
district = dis;
trace = 'Z';
}
public: string LetterNumbers()
{
random_num = rand();
string letter_no ( district + " " + random_num);
return letter_no;
}
};
int main()
{
srand(time(0));
cout << "Enter district\n"<<endl;
char dis ;
cin >> dis;
LetterDistribution ld(dis);
cout << ld.LetterNumbers();
return 0;}
I am getting error in second last line inside main "cout << ld.LetterNumbers();". I am new to c++ , I have been working on C# earlier. I shall be thankful if someone could help me .
You have 2 issues in LetterNumbers function:
You can't add to string a number, you should convert the number to string first. you can do so by std::to_string(random_num)
You can't start concatenate string with a character, since character is like number in c++, and adding anything to number is a number. You should start from a string, even an empty one.
So the whole function can be something like:
string LetterNumbers()
{
random_num = rand();
string letter_no ( std::string("") + district + " " + std::to_string(random_num));
return letter_no;
}
Another issues: (but not errors!)
in c++ you can specify public: once, and everything after it is still public, until you change it. same thing for private and protected.
instead of <stdio.h> you should use <cstdio> which is the c++ wrapper for the c header.
Is it possible to create a macro which counts the number of expanded items?
macro_rules! count {
($($name:ident),*) => {
pub enum Count {
$(
$name = 1 << $i // $i is the current expansion index
),*
}
}
}
count!(A, B, C);
Here is a macro that counts the number of matched items:
macro_rules! count_items {
($name:ident) => { 1 };
($first:ident, $($rest:ident),*) => {
1 + count_items!($($rest),*)
}
}
fn main() {
const X: usize = count_items!(a);
const Y: usize = count_items!(a, b);
const Z: usize = count_items!(a, b, c);
assert_eq!(1, X);
assert_eq!(2, Y);
assert_eq!(3, Z);
}
Note that the counting is computed at compile time.
For your example, you can do it using accumulation:
macro_rules! count {
($first:ident, $($rest:ident),*) => (
count!($($rest),+ ; 0; $first = 0)
);
($cur:ident, $($rest:ident),* ; $last_index: expr ; $($var:ident = $index:expr)+) => (
count!($($rest),* ; $last_index + 1; $($var = $index)* $cur = $last_index + 1)
);
($cur:ident; $last_index:expr ; $($var:ident = $index:expr)+) => (
#[repr(C)]
enum Count {
$($var = 1 << $index),*,
$cur = 1 << ($last_index + 1),
}
);
}
pub fn main() {
count!(A, B, C, D);
assert_eq!(1, Count::A as usize);
assert_eq!(2, Count::B as usize);
assert_eq!(4, Count::C as usize);
assert_eq!(8, Count::D as usize);
}
Yes, if you pack it as array of idents:
macro_rules! count {
($($name:ident),*) => {
{
let counter = [$(stringify!($name),)*];
counter.len()
}
}
}
Count, names, reverse order of names are available. After, you can use it to construct something. For enum building you have to join it with something like this.
In this context, no. A macro could create an expression that counts the number of identifiers passed to it, but it would only be evaluated at runtime. I created this example in just a few minutes, but I realized it would not work for what you're doing.
Compiler plugins, however, are particularly suited to this sort of work. While they're not trivial to implement, I don't think it would be overly difficult to create one for this purpose. Maybe take a look, try your hand at it, and come back if you get stuck?
Since this question is general, posting an example of counting where arguments are separated by white-space (not commas).
Although in retrospect it seems obvious, it took me a while to figure out:
/// Separated by white-space.
#[macro_export]
macro_rules! count_args_space {
($name:ident) => { 1 };
($first:ident $($rest:ident) *) => {
1 + count_args_space!($($rest) *)
}
}
/// Separated by commas.
#[macro_export]
macro_rules! count_args_comma {
($name:ident) => { 1 };
($first:ident, $($rest:ident),*) => {
1 + count_args_comma!($($rest),*)
}
}
Second example is from #malbarbo, just posting to so you can see the 2x changes that were needed.