Can't Read (!##$...and Capital Letters) from console with ReadConsoleInput - c

have wrote this app which reads input from console.
for(; ; )
{
GetNumberOfConsoleInputEvents(stdinInput, &numEvents);
if (numEvents != 0) {
INPUT_RECORD eventBuffer;
ReadConsoleInput(stdinInput, &eventBuffer, 1, &numEventsRead);
if (eventBuffer.EventType == KEY_EVENT) {
if(eventBuffer.Event.KeyEvent.bKeyDown)
{
printf("%c",eventBuffer.Event.KeyEvent.uChar.AsciiChar);
dataBuffer[bufferLen++] = eventBuffer.Event.KeyEvent.uChar.AsciiChar;
dataBuffer[bufferLen] = '\0';
if ( dataBuffer[bufferLen] == 99 || eventBuffer.Event.KeyEvent.uChar.AsciiChar == '\r' ) {
printf("User Wrote: %s\n",dataBuffer);
memset(dataBuffer,0,sizeof(dataBuffer));
bufferLen = 0;
}
}
}
}
}
It puts the data on a buffer and then it prints out the buffer. The problem occurs when im using Shift or CapsLock to write Capital letters or ! # # $ % characters. Then it prints out NOTHING.
Ive tried something with the VK_LSHIFT code but didn't worked.
Also if try to write something in other language than English it prints out something like this ▒├╞▒├╞▒├│▒├│ It cannot recognize the other language.
Can someone give me a hint on how to fix those problems ?
Thanks!

ReadConsoleInput returns events for each keystroke. For example, if you type SHIFT+A to get a capital A then you'll receive four key events: SHIFT down, A down, A up, SHIFT up.
The SHIFT key does not have a corresponding ASCII code so eventBuffer.Event.KeyEvent.uChar.AsciiChar is set to zero. This zero terminates the string you are building in dataBuffer so you don't see anything typed after the SHIFT key.
The simplest fix is to ignore any key event with an ASCII code of zero.
Additionally, if you want this to work well with foreign languages you might do better to use ReadConsoleInputW and eventBuffer.Event.KeyEvent.uChar.UnicodeChar. Better yet, compile it all as a Unicode app.

Related

How to fix: user inputted string not working correctly as a function

I have a successfully written encryption code that asks the user if they want a left shift or right shift and how much they want to shift by.The goal is to make the program work through functions. I was able to get the first part of the code into a function (school programming exercise), but I am stuck on getting the user input. The function is getValidMessage(); I know I've called it correctly in the main code. I think the issue might be with null terminating the string, but I can't figure out what's wrong.
I have a line of code that should null-terminate it, and I think I made enough changes to the original code that it should work. However, I'm not sure that I implemented the code correctly in the function.
// get message to encrypt
//This is called in the main function
char originalMessage[100];
getValidMessage(&originalMessage, sizeof(originalMessage));
int originalMessageLength = strnlen(originalMessage,
sizeof(originalMessage));
//This is the function
/*
* Gets valid message from user
*/
void getValidMessage(char* message, int messageSize)
{
char originalMessage[100];
bool validMessage = false;
printf("\n");
printf("Enter message to be encrypted (upper case alphabetic
characters only): ");
fgets(originalMessage, messageSize, stdin);
int originalMessageLength = strnlen(originalMessage,
messageSize) - 1;
while (!validMessage)
{
// invalid if non-upper case alpha characters in
// message (don't include newline at end))
validMessage = true;
for (int i = 0; i < originalMessageLength; i++)
{
if (!isupper(originalMessage[i]))
{
printf("\n");
printf("Message must contain only upper "
"case alphabetic characters!\n");
printf("Enter message to be encrypted "
"(upper case alphabetic characters only):");
fgets(originalMessage, messageSize, stdin);
originalMessageLength =
strnlen(originalMessage, messageSize) - 1;
// reset flag and exit for loop
validMessage = false;
break;
}
}
}
originalMessage[originalMessageLength] = '\0';
return originalMessage;
}
I am using a running test code that uses MESSAGE. The entirety of the code should encrypt and decrypt the code to show OGUUCIG and then MESSAGE again. Currently, it just shows a bunch of weird characters.
Note: This is NOT the entirety of the code. It doesn't show the encryption or decryption code. I know that works fine, but I can't get it to work smoothly with a separate function instead of in the main body of the code.

