Solved

passing back an char[][]??

Posted on 1998-08-21
14
237 Views
Last Modified: 2010-08-05
Ok till I get to out main database I was writing a quick hack.  Anyhow what I have is a DB class to returns some basic things.  One thing I wanted to get back is an and array of char*.  

So in the DB class I have a struct { ... char x[5][50] }

somehow I want to pass back a pointer to this.  I tried char** tried void*. gave up on that.  then I tried using char** and some combination of new char*[5] then new char[50] couldn't seem to get it to allocate.  How can I do any of this?

In otherwords I want to pass back a list of strings.  I don't care how.  I know I shouldn't be passing a pointer back, but the class will be going away soon.
0
Comment
Question by:micah
  • 6
  • 4
  • 2
  • +1
14 Comments
 
LVL 5

Expert Comment

by:ecw
ID: 1170857
make a typedef to an [5][50] array of chars, and get you func to return a pointer to this type ie.:

typedef char x_t[5][50];

x_t *func(DB &d)
{
return &d.x;
}
0
 
LVL 22

Expert Comment

by:nietod
ID: 1170858
ecw's answer is right according to what you requested.  However, waht you asked for might not be what you want.  In many cases and array of strings is best implimented using an array of character pointers, that is, by using "char * []".  Wethor or not that is better depends on what you are trying to do. If you supply more details as to the nature of the data and the way in which it will be used, I might be able to ofter some suggestions.  In any case, ecw has provided a solution that will work.
0
 
LVL 5

Expert Comment

by:ecw
ID: 1170859
Yeah but if you store a char[][] in a class, you know that's what you get with every instance of the class- no further memory allocs needed.  My preference is to store things as char*[], or char**, because I hate boundaries, but it is not always appropriate, or always worth the effort.
In this case,  the class is "going away soon", so changing the storage layout isn't worth the effort.
0
 

Author Comment

by:micah
ID: 1170860
char*[] ? not sure I understand you there.  Here is my code


what does it take to pass back _nextHigher?  Once it is passed back how do I print out each element. When I pass it back now it seems to get stomped.  






#ifndef __DB
#define __DB

#include "Device.h"
//
// a realy crappy database
//

struct dbStruct{
  char        _name[50];
  DEVICETYPE  _deviceType;
  char **     _nextHigher;
  int         _nextHigherCount;
  char        _tool[50];

};

class DB{
 public:
  DB();
  ~DB();
  DEVICETYPE getDeviceType(char* name);

  int getNextHigher(char* name,char** data);

  char* getTool(char* name);

 private:
  int findName(char* name);
  dbStruct _data[30];
  int _size;
};
#endif

#include "DB.h"
#include <string.h>

DB::DB(){

  for(int i=0;i<30;i++){
    _data[i]._nextHigher = new char*[5];      
    for(int j=0;j<5;j++)
      _data[i]._nextHigher[j]=new char[50];
  }      
  strcpy(_data[0]._name,"panel");      
  _data[0]._deviceType = PANEL;
  strcpy(_data[0]._nextHigher[0],"fastener_p");
  _data[0]._nextHigherCount=1;
  strcpy(_data[0]._tool,"NULL");

  strcpy(_data[1]._name,"ratchet");                  
  _data[1]._deviceType = ROTATIONAL_TOOL;
  strcpy(_data[1]._nextHigher[0],"NULL");
  _data[1]._nextHigherCount=0;
  strcpy(_data[1]._tool,"NULL");

  strcpy(_data[2]._name,"fastener_p");                  
  _data[2]._deviceType = FASTENER;
  strcpy(_data[2]._nextHigher[0],"NULL");
  _data[2]._nextHigherCount=0;      
  strcpy(_data[2]._tool,"ratchet");

  strcpy(_data[3]._name,"LRU");                  
  _data[3]._deviceType = GENERIC;
  strcpy(_data[3]._nextHigher[0],"fastener_p");
  strcpy(_data[3]._nextHigher[1],"harness_p");
  _data[3]._nextHigherCount=2;      
  strcpy(_data[3]._tool,"NULL");

  strcpy(_data[4]._name,"harness_p");                  
  _data[4]._deviceType = HARNESS;
  strcpy(_data[4]._nextHigher[0],"NULL");
  _data[4]._nextHigherCount=0;      
  strcpy(_data[4]._tool,"NULL");  
 
 _size = 5;
}


