Getting choice from input - c

I want to prompt the user to press a key.This key will be stored in a variable and a switch statement is applied on the key to execute the corresponding command.I wrote a code,which seems a bit nasty and inefficient because it makes a call to the function GetAsyncKeyState in an exhausting way,specially if the keys are too many.Is there a simpler approach to this?
#include <stdio.h>
#include <Windows.h>
int GetChoice(int *keys,size_t size);
int main(void)
{
int keys[] = {'A','B','F'};
int cKey = GetChoice(keys,3);
switch(cKey)
{
case 'A':
puts("you pressed : A!");
break;
case 'B':
puts("you pressed : B!");
break;
case 'F':
puts("you pressed : F!");
break;
}
Sleep(2000);
return 0;
}
int GetChoice(int *keys,size_t size)
{
size_t n;
while(1)
{
for(n = 0 ; n < size ; n++)
{
if(GetAsyncKeyState(keys[n]))
return keys[n];
}
}
return 0;
}

Well you need to only change from
int cKey = GetChoice(keys,3);
to
char cKey;
cKey=getch();
you do not need the
int GetChoice(int *keys,size_t size)
function. Just remove it too. Your entire code should look like
#include <stdio.h>
#include<conio.h>
int main(void)
{
char cKey;
cKey=getch();
switch(cKey)
{
case 'A':
puts("you pressed : A!");
break;
case 'B':
puts("you pressed : B!");
break;
case 'F':
puts("you pressed : F!");
break;
}
Sleep(2000);
return 0;
}

You are mixing apples and oranges. If you output messages with puts(), you should probably read input from standard input with getchar(). Reading the keyboard state with GetAsyncKeyState() is only consistent if you display information on the screen using the Windows API. Doing this in C has gone out of fashion a long time ago already. Good luck!

If you're trying to program in C, use C constructs, not Windows constructs. Take a look at K&R (Kernighan and Ritchie) section 1.5. K&R is available in PDF form. Just search for it.
If you use the async key state, you will have to apply your own detection for liftoff.

Related

(C) Am I properly converting enum type to string?

