Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> undefined symbol 
:(
    Опции темы
=Женек=
Дата 19.3.2006, 11:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



Код

typedef __flash struct _TMenuItem
    {
        char title[16];
        int type;                
        __flash struct _TMenuItem *parent;
        __flash struct _TMenuItem *submenu;
    } TMenuItem;


TMenuItem __flash Options[2]=
             {
               {"Option 1", 1, MainMenu , NULL},
               {"Option 2", 1, MainMenu , NULL}              
             };
           
TMenuItem __flash Channels[2]=
             {
               {"Channel 1", 1, MainMenu , NULL},
               {"Channel 2", 1, MainMenu , NULL}              
             };
            



TMenuItem __flash MainMenu[2]=
             {
               {"Options", 1, NULL , Options},
               {"Channels", 1, NULL ,Channels}              
             };



Бред получается. Как ни располагаю менюшки - всегда будет ошибка undefined symbol. Понятно что при указании идентификатора, он уже должен быть описан ранее.


Как разорвать замкнутый круг?
PM MAIL   Вверх
MAKCim
Дата 19.3.2006, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Код

typedef struct _TMenuItem
    {
        char title[16];
        int type;                
        struct _TMenuItem *parent;
        struct _TMenuItem *submenu;
    } TMenuItem;

TMenuItem Options[2]=
             {
               {"Option 1", 1, MainMenu , NULL},                    //где MainMenu???
               {"Option 2", 1, MainMenu , NULL}              
             };
           
TMenuItem Channels[2]=
             {
               {"Channel 1", 1, MainMenu , NULL},
               {"Channel 2", 1, MainMenu , NULL}              
             };
            
TMenuItem MainMenu[2]=
             {
               {"Options", 1, NULL , Options},                          //где Options?
               {"Channels", 1, NULL ,Channels}                    //где Channels?
             };



--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
=Женек=
Дата 19.3.2006, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



ЧТо за вопросы? Или продери глаза или без намеков.
Хочу добавить - что пишу в AVR С (для микроконтроллеров). И когда небыло параметра parent, то все работало. А именно в MainMenu параметр Options указывал на TMenuItem Options
PM MAIL   Вверх
srd
Дата 19.3.2006, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Код

typedef __flash struct _TMenuItem
    {
        char title[16];
        int type;                
        __flash struct _TMenuItem *parent;
        __flash struct _TMenuItem *submenu;
    } TMenuItem;

extern TMenuItem MainMenu[];

TMenuItem __flash Options[2]=
             {
               {"Option 1", 1, MainMenu , NULL},
               {"Option 2", 1, MainMenu , NULL}              
             };
           
TMenuItem __flash Channels[2]=
             {
               {"Channel 1", 1, MainMenu , NULL},
               {"Channel 2", 1, MainMenu , NULL}              
             };
            
TMenuItem __flash MainMenu[2]=
             {
               {"Options", 1, NULL , Options},
               {"Channels", 1, NULL ,Channels}              
             };




--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
=Женек=
Дата 19.3.2006, 13:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



Ух ты.. Только вот так:
Код

extern TMenuItem __flash MainMenu[];


Спасибо!! Вроде компилятор не ругается... Ща посмотрим в деле...
PM MAIL   Вверх
=Женек=
Дата 19.3.2006, 19:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



ТЕперь я что-то с указателями запутался...

Код

void EnterMenuItem(TMenuItem __flash *point_to_menu)
{
 int i=0;
 char *s=r; 
 LcdClear();  


while (point_to_menu[i].title != NULL)
{
           LcdGotoXY(2,i+1);
            sprintf(s,"%p", point_to_menu[i].title);
            LcdStr(FONT_1X, s, NORMAL);  
            i++;
            LcdUpdate();
}

 LcdSelect(0);
 LcdUpdate();
}



Подозреваю что point_to_menu[i].title != NULL - лажа.. Как правильно.

P.S. Функция вызвана так: EnterMenuItem(MainMenu); Описание MainMenu в этой теме выше.
PM MAIL   Вверх
MAKCim
Дата 19.3.2006, 19:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

Подозреваю что point_to_menu[i].title != NULL - лажа.. К

насколько я понимаю title всегда не NULL
контролируй сколько у тебя объектов TMenuItem (передавай
size и делай проверку i<size)


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
srd
Дата 19.3.2006, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Либо передавай в функцию количество элементов в массиве, как было предложено выше, либо добавь в конец массива элемент, служащий признаком конца:
Код

TMenuItem __flash MainMenu[2]=
             {
               {"Options", 1, NULL , Options},
               {"Channels", 1, NULL ,Channels},
               {NULL, 0, NULL, NULL}              
             };




--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
=Женек=
Дата 19.3.2006, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



Я уже делал вот так:
Код

         for (i=0;i<point_to_menu->count;i++) 
          {
            LcdGotoXY(2,i+1);
            sprintf(s,"%p", point_to_menu[i].title);
            LcdStr(FONT_1X, s, NORMAL);  
           }    





Тогда менюшку приходится объявлять вот так:

Код

TMenuItem __flash MainMenu[]=
             {
               {"Ïîèñê", 1,  3, NULL , Search},
               {"Êàíàëû", 1, 3, NULL , Channels},
               {"Íàñòðîéêè", 1, 3, NULL , Options}
             } ;




Лажа получается - в MainMenu 3 раза встречается число его собственных элементов. По-моему избыточно. Если же параметр count назначать по отношению к подменю, то обратиться к нему еще сложнее.
Поэтому я и хочу не считать число элементов, а просто выводить их пока очередной point_to_menu существует. Вот только пишу неграмотно.

Подскажите, как.

P.S. можно конечно передавать в функцию, но согласитесь это лишнее, если информация уже известна.
Насчет признака конца я уже думал. Но какая разница, что ты прочтешь признак конца, что определишь что 4-й (в данном случае) элемент отсутствует. Вот я и хочу знать как это сделать..

ПОймте, я пишу под AVR - всего 8кб кода и 1 кб оперативной памяти. Вот и приходится делать вещи, на которые в обычном C я уже плюнул бы.

Это сообщение отредактировал(а) =Женек= - 19.3.2006, 19:43
PM MAIL   Вверх
srd
Дата 19.3.2006, 19:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Цитата(=Женек= @ 20.3.2006, 02:42 Найти цитируемый пост)
Насчет признака конца я уже думал. Но какая разница, что ты прочтешь признак конца, что определишь что 4-й (в данном случае) элемент отсутствует. Вот я и хочу знать как это сделать..

Разница в том, что нулевой элемент в конце массива позволяет писать код в виде:
Код

...
while (point_to_menu[i].title != NULL) {
...

что вроде и требовалось. В любом случае, это гораздо лучше, чем заводить поле с количеством элементов в каждом элементе smile

Цитата(=Женек= @ 20.3.2006, 02:42 Найти цитируемый пост)
можно конечно передавать в функцию, но согласитесь это лишнее, если информация уже известна.

Вот проблема как раз в том, что в функции ничего не известо про количество элементов. У неё на входе ничего нет кроме одного указателя smile

З.Ы.
Можно так:
Код

TMenuItem __flash MainMenu[2]=
             {
               {"Options", 1, NULL , Options},
               {"Channels", 1, NULL ,Channels},
             };
#define MAINMENU_COUNT (sizeof (MainMenu) / sizeof (MainMenu[0]))

void EnterMenuItem(TMenuItem __flash *point_to_menu, size_t item_count)
{
    size_t i;

    while (i = 0; i < item_count; ++i)
    {
        /* ... */
    }
    /* ... */
}

И вызывать функцию так:
Код

EnterMenuItem(MainMenu, MAINMENU_COUNT);

Макрос статической памяти не занимает.


Это сообщение отредактировал(а) srd - 19.3.2006, 19:54


--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
=Женек=
Дата 19.3.2006, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



Код

TMenuItem __flash MainMenu[4]=
             {
               {"Ïîèñê", 1,  3, NULL , Search},
               {"Êàíàëû", 1, 3, NULL , Channels},
               {"Íàñòðîéêè", 1, 3, NULL , Options},
               {NULL, 0, 0, NULL , NULL}               
             } ;


/////////////////////////////

while (point_to_menu[i].title != NULL)
{
           LcdGotoXY(2,i+1);
            sprintf(s,"%p", point_to_menu[i].title);
            LcdStr(FONT_1X, s, NORMAL);  
            i++;
            LcdUpdate();
}



Эх.... проскакивает она конец...
Добавлено @ 20:23
Секунду... если я передаю в функцию указатель на MainMenu, то внутри функции количество элементов массива нельзя посчитать?
PM MAIL   Вверх
srd
Дата 19.3.2006, 20:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Сейчас посмотрел внимательно на определение структуры - у тебя оказывается title - не указатель на строку а массив символов. Тогда надо так:
Код

TMenuItem __flash MainMenu[2]=
             {
               {"Options", 1, NULL , Options},
               {"Channels", 1, NULL ,Channels},
               {"", 0, NULL, NULL}
             };
/* ... */
while (point_to_menu[i].title[0] != '\0') {

Добавлено @ 20:29
Цитата(=Женек= @ 20.3.2006, 03:14 Найти цитируемый пост)
Секунду... если я передаю в функцию указатель на MainMenu, то внутри функции количество элементов массива нельзя посчитать?

Совершенно верно
Код

MainMenu a[2]; /* Здесь a - идентификатор массива. Компилятор знает размер каждого элемента, количество элементов и адрес, с которого начинается массив */
MainMenu *p = a; /* Здесь p - указатель. Компилятор знает размер каждого элемента и адрес, но он не имеет никакого понятия о количестве элементов */



--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
=Женек=
Дата 19.3.2006, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



работает.

А в другом месте:
Код

current_point=MainMenu;
selection_pos=0;  
//////////////////
       if (current_point[selection_pos].title[0] !='\0')  


не работает. Пишет "can't subscript away"
Добавлено @ 21:40
В начале еще было
TMenuItem __flash *current_point;
PM MAIL   Вверх
=Женек=
Дата 21.3.2006, 07:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



Хм.. так ниче и не получилось..
PM MAIL   Вверх
srd
Дата 21.3.2006, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Мало информации. По идее такой синтаксис совершенно законный. Попробуй создать короткий пример, воспроизводящий эту проблему на твоём компиляторе, и проверь его на какому-нибудь другом компиляторе. Я, например, не могу сооборазить, что означает сообщение "can't subscript away".


--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
=Женек=
Дата 21.3.2006, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



Это работает:
Код

layer_items=(sizeof (MainMenu) / sizeof (MainMenu[0]));


А вот это не работает:

Код

TMenuItem __flash *current_point;
current_point=MainMenu;
layer_items=(sizeof (current_point) / sizeof (current_point[0]));

PM MAIL   Вверх
srd
Дата 21.3.2006, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Цитата(=Женек= @ 21.3.2006, 23:12 Найти цитируемый пост)

Код

TMenuItem __flash *current_point;
current_point=MainMenu;
layer_items=(sizeof (current_point) / sizeof (current_point[0]));


А это и не должно работать. sizeof (MainMenu) - это размер массива, а sizeof (curren_point) - это размер указателя, а не массива. Кажется, я это писал выше по теме.




--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
=Женек=
Дата 21.3.2006, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



Да, писал... Я это понял. Я это к тому что формула приведенная не подходит...
PM MAIL   Вверх
=Женек=
Дата 21.3.2006, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



Srd, если не сложно, помогите советом. ПРилагаю код (функции вырезал, дабы проще было разобраться).

Как бы вы решили задачу определения количества пунктов меню при заходе в дочернее подменю, и, самое главное - при возвращении в родительское

меню. Комментарии прилагаются

Заранее благодарен.

Код



// ИНИЦИАЛИЗАЦИЯ ПУНКТОВ МЕНЮ

typedef __flash struct _TMenuItem
    {
        char title[16];
        int type;   
        int count;             
        __flash struct _TMenuItem *parent;
        __flash struct _TMenuItem *submenu;
    } TMenuItem;

extern TMenuItem __flash MainMenu[];
extern TMenuItem __flash Search[];
extern TMenuItem __flash Options[];
extern TMenuItem __flash Channels[];

TMenuItem __flash Search[]=
             {
               {"Начать",  1, 0, MainMenu, NULL},
               {"Кончить", 1, 0, MainMenu, NULL},
               {"Выйти",   1, 0, MainMenu, NULL},
               {"", 0, 0, NULL , NULL}                              
             } ;

TMenuItem __flash Sub1[]=
             {
               {"Sub1 A", 1, 0, Options, NULL},
               {"Sub1 B", 1, 0, Options, NULL},
               {"Sub1 C", 1, 0, Options, NULL},
               {"Sub1 D", 1, 0, Options, NULL},
               {"Sub1 E", 1, 0, Options, NULL},
               {"", 0, 0, NULL , NULL}                                                            
             } ;

TMenuItem __flash Sub2[]=
             {
               {"Sub2 A", 1, 0, Options, NULL},
               {"Sub2 B", 1, 0, Options, NULL},
               {"Sub2 C", 1, 0, Options, NULL},
               {"", 0, 0, NULL , NULL}                              
             } ;

TMenuItem __flash Sub3[]=
             {
               {"Sub3 A", 1, 0, Options, NULL},
               {"Sub3 B", 1, 0, Options, NULL},
               {"Sub3 C", 1, 0, Options, NULL},
               {"", 0, 0, NULL , NULL}                              
             } ;

  
TMenuItem __flash Options[]=
             {
               {"Option 1", 1, 5, MainMenu, Sub1},
               {"Option 2", 1, 3, MainMenu, Sub2},
               {"Option 3", 1, 3, MainMenu, Sub3},
               {"", 0, 0, NULL , NULL}                              
             } ;

TMenuItem __flash Channels[]=
             {
               {"Channel 1", 1, 0, MainMenu, NULL},
               {"Channel 2", 1, 0, MainMenu, NULL},
               {"Channel 3", 1, 0, MainMenu, NULL},
               {"", 0, 0, NULL , NULL}                              
             } ;

            

TMenuItem __flash MainMenu[]=
             {
               {"Поиск", 1,  3, NULL , Search},
               {"Каналы", 1, 3, NULL , Channels},
               {"Настройки", 1, 3, NULL , Options},
               {"", 0, 0, NULL , NULL}               
             } ;


////////////////////////////////////////////////////////////////////////////////////  

void EnterMenuItem(TMenuItem __flash *point_to_menu, int count)
{
 int i,j=0;
 char *s=r; 
 LcdClear();  
 
 for (i=0;i<count;i++)
  {
   LcdGotoXY(2,i+1);
    sprintf(s,"%p", point_to_menu[i].title);
    LcdStr(FONT_1X, s, NORMAL);  
  }

  

 LcdSelect(0);
 LcdUpdate();
}



void main ()
{
int i, selection_pos, layer_items;
char *s=r; 
TMenuItem __flash *current_point;

LcdInit();
Delay();

DDRD=0x00;
PORTD=0xFF;
LcdInit();
Delay();   

current_point=MainMenu;
selection_pos=0;  
layer_items=3;
EnterMenuItem(current_point,layer_items);

LcdUpdate();     
for(;;)
{

   if (!PIND.0)     // Нажата клавиша "вниз"
     {
      if (selection_pos>layer_items) continue;
        LcdSelect(selection_pos);
        selection_pos++;         
        LcdSelect(selection_pos);      

     }
  
   if (!PIND.1)                // Нажата клавиша "верх" 
     {
      if (selection_pos==0) continue;
      LcdSelect(selection_pos);
      selection_pos--;         
      LcdSelect(selection_pos);      
    }

   if (!PIND.2)                // Нажата клавиша "Enter" (вход в подменю)
     {
        if (current_point[selection_pos].submenu==NULL) continue;
           layer_items=current_point[selection_pos].count;                                                  
           current_point=current_point[selection_pos].submenu;
           EnterMenuItem(current_point,layer_items);
           selection_pos=0;       
    }

   if (!PIND.3)                 // Нажата клавиша выхода в родительское меню) 
     {
        if (current_point[selection_pos].parent==NULL) continue;
          current_point=current_point[selection_pos].parent;
          layer_items=current_point[selection_pos].count;                                                  
          EnterMenuItem(current_point, layer_items);
          selection_pos=0;       

    }

   LcdUpdate();

}

}
/*--------------------------------------------------------------------------------------------------
                                         End of file.
--------------------------------------------------------------------------------------------------*/


PM MAIL   Вверх
srd
Дата 21.3.2006, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Насколько я понял, требуется что-то вроде такого (здесь просто иллюстрация, написанная в таком виде, чтобы его можно было быстро скомпилировать и посмотреть):
Код

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

struct Menu;

/* Каждый пункт меню имеет текст, тип(?) и указатель на подменю */
struct MenuItem
{
    char text[16];
    int type;
    struct Menu *submenu;
};

/* Меню имеет укатель на массив пунктов, количество пунктов и указатель на родительское меню */
struct Menu
{
    struct MenuItem *items;
    int item_count;
    struct Menu *parent;
};

extern struct Menu main_menu;

struct MenuItem search_items[] =
{
    {"Start", 1, NULL},
    {"Finish", 1, NULL},
    {"Quit", 1, NULL}
};
struct Menu search_menu = {search_items, sizeof search_items / sizeof search_items[0], &main_menu};

struct MenuItem channels_items[] =
{
    {"Channel 1", 1, NULL},
    {"Channel 2", 1, NULL},
    {"Channel 3", 1, NULL}
};
struct Menu channels_menu = {channels_items, sizeof channels_items / sizeof channels_items[0], &main_menu};

struct MenuItem options_items[] =
{
    {"Option 1", 1, NULL},
    {"Option 2", 1, NULL},
    {"Option 3", 1, NULL}
};
struct Menu options_menu = {options_items, sizeof options_items / sizeof options_items[0], &main_menu};

struct MenuItem main_items[] =
{
    {"Search", 1, &search_menu},
    {"Channels", 1, &channels_menu},
    {"Options", 1, &options_menu}
};
struct Menu main_menu = {main_items, sizeof main_items / sizeof main_items[0], NULL};

int main()
{
    struct Menu *current_menu = &main_menu;
    int i;
    int selected;

    for (;;)
    {
        /* выводим меню на экран */

        printf("=====================\n");
        for (i = 0; i < current_menu->item_count; ++i)
        {
            printf("Menu text == \"%s\", menu type == %d\n",
                current_menu->items[i].text,
                current_menu->items[i].type);
        }
        printf("=====================\n\n");

        // читаем введённый номер
        selected = _getch() - (int)'0' - 1;

        if (selected < 0 || current_menu->item_count <= selected)
        {
            printf("Invalid menu item number\n");

            /* Если указан ошибочный пункт, то возвращаемся в родительское меню */

            if (current_menu->parent != NULL)
                current_menu = current_menu->parent;
            else
            {
                /* Если нет родительского меню, то выходим */
                break;
            }
        }
        else
        {
            if (current_menu->items[selected].submenu != NULL)
            {
                /* Если у выбранного пункта есть подменю, то переходим в него */
                current_menu = current_menu->items[selected].submenu;
            }
            else
            {
                /* Иначе просто печатаем выбранный пункт */
                printf("Selected == \"%s\"\n", current_menu->items[selected].text);
            }
        }
    }

    return 0;
}

Возможно, кто-то предложит вариант лучше.


--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
=Женек=
Дата 21.3.2006, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 548
Регистрация: 20.2.2005

Репутация: нет
Всего: 1



Спасибо за пример, он интересен, но...
Я конечно плохо знаю С, но все же имею представлени о том, что такое программирование вообще.

Нерационально хранить отдельно информацию о количестве элементов массива, если у нас есть сам массив. Да, можно конечно передавать это количество в функуию и программа будет работать, но это извращение. Любая программа должна быть самодостаточна.

Так вот, если у нас есть массив, то даже если нет функции, которая считает элементы, можно их вручную посчитать.
Однако тут ни один вариант не прокатил...


Мне все же непонятно - даже если мы работаем с указателями - вот так:

sprintf(s,"%p", point_to_menu[i].title);

то неужели нельзя определить существует ли point_to_menu[i].title для данного i?
Внутри вышеописанной функции EnterMenuItem это работало - через !=Null.

Когда же я определил current_point в теле главной функции - проверка на NULL не срабатывает...

PM MAIL   Вверх
srd
Дата 21.3.2006, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Цитата(=Женек= @ 22.3.2006, 01:55 Найти цитируемый пост)
Нерационально хранить отдельно информацию о количестве элементов массива, если у нас есть сам массив. Да, можно конечно передавать это количество в функуию и программа будет работать, но это извращение. Любая программа должна быть самодостаточна.

Да без проблем, но только никакой экономии тут нет. Проще хранить количесво элементов, чем каждый раз его считать.
Код

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

struct Menu;

/* Каждый пункт меню имеет текст, тип(?) и указатель на подменю */
struct MenuItem
{
    const char *text;
    int type;
    struct Menu *submenu;
};

/* Меню имеет укатель на массив пунктов, количество пунктов и указатель на родительское меню */
struct Menu
{
    struct MenuItem *items;
    struct Menu *parent;
};

extern struct Menu main_menu;

struct MenuItem search_items[] =
{
    {"Start", 1, NULL},
    {"Finish", 1, NULL},
    {"Quit", 1, NULL},
    {NULL, 0, NULL}
};
struct Menu search_menu = {search_items, &main_menu};

struct MenuItem channels_items[] =
{
    {"Channel 1", 1, NULL},
    {"Channel 2", 1, NULL},
    {"Channel 3", 1, NULL},
    {NULL, 0, NULL}
};
struct Menu channels_menu = {channels_items, &main_menu};

struct MenuItem options_items[] =
{
    {"Option 1", 1, NULL},
    {"Option 2", 1, NULL},
    {"Option 3", 1, NULL},
    {NULL, 0, NULL}
};
struct Menu options_menu = {options_items, &main_menu};

struct MenuItem main_items[] =
{
    {"Search", 1, &search_menu},
    {"Channels", 1, &channels_menu},
    {"Options", 1, &options_menu},
    {NULL, 0, NULL}
};
struct Menu main_menu = {main_items, NULL};

struct MenuItem *get_menu_item(struct Menu *menu, int index)
{
    struct MenuItem *item = menu->items;
    int i = 0;

    while (item->text != NULL)
    {
        if (index == i)
            return item;
        ++item;
        ++i;
    }

    return NULL;
}

int main()
{
    struct Menu *current_menu = &main_menu;
    struct MenuItem *item;
    int selected;

    for (;;)
    {
        /* выводим меню на экран */

        printf("=====================\n");
        for (item = current_menu->items; item->text != NULL; ++item)
        {
            printf("Menu text == \"%s\", menu type == %d\n",
                item->text,
                item->type);
        }
        printf("=====================\n\n");

        // читаем введённый номер
        selected = _getch() - (int)'0' - 1;
        item  = get_menu_item(current_menu, selected);

        if (item == NULL)
        {
            printf("Invalid menu item number\n");

            /* Если указан ошибочный пункт, то возвращаемся в родительское меню */

            if (current_menu->parent != NULL)
                current_menu = current_menu->parent;
            else
            {
                /* Если нет родительского меню, то выходим */
                break;
            }
        }
        else
        {
            if (item->submenu != NULL)
            {
                /* Если у выбранного пункта есть подменю, то переходим в него */
                current_menu = item->submenu;
            }
            else
            {
                /* Иначе просто печатаем выбранный пункт */
                printf("Selected == \"%s\"\n", item->text);
            }
        }
    }

    return 0;
}




--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0722 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.