DB::~DB(){
  for(int i=0;i<30;i++){
    for(int j=0;j<5;j++)
      delete [] _data[i]._nextHigher[j];
    delete [] _data[i]._nextHigher;
  }      
}

DEVICETYPE        DB::getDeviceType(char* name){
  int i=findName(name);
  if( i >=0 )
      return _data[i]._deviceType;
    return INVALID;
 
}
 

int             DB::getNextHigher(char* name,char** data)
{
  int i=findName(name);
  if(i >=0 ){
    data = &_data[i]._nextHigher;
    return _data[i]._nextHigherCount;
  }
  else
    return 0;
}

char*             DB::getTool(char* name){
  int i=findName(name);      
  if(i >=0 )
    return _data[i]._tool;
  else
    return NULL;
}
//
/** PRIVATE **/
//
int            DB::findName(char* name){
  for(int i=0;i<_size;i++){
    if(!strcmp(_data[i]._name,name))
      return i;
  }
  return -1;
}


0
 

Author Comment

by:micah
ID: 1170861
char*[] ? not sure I understand you there.  Here is my code


what does it take to pass back _nextHigher?  Once it is passed back how do I print out each element. When I pass it back now it seems to get stomped.  






#ifndef __DB
#define __DB

#include "Device.h"
//
// a realy crappy database
//

struct dbStruct{
  char        _name[50];
  DEVICETYPE  _deviceType;
  char **     _nextHigher;
  int         _nextHigherCount;
  char        _tool[50];

};

class DB{
 public:
  DB();
  ~DB();
  DEVICETYPE getDeviceType(char* name);

  int getNextHigher(char* name,char** data);

  char* getTool(char* name);

 private:
  int findName(char* name);
  dbStruct _data[30];
  int _size;
};
#endif

#include "DB.h"
#include <string.h>

DB::DB(){

  for(int i=0;i<30;i++){
    _data[i]._nextHigher = new char*[5];      
    for(int j=0;j<5;j++)
      _data[i]._nextHigher[j]=new char[50];
  }      
  strcpy(_data[0]._name,"panel");      
  _data[0]._deviceType = PANEL;
  strcpy(_data[0]._nextHigher[0],"fastener_p");
  _data[0]._nextHigherCount=1;
  strcpy(_data[0]._tool,"NULL");

  strcpy(_data[1]._name,"ratchet");                  
  _data[1]._deviceType = ROTATIONAL_TOOL;
  strcpy(_data[1]._nextHigher[0],"NULL");
  _data[1]._nextHigherCount=0;
  strcpy(_data[1]._tool,"NULL");

  strcpy(_data[2]._name,"fastener_p");                  
  _data[2]._deviceType = FASTENER;
  strcpy(_data[2]._nextHigher[0],"NULL");
  _data[2]._nextHigherCount=0;      
  strcpy(_data[2]._tool,"ratchet");

  strcpy(_data[3]._name,"LRU");                  
  _data[3]._deviceType = GENERIC;
  strcpy(_data[3]._nextHigher[0],"fastener_p");
  strcpy(_data[3]._nextHigher[1],"harness_p");
  _data[3]._nextHigherCount=2;      
  strcpy(_data[3]._tool,"NULL");

  strcpy(_data[4]._name,"harness_p");                  
  _data[4]._deviceType = HARNESS;
  strcpy(_data[4]._nextHigher[0],"NULL");
  _data[4]._nextHigherCount=0;      
  strcpy(_data[4]._tool,"NULL");  
 
 _size = 5;
}


DB::~DB(){
  for(int i=0;i<30;i++){
    for(int j=0;j<5;j++)
      delete [] _data[i]._nextHigher[j];
    delete [] _data[i]._nextHigher;
  }      
}

DEVICETYPE        DB::getDeviceType(char* name){
  int i=findName(name);
  if( i >=0 )
      return _data[i]._deviceType;
    return INVALID;
 
}
 

