There is a problem confused me a lot.
I use C language to display GUI in the Embedded device.Just like the following example.
title
1.xxxx 2.xxxx
3.xxxx 4.xxxx
5.xxxx 6.xxxx
I use the keypad to choose which item i need.but the item often has is's sub-item and I have to draw the menu and set the function again.Just like the follwing shows.
title title title
1.xxxx 2.xxxx press 1 1.xxxx 2.xxxx press 2 1.xxxx 2.xxxx
3.xxxx 4.xxxx --------------> 3.xxxx 4.xxxx --------------> 3.xxxx 4.xxxx
5.xxxx 6.xxxx 5.xxxx 6.xxxx 5.xxxx 6.xxxx
Now I use the following code temple to set the function i need.
GrawAndGetKeyCode( "0.xxxx||1.xxxx||2.xxxx||3.xxxx||4.xxxx", "title", &nSelect);
switch(nSelect)
{
case 0:
fuction();
break;
case 1:
fuction();
break;
case 2:
fuction();
break;
case 3:
fuction();
break;
case 4:
fuction();
break;
default:
break;
}
I wonder if there is some way i can use the menu1.item1.subitem2() to figure out the function i need?
Thanks a lot!!!
A simple menu system like that could be implemented using a simple state-machine.
Maybe something like this (warning: pseudo-ish code):
typedef void (*handler_t)(void); // Menu handler function type
handler_t * current_handlers;
char *current_menu;
// The top-level menu
handler_t top_menu_handlers[] = {
top_menu_1,
top_menu_2,
top_menu_3
};
char *top_menu = "..."; // Menu text for the top menu
// One sub-menu
handler_t sub_menu_1_handlers[] = {
sub_menu_1_1,
sub_menu_1_2,
sub_menu_1_3
};
char *sub_menu_1 = "...";
// Another sub-menu
handler_t sub_menu_2_handlers[] = {
sub_menu_2_1,
sub_menu_2_2,
sub_menu_2_3
};
char *sub_menu_2 = "...";
// ...
// Initialization
current_handlers = top_menu_handlers;
current_menu = top_menu;
// The state machine
for (;;) // Infinite loop
{
clear_screen();
print_menu(current_menu);
int selection = get_input();
current_handlers[selection](); // Call menu function
}
// ...
void top_menu_1(void)
{
// When user selects `1` in the top menu, go to first sub-menu
current_handlers = sub_menu_1_handlers;
current_menu = sub_menu_1;
}
// ...
void sub_menu_1_3(void)
{
// When the user select `3` in the first sub-menu, go back to top menu
current_handlers = top_menu_handlers;
current_menu = top_menu;
}
It's a lot of work to set up initially, but then it makes the code more general, and it's easier to add new alternatives or menus. And most importantly, it can be much more automated (by e.g. making the menu tree into an actual tree structure, and making the state-machine code handle the menu changing instead of having handler functions change it).
You may have a structure for menu items, each structure contains a label to be shown and a function pointer to be invoked. Then, your DrawMenuAndExecute function may take an array of menu_items and draw them, take the input and execute the corresponding function. Here is a working example:
#include <stdio.h>
#include <stdlib.h>
typedef void (* MENUFUNCPTR)();
struct menu_item {
const char *menu_item;
MENUFUNCPTR func;
};
void DrawMenuAndExecute(struct menu_item *items, size_t n) {
size_t i;
int opt;
int cont = 1;
// draw the menu
for (i = 0; i < n; ++i) {
printf("%3d: %s\n", (int)(i+1), items[i].menu_item);
}
printf("Your selection: ");
while (cont) {
scanf("%d", &opt);
if (opt > 0 && opt <= n) {
cont = 0;
}
else {
printf("Wrong selection, your selection again: ");
}
}
opt--;
if (items[opt].func != NULL) {
(*(items[opt].func))();
}
}
void main_menu();
void item1_item1();
void item1_item2();
void item1();
void item2();
void item3();
void item4();
void main_menu() {
struct menu_item items [] = {
{ "Item 1 (has submenu)", &item1 },
{ "Item 2 (count to ten)", &item2 },
{ "Item 3 (write something)", &item3 },
{ "Exit", &item4 }
};
DrawMenuAndExecute(items, 4);
}
void item1_item1() {
printf("Hello, how're you? (since I don't care, I won't let you type.)\n");
item1();
}
void item1_item2() {
main_menu();
}
void item1() {
// item1 has a sub menu
struct menu_item items [] = {
{ "Write something", &item1_item1 },
{ "Previous Menu", &item1_item2 }
};
DrawMenuAndExecute(items, 2);
}
void item2() {
int i = 1;
for (; i <= 10; ++i) {
printf("%d ", i);
}
printf("\n");
main_menu();
}
void item3() {
printf("Something.\n");
main_menu();
}
void item4() {
exit(0);
}
int main(int argc, char **argv) {
main_menu();
}
Related
This is a plane game function I wrote. I use a two-dimensional array to represent the game variables but The running result is abnormal, and * will jump suddenly.
And there will be two * , at the same time, and the plane also will stop
There should be no two * in the process of traversing the two-dimensional array. I tried to modify the position of * but I still couldn't.It's OK to run part of the code alone, but when you use the key operation, the program makes an error, but I don't know what's wrong
#include<stdio.h>
#include <windows.h>
#include<stdlib.h>
#include<conio.h>
#define enemynum 3
int element [20][30];
int position_x,position_y;
int enemy_x[enemynum],enemy_y[enemynum];
int score;
void gotoxy(int x, int y)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle, pos);
}
void HideCursor()
{
CONSOLE_CURSOR_INFO cursor_info = {1,0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void startup()
{ element[20][30]={0};
position_x=10;position_y=15;
element[position_x][position_y]=1;
for(int k=0;k<enemynum;k++)
{
enemy_x[k]=rand()%3;enemy_y[k]=rand()%20;
element[enemy_x[k]][enemy_y[k]]=3;
}
HideCursor();
}
This is an encapsulated pointer callback function. I don't think we need to consider the above functions
void show()
{ int i,j;
gotoxy(0,0);
for(i=0;i<20;i++)
{
for(j=0;j<30;j++)
{ if(element[i][j]==1)
{
printf("*");
}else if(element[i][j]==3)
{
printf("#");
}
else
printf(" ");
}
printf("\n");
}
}
void updatewhithout()
{
int i,j;
for(i=0;i<20;i++)
{
for(j=0;j<30;j++)
{
if(element[i][j]==2)
{
element[i][j]=0;
if(i>0)
element[i-1][j]=2;
}
}
} static int flag;
if(flag<20)
flag++;
if(flag==20)
{ for(int k=0;k<enemynum;k++)
{
if(enemy_x[k]==20)
{
enemy_x[k]=rand()%3;
enemy_y[k]=rand()%20;
}
element[enemy_x[k]][enemy_y[k]]=0;
enemy_x[k]++;
element[enemy_x[k]][enemy_y[k]]=3;
flag=0;
}
}
}
void updatewhith()
{ char ch;
if( kbhit())
ch=getch();
if(ch=='a')
{ element[position_x][position_y]=0;
position_y--;
element[position_x][position_y]=1;
}
if(ch=='d')
{ element[position_x][position_y]=0;
position_y++;
element[position_x][position_y]=1;
}
}
int main()
{startup();
while(1)
{show();
updatewhithout();
updatewhith();
}
}
The problem is this, I, am writing a chip 8 emulator in C, and i am using a library that use Xlib, for writing sprites attending input etc, the method that the library have for wait an input is this:
char gfx_wait(){
XEvent event;
gfx_flush();
while(1) {
XNextEvent(gfx_display,&event);
if(event.type==KeyPress) {
saved_xpos = event.xkey.x;
saved_ypos = event.xkey.y;
return XLookupKeysym(&event.xkey,0);
} else if(event.type==ButtonPress) {
saved_xpos = event.xkey.x;
saved_ypos = event.xkey.y;
return event.xbutton.button;
}
}
}
when i call this method the program stops waiting for input, I, need a methods that is called just when i press or release a button.
I just solve my problem, using this function :
int gfx_event_waiting(unsigned char *ch)
{
XEvent event;
gfx_flush();
while (1) {
if(XCheckMaskEvent(gfx_display,-1,&event)) {
if(event.type==KeyPress) {
*ch = XLookupKeysym(&event.xkey,0);
return 1;
}else if(event.type==KeyRelease){
return 1;
}else if (event.type==ButtonPress) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
}
and this is the main :
int
main(int argc, char *argv[])
{
int x;
int i;
unsigned char key_pressed,key_released;
Init();
LoadRom(SELECTED_ROM);
gfx_open(WIDTH,HEIGHT,"Chip 8 Emulator");
gfx_color(255,250,250);
for(;;){
if(!gfx_event_waiting(&key_pressed)){
opcode_cycle();
key_wait(key_released,0);
#if DEBUG
printf("# %d | %c #",x,key_pressed);
#endif
key_wait(key_pressed,1);
key_released = key_pressed;
gfx_clear();
if(DrawFlag)
Draw();
/*Big for for simulate a delay*/
for(i = 0; i <= 100000; i++)
;
}else{
x++;
}
}
}
I, am sure that there is a better way for do this , but you know, It's work...
in order to set a certain variable (MyVariable) to "TRUE" I have to check that a specific function call order was respected within a system.
For example, I have different functions within the system:
uint8 myFunction1()
{
if (...)
{
return NOT_OK
}
else
{
return OK
}
}
uint8 myFunction2()
{
if (...)
{
return NOT_OK
}
else
{
return OK
}
}
uint8 myFunction3()
{
if (...)
{
return NOT_OK
}
else
{
return OK
}
}
MyVariable = TRUE only if:
OK == myFunction1
OK == myFunction2
OK == myFunction3
exactly this call order was respected.
How to check the call order in C but without touching the body of the functions (like setting some flags´etc.)?
I'm still beginner and experimenting with C :)
Thanks!
This is almost certainly an "XY problem". That is, you think saving the call order is the solution to your actual problem, but your actual problem might be to ensure that the functions can't be called in the wrong order in the first place.
So the most correct way to fix this is to remake the program design. Someone mentioned state machines as one solution. Another solution might be something like an array of function pointers (which is a common implementation of state machines).
That being said, you can do something artificial to track the call order, though I wouldn't really recommend it. Example:
#define CALL_ORDER_N 3
const char* call_order [CALL_ORDER_N] = {NULL};
size_t call_order_i = 0;
static void save_call (const char* func)
{
call_order[call_order_i] = func;
call_order_i++;
if(call_order_i == CALL_ORDER_N)
{
call_order_i = 0;
}
}
Where call_order saves the 3 last function calls as pointers to string literals. The function save_call updates this array, by passing the __func__ constant to it from each function. __func__ is guaranteed to work like a static const char[] so this is safe. You'd do something like this:
void myFunction1 (void)
{
save_call(__func__);
...
}
void myFunction2 (void)
{
save_call(__func__);
...
}
void myFunction3 (void)
{
save_call(__func__);
...
}
And then go through the calls to see if they were in the correct order:
static bool is_call_order_ok (void)
{
const char* expected_order [CALL_ORDER_N] =
{
"myFunction1",
"myFunction2",
"myFunction3"
};
size_t co_i = call_order_i;
for(size_t i=0; i<CALL_ORDER_N; i++)
{
if(strcmp(call_order[co_i], expected_order[i])==0)
{
co_i++;
if(co_i == CALL_ORDER_N)
{
co_i = 0;
}
}
else
{
return false;
}
}
return true;
}
Full example:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define CALL_ORDER_N 3
const char* call_order [CALL_ORDER_N] = {NULL};
size_t call_order_i = 0;
static void save_call (const char* func)
{
call_order[call_order_i] = func;
call_order_i++;
if(call_order_i == CALL_ORDER_N)
{
call_order_i = 0;
}
}
static bool is_call_order_ok (void)
{
const char* expected_order [CALL_ORDER_N] =
{
"myFunction1",
"myFunction2",
"myFunction3"
};
size_t co_i = call_order_i;
for(size_t i=0; i<CALL_ORDER_N; i++)
{
if(strcmp(call_order[co_i], expected_order[i])==0)
{
co_i++;
if(co_i == CALL_ORDER_N)
{
co_i = 0;
}
}
else
{
return false;
}
}
return true;
}
void myFunction1 (void)
{
save_call(__func__);
}
void myFunction2 (void)
{
save_call(__func__);
}
void myFunction3 (void)
{
save_call(__func__);
}
int main (void)
{
printf("Call 1,2,3: ");
myFunction1();
myFunction2();
myFunction3();
printf(is_call_order_ok() ? "Ok\n" : "Failed\n");
printf("Call 3,2,1: ");
myFunction3();
myFunction2();
myFunction1();
printf(is_call_order_ok() ? "Ok\n" : "Failed\n");
printf("Call 1,1,1: ");
myFunction1();
myFunction1();
myFunction1();
printf(is_call_order_ok() ? "Ok\n" : "Failed\n");
return 0;
}
The advanced, more professional version of the above, would be to cook together a mini-API with a single function, in order to give private encapsulation to every single variable. The function save_call would then be a multi-purpose function, that can be used to register expected call order, save function calls, as well as verify if the current registered order is ok.
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define CALL_ORDER_N 3
static bool save_call (const char* func, bool verify)
{
bool result;
static const char* call_order [CALL_ORDER_N] = {NULL};
static size_t call_order_i = 0;
static const char* expected_order [CALL_ORDER_N] = {NULL};
size_t i = call_order_i;
if(verify) // special case, verify the order
{
for(size_t expected=0; expected<CALL_ORDER_N; expected++)
{
if(call_order[i] == expected_order[expected])
{
i++;
if(i == CALL_ORDER_N)
{
i = 0;
}
}
else
{
return false;
}
}
return true;
}
if(expected_order[i] == NULL) // register order of calls
{
expected_order[i] = func;
result = true;
}
else // save calls
{
call_order[i] = func;
result = false;
}
call_order_i++;
if(call_order_i == CALL_ORDER_N)
{
call_order_i = 0;
}
return result;
}
void myFunction1 (void)
{
if(save_call(__func__, false))
return ;
printf("Execute stuff in %s.\n", __func__);
}
void myFunction2 (void)
{
if(save_call(__func__, false))
return ;
printf("Execute stuff in %s.\n", __func__);
}
void myFunction3 (void)
{
if(save_call(__func__, false))
return ;
printf("Execute stuff in %s.\n", __func__);
}
int main (void)
{
/* register call order: */
myFunction1();
myFunction2();
myFunction3();
printf("Call 1,2,3:\n");
myFunction1();
myFunction2();
myFunction3();
printf(save_call(NULL, true) ? "Ok\n\n" : "Failed\n\n");
printf("Call 3,2,1:\n");
myFunction3();
myFunction2();
myFunction1();
printf(save_call(NULL, true) ? "Ok\n\n" : "Failed\n\n");
printf("Call 1,1,1:\n");
myFunction1();
myFunction1();
myFunction1();
printf(save_call(NULL, true) ? "Ok\n\n" : "Failed\n\n");
return 0;
}
save_call should of course be properly placed in a .h/.c file pair of its own.
There is no direct and portable way. That being said, debuggers are great at breaking execution flow when a function is reached, so you could either use a debugger, or use debugging functions to be warned when the functions are called (unfortunately nothing portable here).
Alternatively, some linkers allow to hide some identifiers and replace them so with custom (and advanced) link options you could replace all call to those functions with calls to custom wrappers. But here again it would only makes sense for a specific implementation so it is not a C way either.
Anyway, this is such an uncommon requirement that I cannot imagine the actual reasonning behind. Maybe you could give more context about your real problem...
I am new to programming and do not understand this error.
I have the same arguments in the Menu () function and when I call the same function in the menu_principal () function.
In function menu_principal(), I want execute the switch-case statement by the function Menu() with 'option' variable.
Can you help please?
int main()
{
void menu_principal();
return 0;
}
void menu_principal()
{
bool stop = true;
int option;
const char *title = "MENU PRINCIPAL";
const char *options_menu[] = { "ARTIGOS", "CLIENTES", "ORCAMENTOS", "SAIR" };
int n_options = 4;
do
{
option = Menu(title, options_menu, n_options);
switch (option)
{
case 1:
Menu_Item();
break;
case 2:
Menu_Client();
break;
case 3:
Menu_Billing();
break;
case 4:
stop = false;
break;
}
} while (stop);
}
int Menu(const char *title1, const char *options_menu1[], int n_options1)
{
int OptionSelected= 1;
int key;
bool stop = true;
do
{
system("cls");
gotoxy(5, 3 + OptionSelected); printf(">>");
gotoxy(15, 2); printf("%s", title1);
for (int i = 0; i < n_options1; i++)
{
gotoxy(10, 4 + i);
printf("%s ", options_menu1[i]);
}
do
{
key = _getch();
} while (key != KEY_UP && key != KEY_DOWN && key != KEY_ENTER );
switch (key)
{
case KEY_UP:
OptionSelected--;
if (OptionSelected < 1)
{
OptionSelected = n_options1;
}
break;
case KEY_DOWN:
OptionSelected--;
if (OptionSelected > n_options1)
{
OptionSelected = 1;
}
break;
case KEY_ENTER:
stop = false;
break;
}
} while (stop);
return OptionSelected;
}
The compiler reads your program top to bottom, so it sees:
option = Menu(title, options_menu, n_options);
On this line, you call a previously unknown function, Menu.
Because the function is unknown, the compiler assumes it will be int Menu(void). (takes no parameters, returns an int).
That assumption is obviously different from how Menu eventually gets declared.
To fix this, declare the function properly near the top of your file:
int Menu(const char *title1, const char *options_menu1[], int n_options1);
Then, when the compiler encounters your function-call, it will not assume a declaration, it will use the declaration you already provided (takes 3 parameters, and returns an int)
I'm making a virtual pet game, and I am now trying to include hunger, however I'm not sure how to make the eat function work. I am trying to make it decrease through the addition of the nutrition value of an item of food. This value is in an object that is stored in an arraylist.
Is there a way to reference
int nutrition(int eaten) {
nutrition = nutrition - eaten;
return nutrition;
(int eaten will be passed in later)
inside
ArrayList items;
void setup() {
items = new ArrayList();
}
void draw() {
for (int i = items.size() - 1; i >=0; i --) {
Food food = (Food) items.get(i);
food.display();
if (food.finished()) {
items.remove(i);
}
}
}
void mouseClicked() {
items.add(new Food(mouseX, mouseY, 1));
}
((Food)items.get(i)).nutrition();
http://www.java-forums.org/new-java/2370-how-return-object-arraylist.html
I've tried to use this, but Processing is unable to find i. I believe this to be because i does not exist in the class, only in the main sketch. If this is so, I will find a way to place i into the method. Maybe using return.
I would appreciate the knowledge if someone was aware of a better way to do this.
CODE
Creature creature;
ArrayList items;
Hand hand;
String data[];
int gameInfo[];
int tempData[];
boolean haveFood;
void setup() {
size(100, 100);
smooth();
noCursor();
String data[] = loadStrings("save.txt");
String[] tempData = split(data[0], ',');
gameInfo = int(tempData);
for (int i = 0; i < data.length; i++) {
creature = new Creature(gameInfo[0], gameInfo[1], gameInfo[2], gameInfo[3]);
haveFood = false;
hand = new Hand();
items = new ArrayList();
}
}
void draw() {
background(255);
for (int i = items.size() - 1; i >=0; i --) {
Food food = (Food) items.get(i);
food.display();
if (food.finished()) {
items.remove(i);
}
}
creature.whatWant();
creature.whatDo(haveFood);
hand.draw();
}
void mouseClicked() {
items.add(new Food(mouseX, mouseY, 1));
haveFood = true;
}
class Creature {
int hunger;
int age;
int gender;
int asleep;
boolean idle;
char want;
char request;
Creature(int _gender, int _age, int _hunger, int _asleep) {
gender = _gender;
age = _age;
hunger = _hunger;
asleep = _asleep;
idle = true;
}
void whatWant() {
if (hunger == 50) {
want = 'H';
}
}
void whatDo(boolean food) {
if (idle == true) {
switch(want) {
case 'H':
if (food == true) {
creature.eat();
}
else
request = 'F';
ask();
}
}
else
{
println("IDLE");
}
}
void ask() {
if (request == 'F') {
println("HUNGRY");
}
}
void eat() {
println("EAT");
((Food)items.get(i)).nutrition();
}
}
class Food {
float posX;
float posY;
int nutrition;
Food(float _posX, float _posY, int rating) {
posX = _posX;
posY = _posY;
nutrition = rating;
}
void display() {
rect(posX, posY, 10, 10);
}
boolean finished() {
if (nutrition < 0) {
return true;
}
else {
return false;
}
}
int nutrition(int eaten) {
nutrition = nutrition - eaten;
return nutrition;
}
}
class Hand {
int posX;
int posY;
Hand() {
posX = mouseX;
posY = mouseY;
}
void draw() {
rectMode(CENTER);
point(mouseX, mouseY);
}
}
Where save.txt is a txt file with 1,1,50,1,1.
Unfortunately I can't provide a nice detailed answer. There are quite a few confusing things with the structure of your project and it's code.
In the meantime, you had a syntax error in the Creature's eat() function.
Try this:
void eat() {
println("EAT");
//((Food)items.get(i)).nutrition();
for(int i = 0 ; i < items.size(); i++){
Food yummy = (Food)items.get(0);
yummy.nutrition(hunger);
}
}
The above works because items is declared at the top and therefore visible through out the scope of the whole sketch(global in other words). I'm not sure if this is intentional or what relationship you plan between creatures and food.
The above can be written in a lazier(but less common/obvious) way like so:
void eat() {
println("EAT");
//((Food)items.get(i)).nutrition();
for(Object yummy : items) ((Food)yummy).nutrition(hunger);
}
I assume the creature will be fed based on how hungry it.
At some point the creature should be full I suppose,
so you would also update the creature's hungry property based on the nutrition
it gets from food, etc.
Also, just to test, I've added very nutritious food :P
items.add(new Food(mouseX, mouseY, 10000));