I am very new to coding, and am taking an online course with very little help. I am working through an assignment creating a bunch of functions that will be used at a later date. I have not learned anything about points, arrays, or recursions at this point. My knowledge of strings is pretty much limited to the "printf" function.
With that being said, I have been given this description for how the function "ranking_to_string" should operate:
This function should convert the
hand_ranking_t enumerated value passed
in to a string that describes it.
The enumerated type here is hand_ranking_t, which ranks a poker hand in descending order of value from STRAIGHT_FLUSH (0) to NOTHING (8). With that all being said, this is the function I have created to attempt to follow my instructions:
const char * ranking_to_string(hand_ranking_t r) {
switch (r) {
case STRAIGHT_FLUSH: printf("STRAIGHT_FLUSH\n"); break;
case FOUR_OF_A_KIND: printf("FOUR_OF_A_KIND\n"); break;
case FULL_HOUSE: printf("FULL_HOUSE\n"); break;
case FLUSH: printf("FLUSH\n"); break;
case STRAIGHT: printf("STRAIGHT\n"); break;
case THREE_OF_A_KIND: printf("THREE_OF_A_KIND\n"); break;
case TWO_PAIR: printf("TWO_PAIR\n"); break;
case PAIR: printf("PAIR\n"); break;
case NOTHING: printf("NOTHING\n"); break;
default: printf("Invalid thing\n"); break;
}
return EXIT_SUCCESS;
}
I am wondering, am I correct in returning EXIT_SUCCESS (0) at the end of the function? Is there another way to convert the enum value entered into a string using printf?
EXIT_SUCCESS is a macro that will expand into an environment defined indicator to be returned from main (or via exit, etc.) to indicate that your entire program has successfully done what it is supposed to do. It's generally not used outside this context.
printf is used to send output to the stream associated with stdout. For example, you might call printf to display text in your terminal.
Your function should instead return the string literals, to be used by the caller of ranking_to_string.
const char *ranking_to_string(hand_ranking_t r) {
switch (r) {
case STRAIGHT_FLUSH: return "STRAIGHT_FLUSH";
case FOUR_OF_A_KIND: return "FOUR_OF_A_KIND";
/* ... and so on ... */
default: return "Invalid thing";
}
}
An example program:
#include <stdio.h>
typedef enum {
STRAIGHT_FLUSH,
FOUR_OF_A_KIND,
/* ... and so on ... */
} hand_ranking_t;
const char *ranking_to_string(hand_ranking_t r) {
switch (r) {
case STRAIGHT_FLUSH: return "STRAIGHT_FLUSH";
case FOUR_OF_A_KIND: return "FOUR_OF_A_KIND";
/* ... and so on ... */
default: return "Invalid thing";
}
}
int main(void) {
hand_ranking_t rank = FOUR_OF_A_KIND;
const char *rank_string = ranking_to_string(rank);
printf("My ranking is <%s>\n", rank_string);
}
Output:
My ranking is <FOUR_OF_A_KIND>
Probably not covered in your course, but it's possible to automate ranking_to_string entirely by using X-Macros. Also, since poker hands have value, it makes sense to list them by it.
#include <stdlib.h>
#include <stdio.h>
#define HANDS X(HIGH_CARD), X(PAIR), X(TWO_PAIR), X(THREE_OF_A_KIND), \
X(STRAIGHT), X(FLUSH), X(FULL_HOUSE), X(FOUR_OF_A_KIND), \
X(STRAIGHT_FLUSH), X(ROYAL_FLUSH)
#define X(name) name
enum hand { HANDS };
#undef X
#define X(name) #name
static const char *hand_str[] = { HANDS };
#undef X
static const size_t hand_size = sizeof hand_str / sizeof *hand_str;
int main(void) {
enum hand i, j;
for(i = 0; i < hand_size; i++) printf("%s\n", hand_str[i]);
i = FULL_HOUSE;
j = FLUSH;
printf("%s is %s than %s.\n",
hand_str[i], i < j ? "less" : "greater", hand_str[j]);
return EXIT_SUCCESS;
}
Where # is the stringizing operator of the pre-processor.

Switch statement using a union in C, got me into problems, what's wrong with my code?

I'm almost done with my assignment where I was supposed to build a program where the user interacts with a warehouseprogram, where you can delete, add, edit... However in my event_loop function, no matter what input I type to choose from the menu goes to default in my switch statement. I'm using a uniontype answer_t in my ask_question_menu, so maybe it has something to do with the return from that function that I want to be a single char. Can someone tell me what the heck is going on here?
Very thankful for help!
typedef union {
int i;
float f;
char *s;
char d;
} answer_t;
char ask_question_menu(char *question){
answer_t answer = ask_question(question, correct_input, (convert_func) toupper);
return answer.d;
}
//my general function for user input follows here...
answer_t ask_question(char *question, check_func check, convert_func convert)
{
int buffersize = 50;
char buffer[buffersize];
do
{
printf("%s\n", question);
read_string(buffer, buffersize);
}
while(check(buffer)==false);
answer_t result = convert(buffer);
return result;
}
int event_loop(item_t *db, int *db_size)
{
while(true){
char choise = ask_question_menu(" [L]ägga till en vara\n [T]a bort en vara\n [R]edigera en vara\n Ån[g]ra senaste ändringen\n Lista [h]ela varukatalogen\n [A]vsluta\n");
switch(choise)
{
case 'L':
add_item_to_db(db, db_size);
break;
case 'T':
remove_item_from_db(db, db_size);
break;
case 'R':
edit_db(db, *db_size);
break;
case 'G':
printf("Not yet implemented\n");
break;
case 'H':
list_db(db, *db_size);
case 'A':
return 0;
break;
default:
printf("Wrong input\n");
break;
}
}
}
When convert points to toupper(), this line ...
answer_t result = convert(buffer);
... definitely produces undefined behavior, because toupper() takes a parameter of type int and returns an int, but you are passing a char * and assuming that the return value is an answer_t. If you prefer, you can say that it is the cast of toupper to convert_func that is ultimately responsible for this UB.
If you need a function that returns an answer_t, then you'll need to wrap toupper(). It's unclear exactly what form a convert_func is supposed to have, but this would be compatible with the way you are trying to use it:
answer_t toupper_wrap(char *buffer) {
return (answer_t) { .d = toupper(*buffer) };
}
Pass a pointer to that instead of a pointer directly to toupper().

