Solved

function member

Posted on 1998-07-29
10
178 Views
Last Modified: 2011-09-20
Hi

I trie to write a program that uses menus.
I want to write a menu class that can be used for every menu that the user wants.
All the class users should do is to declare an object of this class , providing arguments. As the number of arguments is unknown at this time, I thought of declaring a constructor that takes a number of let's say 10 arguments( this will be now the max number of arguments that the object can take) give them implicit values. So when the user provides a number of arguments the rest of them will remain with the initial value( being pointers they just point to null).
I wrote the code and I am posting it now. But I do not like the way I had to write the thing every time for every argument. If I the function was main, I could have the argc argv convention so I could use a loop. This is what I am looking for, a way to avoid writting the code as many times as arguments.

Thank you.

Here is the code:
#include<iostream.h>
#include<string.h>
#include<conio.h>


class CMenu
{
      static float Choice;      
      char *menuItem[9];
public:
        CMenu(char *givenMenuItem1 = NULL, char *givenMenuItem2 = NULL, char *givenMenuItem3 = NULL, char *givenMenuItem4 = NULL, char *givenMenuItem5 = NULL);
        ~CMenu();
        void putMenu();
      void getChoice();
      void returnChoice(float&);
        void returnChoice(int&);
};

float CMenu::Choice;



CMenu::CMenu(char *givenMenuItem1, char *givenMenuItem2, char *givenMenuItem3, char *givenMenuItem4, char *givenMenuItem5)
{
      if(givenMenuItem1 != NULL)
      {
            menuItem[0] = new char[strlen(givenMenuItem1) + 1];
            strcpy(menuItem[0], givenMenuItem1);
      }
      else
            menuItem[0] = NULL;
      if(givenMenuItem2 != NULL)
      {
            menuItem[1] = new char[strlen(givenMenuItem2) + 1];
            strcpy(menuItem[1], givenMenuItem1);
      }
      else
            menuItem[1] = NULL;
   
      if(givenMenuItem3 != NULL)
      {
            menuItem[2] = new char[strlen(givenMenuItem3) + 1];
            strcpy(menuItem[2], givenMenuItem3);
      }
      else
            menuItem[2] = NULL;
      if(givenMenuItem4 != NULL)
      {
            menuItem[3] = new char[strlen(givenMenuItem4) + 1];
            strcpy(menuItem[3], givenMenuItem4);
      }
      else
            menuItem[3] = NULL;
      if(givenMenuItem5 != NULL)
    {
            menuItem[4] = new char[strlen(givenMenuItem5) + 1];
            strcpy(menuItem[4], givenMenuItem5);
      }
      else
            menuItem[4] = NULL;
      cout << "Constructor" << endl;

      
}
      
                  
CMenu::~CMenu()
{
      for(int count = 0; count < 5; count++)
            if(menuItem[count] != NULL)
                  delete menuItem[count];
      
}

void CMenu::putMenu()

{
      cout << "\n\n\t\tEnter your choice" << endl;
      for(int count = 0; count < 10 && menuItem[count] != NULL;count++)
            cout << "\t\t" << count + 1 << "." << menuItem[count] << endl;
      cout << "Press any key to continue" << endl;
}

void CMenu::getChoice()
{
      cout << "getChoice" << endl;
      cin >> Choice;
      cout << "getChoice" << endl;
}

void CMenu::returnChoice(float& passChoice)
{
      passChoice = Choice;
      
}

void CMenu::returnChoice(int& passChoice)
{
      passChoice = (int)Choice;
}

int main()
{
CMenu generalMenu("FIRST", "SECOND");
      
      generalMenu.putMenu();
      generalMenu.getChoice();
      int givenPassChoice;
      generalMenu.returnChoice(givenPassChoice);
      cout << "The choice is = " << givenPassChoice << endl;

      return 0;
}
0
Comment
Question by:simi
  • 8
  • 2
10 Comments
 
LVL 22

Accepted Solution

by:
nietod earned 50 total points
ID: 1168994
answer coming.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1168995
It sounds like you need a "variable argument list" function (that is the official name).  These are functions that are called like printf() where you specify one or more "fixed" parameters followed by any number of "variable" parameters.  These functions are declared by using an ellipsies at the end of the parameter list like.

int SomeFunction(int Fixedparameter, ...)

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 1168996
When you write a function that takes varialbe argument lists, you need to develop a mechanism that the caller uses to indicate how many variable parameters have been passed (sometimes their type as well.)  For example printf() looks at the string passed in the first parameter and knows that each time it comes to an %XXXX item that there is a cooresponding parameter.  Another approach is to pass an integer count of the number of varaible parameters.  In your case I would pass any number of pointers to strings (menu titles).  With the last one being indicated by a NULL pointer.  Thus you would create a 3 item menu like

CMenu generalMenu("FIRST", "SECOND","THIRD",NULL);

continues.
0
Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

 
LVL 22

Expert Comment

by:nietod
ID: 1168997
To access the variable parameters, you need to use the va_start and va_arg macros.  

Let me know if you have any questions.
0
 

Author Comment

by:simi
ID: 1168998
I think I did not made clear my question.
My problem is not how to pass an undefined ( unlimited) number of parameters to the function. I can handle this by declaring the constructor as receiving a big number of parameters, like 20, becaus I don;t think that someone would like to have too many menuitems in the same menu. I can declare those parameters as pointers and set them to NULL. This way the user can provide two, three or nineteen parameter, the rest will be considered as having default values.
The question is that for every parameter I have to alocate memory for the array variable where I want to store the value, and to copy the value there. I was looking for a way to say like
for(count = 0; count < max_nr_of_arguments && argument[count] != NULL; count++)
{
allocate memory for the array member.
copy the value of the given_parameter[count] in array_member[count]
}