Why does an empty printf allow me to continue reading data from the stdin?

CODE
while (1)
{
keycode = key_hook();
if (keycode == SPACE || keycode == BKSPACE)
{
render_again = 1;
}
if (keycode == ESC)
break;
if (render_again)
{
render_again = 0;
render(all);
}
dprintf(1, ""); //I have no idea why this prevents the program from freezing
}
int key_hook()
{
char buffer[4];
read(0, buffer, 4);
return (*(unsigned int *)buffer);
}
Alright, so this piece of code handles redrawing of text on screen. Some rows of text are underlined or highlighted using termcaps (tputs(tgetstr("us, NULL")......). Everything prints fine but after the first redraw of the text the while apparently freezes unless a dprintf/printf is present. The key_hook function just reads 4 bytes from the stdin and converts them to an int.
When I last did work here, my version of key_hook had a loop of single byte reads. This was broken by an alarm of 1 second and logic to whether the data so far was a key prefix.
The alarm interrupted the read, and stopped freeze

Input text in graphics in C programming

I am making a project in C. Its simple, just a Hangman Game.
Got the logic already cause I've done that only in console.
Now, I'm trying to do it in C again with GRAPHICS. I am using Turbo C.
I've read some of the functions of graphics.h: so far I've seen outtext() / outtextxy() something like that. It can print a string.
Can you input a char or string in graphics? Searched a lot but seen nothing.
Seen only drawing shapes examples.
How do you input characters, integers etc. in the graphics mode?
From memory, while you can use regular stdio functions printf, scanf, and gets, the graphics driver will paint them over your screen onto a "virtual cursor" position and scroll the screen when it reaches the bottom. You can use the nonstandard conio.h functions such as gotoxy and attempt to position the cursor, but it's still a mediocre way of inputting text, messing up the graphics stuff. You also cannot use the fancy fonts!
So use getch to read characters without showing them; update a string buffer (manually handling special keys such as Backspace and Return), and draw that on the screen using a font of your choice.
A short sample snippet of code to get you started:
#define MAX_INPUT_LEN 80
char inputbuf[MAX_INPUT_LEN];
int input_pos = 0;
then, in your main loop
int the_end = 0;
do
{
outtextxy (0,0, inputbuf);
c = getch();
switch (c)
{
case 8: /* backspace */
if (input_pos)
{
input_pos--;
inputbuf[input_pos] = 0;
}
break;
case 13: /* return */
the_end = 1;
break;
case 27: /* Escape = Abort */
inputbuf[0] = 0;
the_end = 1;
break;
default:
if (input_pos < MAX_INPUT_LEN-1 && c >= ' ' && c <= '~')
{
inputbuf[input_pos] = c;
input_pos++;
inputbuf[input_pos] = 0;
}
}
} while (!the_end);
Before you draw the text, make sure to erase the previous line! I left that out because it's been too long ago I used Turbo-C.
For taking input from used.. you can use scanf function similar to how we take input in any non-graphics c program.
You can do this by using normal scanf function. And by using sprintf copy a integer/whatever variable into a string. Now you can use outtextxy to set the string in specified location using x,y axis. Check geeksforgeeks to learn sprintf syntax.
I know it is too late. Hope it helps someone else.!

Parameters inside the function

I have a work to do in which I have to keep a loop inside the function expecting the following parameters:
-"i" to insert
-"s" to search
-"q" to quit
How do I keep this loop? I've looked up some options and it seems to be possible using a while or a switch, but I am not sure which is the best way to read those chars (with a fscanf perhaps?). I am also not sure how to read the things after the parameter "i" as the input would be "i word 9", so after detecting the i to insert I have to read a string and an int.
Anyone has any idea how to do this? I am sorry is this seems simple, but I am new to programming.
edit: Here is what I have so far
while (loop) {
fscanf(stdin,"%c",&par);
if (strcmp(&par,"i")){
scanf("%s %d",palavra,p);
raiz = insere(raiz,&palavra,p);
}
else if (strcmp(&par,"b")){
scanf("%s",palavra);
busca(raiz,&palavra);
}
else if (strcmp(&par,"q"))
loop = 0;
}
edit 2: This is what I have now, I am having problems reading the string and integer when the parameter is i, somehow it crashes the function
while (1) {
c = getchar();
if (c == 'f')
break;
else if (c == 'i'){
fscanf(stdin,"%s",&palavra);
scanf("%d",&p);
raiz = insere(raiz,palavra,p);
}
else if (c == 'b') {
scanf("%s",palavra);
busca(raiz,palavra);
}
}
Thanks in advance!
The code you have doesn't look too bad compared to what I believe you want. You can replace the "while (loop)" with "while (1)" and then your exist code "loop = 0;" with "break;" which is a bit more standard way of doing things. Also "fscanf(stdin..." is the same as "scanf(..." ... scanf will read from stdin by default. You might want to check the docs for strcmp because it returns 0 for an exact match and I don't think that will do what you want in your 'if' statements. You should be able to use scanf to read in the values you want, is it giving you an error?
You are using 3 separated scans. That means you can't input this "i word 9", but input one command or parameter at the time separated by EOL(pressing enter).. i, enter, word, enter, 9, enter ... Then the function should actually get further in those "if"s. With those scans you also should consider printing information about expected inputs ("Choose action q/i/f")
And I would recommend using something to test those inputs.
if (scanf("%d", &p) == 0) {
printf("Wrong input");
break;
}

Arduino Serial.println() outputs a blank line if not in loop()

I'm attempting to write a function that will pull text from different sources (Ethernet client/Serial/etc.) into a single line, then compare them and run other functions based on them. Simple..
And while this works, I am having issues when trying to call a simple Serial.println() from a function OTHER than loop().
So far, I have around 140 lines of code, but here's a trimmed down version of the portion that's causing me problems:
boolean fileTerm;
setup() {
fileTerm = false;
}
loop() {
char character;
String content="";
while (Serial.available()) {
character = Serial.read();
content.concat(character);
delay(1);
}
if (content != "") {
Serial.println("> " + content);
/** Error from Serial command string.
* 0 = No error
* 1 = Invalid command
*/
int err = testInput(content);
}
int testInput(String content) {
if (content == "term") {
fileTerm = true;
Serial.println("Starting Terminal Mode");
return 0;
}
if (content == "exit" && fileTerm == true) {
fileTerm = false;
Serial.println("Exiting Terminal Mode");
return 0;
}
return 1;
}
(full source at http://pastebin.com/prEuBaRJ)
So the point is to catch the "term" command and enter some sort of filesystem terminal mode (eventually to access and manipulate files on the SD card). The "exit" command will leave the terminal mode.
However, whenever I actually compile and type these commands with others into the Serial monitor, I see:
> hello
> term
> test for index.html
> exit
> test
> foo
> etc...
I figure the function is catching those reserved terms and actually processing them properly, but for whatever reason, is not sending the desired responses over the Serial bus.
Just for the sake of proper syntax, I am also declaring the testInput() function in a separate header, though I would doubt this has any bearing on whether or not this particular error would occur.
Any explainable reason for this?
Thanks.
Model: Arduino Uno R3, IDE version: 1.0.4, though this behavior also happened on v1.0.5 in some instances..
It is kinda guessable how you ended up putting delay(1) in your code, that was a workaround for a bug in your code. But you didn't solve it properly. What you probably saw was that your code was too eager to process the command, before you were done typing it. So you slowed it down.
But that wasn't the right fix, what you really want to do is wait for the entire command to be typed. Until you press the Enter key on your keyboard.
Which is the bug in your code right now, the content variable doesn't just contain "term", it also contains the character that was generated by your terminal's Enter key. Which is why you don't get a match.
So fix your code, add a test to check that you got the Enter key character. And then process the command.

Resources