int             DB::getNextHigher(char* name,char** data)
{
  int i=findName(name);
  if(i >=0 ){
    data = &_data[i]._nextHigher;
    return _data[i]._nextHigherCount;
  }
  else
    return 0;
}

char*             DB::getTool(char* name){
  int i=findName(name);      
  if(i >=0 )
    return _data[i]._tool;
  else
    return NULL;
}
//
/** PRIVATE **/
//
int            DB::findName(char* name){
  for(int i=0;i<_size;i++){
    if(!strcmp(_data[i]._name,name))
      return i;
  }
  return -1;
}


0
 
LVL 22

Expert Comment

by:nietod
ID: 1170862
Change GetNextHigher to to take a "char ** &"  That i, it takes a parameter that it can alter (that is what the & is for) and that parameter is a pointer to a pointer to characters.

int DB::getNextHigher(char* name,char** &data)
      {
        int i=findName(name);
        if(i >=0 ){
          data = _data[i]._nextHigher;
          return _data[i]._nextHigherCount;
        }
        else
          return 0;
      }
0
 
LVL 22

Expert Comment

by:nietod
ID: 1170863
I don't see a place where you are using this procedure, so I'll make one up.

char **StrAry;
int StrCnt = SomeDB.getNextHigher("Searchforme",StrAry);

for (int i = 0; i < StrCnt; ++i)
   cout << *StrAry++;

let me know if you have any questions.  I have not answered because ecw was here first and I believe could have provided the same information.

FYI   you may want to add the "const" declaration to your char * parameters that are treated as constant, for example, the first parameter to getNextHigher.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:micah
ID: 1170864
This is how I want to call getNextHigher, what do I need to do to have junk point to the contents of _nextHigher in the struct in DB.

How do I get the following to work

#include "DB.h"
#include "iostream.h"
void main(){
  DB db;
  char** junk;
  int junkCount;
  junkCount=db.getNextHigher("panel",&junk);
  cout<<junk[0]<<endl;
}
0
 
LVL 22

Expert Comment

by:nietod
ID: 1170865
That is exactly what I showed, you except I passed the parameter (junk) by reference so an  wasn't needed, that is my way you specify

 junkCount=db.getNextHigher("panel",junk);  // no &

instead of

 junkCount=db.getNextHigher("panel",&junk); // with &

If you want the &, then the GetNextHigher function should take a pointer to a char **, rather than a reference to a char **.  That is it should take "char ***", rather thann "char ** &"  In that case it would be

int DB::getNextHigher(char* name,char*** data)
{
        int i=findName(name);
        if(i >=0 ){
             data = &_data[i]._nextHigher;
             return _data[i]._nextHigherCount;
         }
         else
                return 0;
 }


0
 
LVL 8

Accepted Solution

by:
Answers2000 earned 100 total points
ID: 1170866
Maybe this is way out in left field,

 but why not pass back either a point to the structure or an array/vector of strings (or reference/pointer to one)


0
 
LVL 8

Expert Comment

by:Answers2000
ID: 1170867
Maybe this is way out in left field,

 but why not pass back either a point to the structure or an array/vector of strings (or reference/pointer to one)


0
 
LVL 22

Expert Comment

by:nietod
ID: 1170868
Don't you think the question was already answered?  I choose not to answer because ecw really deserved it, he was here first and suplied the correct answer.  I oftered additional help if additional information was supplied and gave it.  
0
 

Author Comment

by:micah
ID: 1170869
The comments where very good, the final proposed answer which came after the comments was a 'C'
0
 
LVL 22

Expert Comment

by:nietod
ID: 1170870
micah, you can choose who gets the grade.  In the future, if you don't like the submitted answer, you can reject it and ask another expert to submit a "dummy" answer.  Keeping the system fair will help to keep it running.  I know of at least two experts who left (and whose contributions are sorely lost) because other experts were "stealing" their points.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Template syntax for variable length arrays 9 71
computer science syllabus 3 70
C++ mouse_event mouse look 7 70
max float value 3 26
Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
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 be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

867 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now