that instead of doing it as many times as passed parameters one by one.

It looks like you are suggesting something when you talk about va_start and va_arg but I have to read about them as I do not know what they mean.

Thanks
0
 
LVL 22

Expert Comment

by:nietod
ID: 1168999
I think the best way to store the information is to use a dynamicaly allocated array of pointers to dynamically allocated strings.  Like

int MenItmCnt = ???;  // set to the number of menu items to store.

char **MenNamTbl = char *[MenItmCnt]; // Allocate array to store pointers to strings.
                                                    // this array would be a member of the class, not a local variable.

for (i = 0; i < MenItmCnt; ++i)
{
    char *ItmNam = ????; // Get pointer to item name parameter to be used.
    MenNamTbl[i] = new char[strlen(ItmNam) + 1] ; // Allocate memory for item name.
    strcpy(MenNamTbl[i],ItmNam); // Copy in item name.
}

the ??? marks are for information you will have to fill in.  You could fill it in using your current approach, but you will find that cumbersome.  I thing you will find the ... approach easier..  But it can be done either way.  

Questions?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1169000
you said
>>what I am looking for, a way to avoid writting the code as many times as arguments

for that you should try a variable argument list and the va_start and va_arg macros.  (You could actually use the macros without the variable argument list, but there is no advantage.  Once you are going to use the macros, you might as well get the other advantages of the variable arguments for free.
0
 

Author Comment

by:simi
ID: 1169001
I read about the va_arg etc.
Here's where I got with the code.
I have problems with the destructor. It works up to this point, but when the first element of the menuItem array is deleted, it gives an error message and it freezes.

I read about the va_arg in my Borland C++ compiler, that it can not be used with char, unsigned char and float. In my Ms Visual C++ compiler it doesn;t say so. Hence, both compilers give examples where the received parameters are integers. Mine are strings. Is that the cause ?

Thanks
#include<iostream.h>
#include<string.h>
#include<conio.h>
#include<stdarg.h>


class CMenu
{
      static float Choice;      
      char **menuItem;
      char *messageBuffer;
public:
        CMenu(char *msg...);
        ~CMenu();
        void putMenu();
      void getChoice();
      void returnChoice(float&);
        void returnChoice(int&);
};

float CMenu::Choice;



CMenu::CMenu(char *msg,...)
{
      
      cout << "Beginning constructor" << endl;
      va_list ap;
      va_start(ap, msg);
      char *arg;
      int count = 0;
      messageBuffer = new char[strlen(msg)];
      strcpy(messageBuffer, msg);
      cout << messageBuffer << endl;
      while (strcmp((arg = va_arg(ap, char* )),"NULL") != 0)
      {
            cout << "Inside while" << endl;
            menuItem[count] = new char[strlen(arg)];
            strcpy(menuItem[count], arg);
            count++;
      }
      menuItem[count] = NULL;
      va_end(ap);
}
                  
CMenu::~CMenu()
{
      cout << "Destructor beginning" << endl;
      for(int count = 0; menuItem[count] != NULL; count++)
      {
            cout << "Inside the for loop" << endl;
            cout << "menuItem[count]=" << menuItem[count] << endl;
            delete [] menuItem[count];
            cout << "Inside the for loop end" << endl;
      }
      cout << "Destructor ends" << endl;
      
}

void CMenu::putMenu()

{
      cout << "\n\n\t\t" << messageBuffer << endl;
      for(int count = 0; menuItem[count] != NULL;count++)
            cout << "\t\t" << count + 1 << "." << menuItem[count] << endl;
      cout << "Press any key to continue" << endl;
}

void CMenu::getChoice()
{
      cout << "getChoice" << endl;
      cin >> Choice;
      cout << "getChoice" << endl;
}

void CMenu::returnChoice(float& passChoice)
{
      passChoice = Choice;
      
}

void CMenu::returnChoice(int& passChoice)
{
      passChoice = (int)Choice;
}

int main()
{
CMenu generalMenu("What do you want to", "pula","pizda", "craci",  "NULL");
      
      generalMenu.putMenu();
      generalMenu.getChoice();
      int givenPassChoice;
      generalMenu.returnChoice(givenPassChoice);
      cout << "The choice is = " << givenPassChoice << endl;

      return 0;
}
0
 
LVL 22

Expert Comment

by:nietod
ID: 1169002
char, and unsigned char can be passed.  The procedure will receive them as ints and unsigned ints. float can be passed as received as double.  This has not effect on you since you are passing pointers.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1169003
in
>> class CMenu
>>     {
>>     static float Choice;      
>>     char **menuItem;
>>     char *messageBuffer;
>>// removed stuff to save space
>>     };

you probably don't need messageBuffer.  That is used only in one function, so declare it in that function.  The class should only store data that is preserved between functions.

The dynamically allocated string pointer array

>> char **menuItem;

is never allocated.  you use this arrray (pointer to an array) without creating it.

>>messageBuffer = new char[strlen(msg)];
>>   strcpy(messageBuffer, msg);

you need to allocate "strlen(msg) + 1" characters to have room for the NUL terminator.at the end of the string.  
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question