can anyone find why is ths program to solve postfix expression giving runtime error

I was trying to solve a postfix expression but i don't understand why is it giving runtime error.
code:
#include<stdio.h>
#include<stdlib.h>
#include<stdlib.h>
struct stack
{
int top;
int n[100];
}s;
void push(int a)
{
s.n[s.top+1]=a;
s.top++;
}
void pop(char a)
{
int c,b;
b=s.n[s.top];
c=s.n[s.top-1];
s.top--;
switch(a)
{
case '+':
s.n[s.top]=b+c;
break;
case '-':
s.n[s.top]=b-c;
break;
case '*':
s.n[s.top]=b*c;
break;
case '/':
s.n[s.top]=b/c;
break;
}
}
int main()
{
s.top=-1;
int m,i,k;
char a[100],c[100];
scanf("%d",&m);
for(i=0;i<m;i++)
{
int j=0;
while(1)
{
scanf("%c",a[j]);
if(a[j]=='?')
break;
else if(a[j]==' ')
{
push(atoi(a));
}
else if(a[j]=='+'||'-'||'*'||'/')
{
pop(a[j]);
}
else
{
j++;
}
}
printf("%d",s.n[s.top]);
}
}
You code is hardly readble, still, I think, you need to change
scanf("%c",a[j]);
to
scanf(" %c",&a[j]); //note the space before %c, and scanf() expects pointer
for
& because as per the scanf() signature, it needs the address to store the scanned result.
leading space [] to stop scanning the previously pressed ENTER [\n] key.
Kindly Check the man page of scanf() for more details.
Also, as mentioned in Mr. #LPs 's answer, usage of push(atoi(a)); is very dangerous, in case a is not null-terminated.
Chnage scanf("%c",a[j]); to scanf("%c",&a[j]);. You need to pass the address to store the value of char. Also, you would further need to discard the extra character after each input from stdin.
I think that instruction push(atoi(a));is not safe, because of the array is not zero initialized, than atoi can fall into undefined behaviour.
Another thing is that with scanf with %c you can accept all chars (eg a, b,c) that make atoi fail.

