Why is else if producing different results compared to a switch? - c

I have a simple piece of code that detects keystrokes using ncurses.
As I understand, 1 keypress pushes 3 values into the buffer. Where the 3rd value differentiates between arrow keys for example.
So when pressing any of the 4 arrows on the keyboard, the first 2 values pushed into the buffer should be similar \033, and [. But the 3rd value is unique to the arrow (A for up, B for down, C for right or D for left). Therefore, when mapping actions to keystrokes, we're depending on the 3rd value.
When trying to assess which arrow was pressed I tried both an if else ladder and a switch. The if else ladder works perfectly. But the switch seems to fire multiple cases on each keypress.
Here's the working code (if else) -
char first = getch(); //returns \033
char second = getch(); //returns [
char third = getch(); // returns A or B or C or D
if(third == 'A'){
printf("Up Arrow Pressed");
}
else if(third == 'B'){
printf("Down Arrow Pressed");
}
else if(third == 'C'){
printf("Right Arrow Pressed");
}
else if(third == 'D'){
printf("Left Arrow Pressed");
}
Here's the code that isn't working (Case) -
char first = getch(); //returns \033
char second = getch(); //returns [
char third = getch(); // returns A or B or C or D
switch(third){
case('B'):
printf("\nDOWN");
case('C'):
printf("\nRIGHT");
case('A'):
printf("\nUP");
case('D'):
printf("\nLEFT");
default:
printf("default");
}
This is the output when cases are used and I press the down key:

if you don't break; at the end of a case the next case is executed.

If You Don't Use break at the end of each case then the cases that you write after the true case will also be executed.

Use "break; " (same as in the code provided as image) as last statement in each case so that it prevents execution of followed cases.!
(https://i.stack.imgur.com/up2pG.png)

Related

How to erase last char in console using backspace, without using space char?

I'm trying to implement a console program that has backspace functionality. The console accepts a number of valid commands I've defined. Example:
Input:
Output:
I'm using a switch statement, which checks the current char returned by getchar().
switch (inChar)
{
case '\r':
case '\n':
{
...
}
case 0x18: // ^x
{
...
}
case 0x08: // backspace
{
printf("\b \b");
break;
}
default:
{
inBuffer[inBufIndx++] = inChar;
inBuffer[inBufIndx] = 0;
printf("%c", inChar); // echo character
}
}
The code above gives the appearance of erasing the character, but places a space char. This works for most instances, such as erasing the o off of helo but does not work when erasing the o off helpo. My shell can no longer interpret the command due to the space char that is printed in the place of the o
How can I implement backspace for chars at the end of the inputthat need to be erased?
EDIT: rici is exactly right. I was not removing the char I erased in the console from my inBuffer. The code below gave the desired functionality.
case 0x08:
{
printf("\b \b");
inBuffer[inBufIndx--] = NULL;
break;
}
Presumably, you need to remove the character from inBuffer (by decrementing inBufIdx and overwriting the old character with a 0). What the screen shows should be irrelevant.
By the way, the backspace-space-backspace sequence won't work at the right margin
#Eugene Sh. answer worked for me, but just without the round braces in my tcsh shell:
printf "\b"

How can I distinguish two keystrokes which have similar responses from getch()

As I said in title, How can I distinguish two keystrokes which have similar responses from getch(). In this code block, K's and left arrow key's getch() responses are same, so when I type capital k case 75 works. How can I fix it? Also I got this problem with some other words.
while(1){
ch1=getch();
switch( ch2 = getch())
{
if(ch1 != 0xE0)
{
default:
for(i=' ';i<'}';i++)
{
if(i == ch2)
{
/*SOME STUFF*/
printf("%c" , iter->x);
}
break;
}
else
{
case 72: printf("UP WAS PRESSED\n");
break;
/*Some other stuff*/
}
}
}
When a special character such as left-arrow is pressed, getch will first return either the value 0 or 0xE0, then it will return a key code (which is not the same as an ASCII code).
From MSDN:
The _getch and _getwch functions read a single character from the
console without echoing the character. None of these functions can be
used to read CTRL+C. When reading a function key or an arrow key, each
function must be called twice; the first call returns 0 or 0xE0, and
the second call returns the actual key code.
So you need to check for a 0 or 0xE0 which tells you the next character is a key code, not an ASCII code.
The list of key codes: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
EDIT:
Your if(ch1 != 0xE0) is outside of any case, so it gets skipped over. Also, you're always calling getch twice when you enter the loop. So if you didn't get a key code, you end up reading 2 regular characters and most likely skip one of them.
Start you loop with a single getch. Then check for 0 or 0xE0, and if found then call getch again.
while (1) {
int ch = getch();
int keycode = 0;
if (ch == 0 || ch == 0xe0) {
keycode = 1;
ch = getch();
}
switch (ch) {
...

How do i stop the blocking?

Hey all I've asked this question a few times in the past few days but I just don't get it...I basically want to have the while loop for the Beep command executed in the background while the user can interact with the available case statements (only one shown..there are others)....i keep getting blocked and everytime i want the beep to make a sound constantly i block the rest of my program...I have to use Beep so please don't suggest any other functionality..
here's a sample code...
while( keypress != 'q' || keypress != 'Q')
{
x = Beep(x);
while (x == 1)
Beep(350,300);
alarm_t current;
keypress = _getch();
switch(keypress){
case 'h':
sprintf_s(current.message,"high alarm");
current.timeOfEvent = time(NULL);
recordEvent(current);
break;
Now...my issue is with the while loop and the Beep command....here is what i call to Beep(x)
int Beep(int y)
{
return y;
}
So basically i am trying to call a function outside of my current cpp file to just compare x and y, and return y as being equivalent to x...i thought this might avoid blocking but it doesn't...
Your while loop around beep just won't work and _getch is blocking. So it will just block until there's a character.
Depending what platform you are on, you need something like kbhit (and if you google that you will find alternatives for other platforms). ie it's not standard C functionality and platform specific.
kbhit will return true or false depending if there is a character or not.
So you can do:
while(!key_is_quit(ch))
{
Beep();
if(kbhit())
{
ch = getch();
// switch....
}
}

Stuck in a loop after switch in c

while (1)
{
c = getchar();
switch(state)
{
case 0:
if((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == Bit_SET))
{
state=1;
}
if ( c=='p')
{
state = 2;
}
break;
case 1 :
if((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) != Bit_SET))
{
state = 0;
}
break;
case 2:
iprintf("%s",led_name_arr[i]);
if (c=='r')
{
state=0;
}
break;
}
}
I want to print the printf and then reach state2 .. how can this be achieved .below is what i have tried and where i am stuck .
psuedocode:
if ( c==P)
{
printf(" hi");
state 2;
}
** in this case the printf statement does not get executed **
or
case 2:
iprintf("%s",led_name_arr[i]);
if (c=='r')
{
state=0;
}
break;
** in this case the printf statement keeps printing in a loop **
i dont want the while loop to stop , in a continuous loop i want case 0 keeps working , but when it get the input p .. it pauses and executes the printf ... and waits till it gets a r to resume case 0 .... Thus the program never halts but waits to either get "P" or "R" to execute each case... I hope i make sense
Any help will be appreciated .
Your breaks are breaking out of the switch ... case not the while. You'll need to use some kind of boolean flag to break out of the outer loop, e.g.:
bool someflag = true;
while(someflag){
switch(something){
case a:
someflag = false; // set the flag so we break out of the loop
break; // break out of the switch-case so we don't enter case b
case b:
// do something else
break;
}
}
-------- EDIT, because I misunderstood the question ------------
I think you need an extra state in your logic, right now (ignoring state 1), you have two states:
Wait for a p, when you get one, goto 2.
printf for each character until you get an r, then goto 1
What you want is:
Wait for a p, when you get one, goto 2.
Do a printf, then goto 3.
Wait for an r, when you get one, goto 1.
i am not sure what you are asking but i m pretty sure what you want in case 2 is something like this:
case 2:
iprintf("%s",led_name_arr[i]);
while(c!='r')
{
c = getchar();
}
state=0;
break;
You've created an infinite loop with the while (1) statement that has no possible exit. The break statements within the switch apply to the switch statement, not the while loop. You need another break statement outside the switch.
well,
initialize state to 0
compile and run the program
first time enter p // here state =2
then enter r // here state = 0
....continue in a loop due to while(1)
Because you are not breaking the while(1) loop. Use one more break for while loop.

Switch and default: for C

Sorry if this sounds like a very basic question, it is my first time on here!
I am having some difficulties with coding for C, specifically with a switch and the default of that switch. Here is some example code:
#include<stdio.h>
int key;
main()
{
while((key=getchar())!=EOF)
{
printf("you pressed %c \n",key);
switch(key){
case'0':
case'1':
case'2':
case'3':
printf("it's a numeral\n");
break;
default:
printf("it's not a numeral\n");
}
}
}
The actual code is a bunch longer, this is purely an example.
So the code compiles it and I execute it, but I get:
"You pressed 1, it's a numeral, you pressed , it's not a numeral."
My code seems to 'fall through' and repeat itself without referring to either one. If anyone could help that would be great as this is an example in a text book and I am utterly stuck!
Kindest Regards.
You need to account for entering the Enter key, which produces a '\n' on *nix systems. I am not sure what pressing the Enter key does on Windows systems.
Here's your original code doctored up to eat the return key.
#include<stdio.h>
int key = 0;
main()
{
while((key=getchar())!=EOF)
{
if('\n' == key)
{
/* Be silent on linefeeds */
continue;
}
printf("you pressed %c \n",key);
switch(key){
case'0':
case'1':
case'2':
case'3':
printf("it's a numeral\n");
break;
default:
printf("it's not a numeral\n");
}
}
}
You maybe using getchar() for a specific reason, but my experiences in C usually involved reading the whole line, and RTL functions like scanf will eat the line terminator for you.
You need to eat the newline character, that is put in the read buffer when you hit return.
Issue another call to getchar after or before the switch to solve your problem.
Here is an idea...immediately before the printf(), insert logic to ignore spaces and all control characters...
if(key <= ' ')
continue;
printf(...) ...
I dont know if that is the problem, but you have three case without a break. So you press key "1" and there is nothing to do for the programm and so ins go to the next case how is right and this is the default.
Although you take a char in an int-variable???
In your Example it is a better way to take a if-clause like this:
#include<stdio.h>
char key;
main()
{
while((key=getchar())!=EOF)
{
printf("you pressed %c \n",key);
if(key == '0' || key == '1' || key == '2' || key == '3'){
printf("it's a numeral\n");
}
else {
printf("it's not a numeral\n");
}
}
Code is not tested. ;-)
The best way in bigger programms is to work with regular expressions.
I hope, this answer was helpful.
the problem might be due to, input buffer not flushing. when "1" is matched in the switch case, a newline character remains in the buffer.
try this,
fflush(stdin)

Resources