nested switch case not working [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am trying to execute some commands using USART communication and reading some values using ATmega32-A. have a look at my code . My problem is i am trying to add some cases (nested switch case) but i am not getting what i want. I hope i am giving all most all information required to solve my problem.
void uniCom(void) {
switch (Command) {
/* ... */
case (muxsel):
printf(muxselection);
switch (c) {
case 1:
printf("this is mux chaneel1");
DDRB = 0b10111111;
PORTB = 0b00000000;
printf("adc Value", ReadAdc());
Command = 0;
break;
case 2:
/*-------------------*/
break;
}
Command = 0;
break;
/* ... */
default:
Command = 0;
break;
}
}
The problem is undefined c. And I don't see any declaration of muxselection, maybe missing "" ? Now the second approach.
void selcase(void) {
unsigned char c;
printf("muxselection");
while (rx_counter0) {
c = getchar();
switch (c) {
case 1:
printf("this is mux chaneel1");
DDRB = 0b10111111;
PORTB = 0b00000000;
printf("adc Value", ReadAdc());
Command = 0;
break;
case 2:
/*-------------------*/
break;
}
}
}
void uniCom(void) {
switch (Command) {
/* ... */
case (muxsel):
printf(muxselection);
selcase();
Command = 0;
break;
/* ... */
default:
Command = 0;
break;
}
}
My problem is i am executing all the commands as i declared but i want to select some more cases in one of the main switch case command "muxsel". for that i wrote nested switch case. if i select "muxsel" command on hyperteminal then it is printing like "muxselection" then if i enter 1 to select "case '1'"in second switch, nothing is printing. it is printing "command not found". what is the problem. I want execute nested switch but i am not able to do that using above code I have tried like this also.
void selcase(void) {
unsigned char c;
printf("muxselection");
while (rx_counter0) {
c = getchar();
switch (c) {
case '1':
printf("this is mux chaneel1");
DDRB = 0b10111111;
PORTB = 0b00000000;
printf("adc Value", ReadAdc());
c= 0;
break;
case '2':
/*-------------------*/
break;
default;
break;
}
}
}
creating one function for nested switch case and calling in main switch case as shown below.
void uniCom(void) {
switch (Command) {
/* ... */
case (muxsel):
printf(muxselection);
selcase();
Command = 0;
break;
/* ... */
default:
Command = 0;
break;
}
}
this way also not working please suggest me how to overcome this problem. i want to select one of the command in main switch case such as "muxsel" after that i have select mux channels using case statement. any help appreciated.
Thanks in advance.
I have solved this problem.
OK... the code isn't terribly clear, but I think I see your problem.
You tried to modify the code like this:
case (muxsel):
printf(muxselection);
switch (c) {
case 1:
printf("this is mux chaneel1");
DDRB = 0b10111111;
PORTB = 0b00000000;
printf("adc Value", ReadAdc());
Command = 0;
break;
case 2:
First, you don't have c declared in the scope of the uniCom() function. So that would not compile. Because you didn't give full code I assume you know that and probably really did something like this:
void uniCom(void) {
unsigned char c;
c = getchar();
switch (Command) {
case (no_com):
Command = 0;
....
case (muxsel):
printf("muxselection\n"); //Need quotes here and maybe a \n?
switch (c) {
case 1:
...
Which leads to the next problem. You're asking for a char c but your cases are built on an int. For example, if the user enters 3, what you're getting is the character '3' or the int 51. Check the ASCII Table
So your cases are for start of header (SOH), start of text (STX), etc right now... that's not going to work the way you wanted it to. You need to either do this:
switch (c) {
case 51: // This is ASCII '1'
...
break;
case 52: // This is ASCII '2'
Or do this:
switch (c) {
case '1':
...
break;
case '2':
Since you didn't give your input, or how c was defined, I could be wrong... but I'm going to wager that's your problem. By the way, make sure you have a default case at the end with a message like "bad input", it makes this type of thing easier to catch.
EDIT:
Modify the code as follows and share the result:
void runCom(void){
unsigned char c;
c = getchar();
printf("%c %d\n", c, c); //<-- add this line here
switch(Command){
and
void selcase(void) {
unsigned char c;
printf("muxselection");
while (rx_counter0) {
c = getchar();
printf("%c %d\n", c, c); //<-- and this line here
switch (c) {
I wrote it as an answer 'cause there is no place for it in comments. Although it's definitely not a final satisfactory once, it might help you get there.
For now I see two problems. You say you tried altering case(muxsel). Your code cannot even compile in my opinion. The code for the function should look similar to this:
void uniCom(void) {
switch (Command) {
/* ... */
case (muxsel):
printf(muxselection);
switch (c) {
case 1:
printf("this is mux chaneel1");
DDRB = 0b10111111;
PORTB = 0b00000000;
printf("adc Value", ReadAdc());
Command = 0;
break;
case 2:
/*-------------------*/
break;
}
Command = 0;
break;
/* ... */
default:
Command = 0;
break;
}
}
The problem is undefined c. And I don't see any declaration of muxselection, maybe missing "" ?
Now the second approach.
void selcase(void) {
unsigned char c;
printf("muxselection");
while (rx_counter0) {
c = getchar();
switch (c) {
case 1:
printf("this is mux chaneel1");
DDRB = 0b10111111;
PORTB = 0b00000000;
printf("adc Value", ReadAdc());
Command = 0;
break;
case 2:
/*-------------------*/
break;
}
}
}
void uniCom(void) {
switch (Command) {
/* ... */
case (muxsel):
printf(muxselection);
selcase();
Command = 0;
break;
/* ... */
default:
Command = 0;
break;
}
}
The second case could compile probably. The thing I do not understand is, why in the 2nd case you do manually read c. While in the former you do not ? Should it be loaded within uniCom routine or not ? It sure is in getCom(). Maybe you should not mess with buffers from the level of uniCom or below. Also are you sure that while(rxcounter0) will ever stop ? And if getchar() means to read a character from standard input from a human user typing on a keyboard it might be hard to read 1 or 2 from him as these are pretty low ASCII codes not present there.

How would I output to a file using multiple chars

#define numeric_b '0'
#define numeric_e '9'
/** init string intervals ---*/
static char c0=numeric_b;
static char c1=numeric_b;
static char c2=numeric_b;
static char c3=numeric_b;
static char c4=numeric_b;
static char c5=numeric_b;
static char c6=numeric_b;
static char c7=numeric_b;
/** init start & end ----------------*/
static const char en = numeric_e +1;
static const char st = numeric_b +1;
void str_in(int length){
FILE * fp = fopen("list.txt","w");
switch(length){
case 0:
printf("%c\n",c0);break;
case 1:
printf("%c%c\n",c0,c1);break;
case 2:
printf("%c%c%c\n",c0,c1,c2);break;
case 3:
printf("%c%c%c%c\n",c0,c1,c2,c3);break;
case 4:
printf("%c%c%c%c%c\n",c0,c1,c2,c3,c4);break;
case 5:
printf("%c%c%c%c%c%c\n",c0,c1,c2,c3,c4,c5);break;
case 6:
printf("%c%c%c%c%c%c%c\n",c0,c1,c2,c3,c4,c5,c6);break;
case 7:
printf("%c%c%c%c%c%c%c%c\n",c0,c1,c2,c3,c4,c5,c6,c7);break;
}
fclose(fp);
}
void permute(int length){
while(c0<=en){
str_in(length);
c0++;
if(c0==en && length==0){break;}
if(c0==en){
c0=st;
c1++;
if(c1==en && length==1){break;}
if(c1==en){
c1=st;
c2++;
if(c2==en && length==2){break;}
if(c2==en){
c2=st;
c3++;
if(c3==en && length==3){break;}
if(c3==en){
c3=st;
c4++;
if(c4==en && length==4){break;}
if(c4==en){
c4=st;
c5++;
if(c5==en && length==5){break;}
if(c5==en){
c5=st;
c6++;
if(c6==en && length==6){break;}
if(c6==en){
c6=st;
c7++;
if(c7==en && length==7){break;}
}
}
}
}
}
}
}
}
}
Sorry #zartag but this is some seriously obfuscated code. Please just tell us in a paragraph what you're trying to do and what you think your code is doing.
The most obvious thing I can see wrong with your code with respect to the question title ("output to a file") is that you are using printf instead of fprintf. They behave almost identically, except that printf prints to standard output, and fprintf prints to a file stream (e.g. to your list.txt). See the documentation on fprintf. In your case it should be
FILE * fp = fopen("list.txt","w");
switch(length){
case 0:
fprintf(fp, "%c\n",c0);break;
..snip
But seriously that code is in dire need of refactoring (e.g. it looks like the whole switch block can be replaced with a for loop). And please, when you ask a question here, give us a little more to go on than a code listing and question title.

Resources