Solved

strings/classes

Posted on 2004-03-28
15
213 Views
Last Modified: 2013-12-14
First, I'm new at using classes and have what I believe to be a farely simple question here. I appreciate the help in advance.
-----------------------
I have a console application that is using a class called family. Here it is so far...
class family
{
private:
      float firstName;
public:
      float getName(float);
};
#endif
---------------------
I also have .h file that has a function in it called getName. Here it is so far...
#include <iostream.h>
#include "family.h"

float family::getName (float d)
{
      firstName = d;
      return firstName;
}
-----------------------
I have another .cpp file....
#include <iostream.h>
#include "family.h"

void main (void)
{
      family member;
      float dad;
      cout<<"Who is the dad?";
      cin >> dad;
      cout<<"His child is then " <<member.getName(dad);
}

where I would like to ask for the father's name and return the children of that family based upon the input. I know I will have to add some to the function, but can you help with that if you have a minute. And also, right now when I enter say, "M" for the dad it returns some random number like -1.07374e+008.

Can you help me with the function and what is needed to be able to retun char data instead of numeric?

Again, thank you.
jandhb

0
Comment
Question by:jandhb
15 Comments
 
LVL 1

Author Comment

by:jandhb
Comment Utility
I changed the function in family.cpp to this...
#include <iostream.h>
#include "family.h"
#include <string.h>
using namespace std;

void family::getName (string &dad)
{
      char members[1][15] = {"Heather"};
      char lookUp[15], *strPtr = NULL;
      int index;

      for (index=0; index <1; index++)
      {
            strPtr = strstr(members[index],lookUp);
            if(strPtr !=NULL)
                  break;
      }
      if (strPtr == NULL)
            cout << "No mathches";
      else
            cout <<members[index]<<endl;
}
-----------------
In family_prog.pp I have...
#include <iostream.h>
#include "family.h"
#include <string>
using namespace std;


void main (void)
{
      family member;
      string dad;
      cout<<"Who is the dad?";
      cin >> dad;
      cout<<"His child is then " <<member.getName(dad);
}
-----------------------
And in the family.h I have...
#ifndef family_h
#define family_h
#include <string>
using namespace std;

//family class declaration
class family
{
private:
      string &father;
public:
      void getName(string&);
};
#endif
--------------------
Now I am getting an error that says...
No appropriate default constructor available. What does that mean? I am using VC++6.0.
Also, am I using the string.h right when trying to read in and pass this as a parameter to the function?
0
 
LVL 15

Expert Comment

by:efn
Comment Utility
family::father is a reference.  References have to be initialized when they are created.  The compiler is telling you that it can't create a family object because there is nothing that initializes that reference.  You could initialize the reference in a constructor or make family::father a string rather than a reference to a string.

The string-handling code in main looks OK.  The code for the family class needs work.

--efn
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
Also, don't mix <iostream.h> with <string>. Use <iostream>.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
Your class is still strange even if you don't use type float (that's a floating point number with binary storage)  for names:

>> string dad

If you use STL string - what is good - don't mix it up with char[] or char* if it isn't necessary. So your class should look like

#ifndef family_h
#define family_h
#include <string>
#include <vector>
using namespace std;

//family class declaration
class Family
{
private:
     string familyName;
     string father;
     string mother;
     vector<string> children;
public:
     Family();
     Family(const string& familyName, const string& dad , const string& mom);
     void setFamilyname(const string& familyName);
     void setFather(const string& dad);
     void setMother(const string& mom);
     void addChild(const string& child);
     string getFamilyName();
     string getFather();
     string getMother();
     string getChild(int i);
     vector<string>& getChildren();
};
#endif

You see, the only reference returned is vector<string>& as it isn't common to return an array by value (means as a copy).
Member data like father, mother, ... shouldn't declared as reference or you have to provide a storage for them at construction time:

class Family
{
private:
     string& father;
public:
     Family(const string& dad) :  father(*new string(dad)) {}
    ~Family()   {  delete &father; }
};

That compiles but might be a little bit too advanced for a beginner ;-)

>> void family::getName (string &dad)

Change it to

  string family::getFather()

as a get function returning only one value shouldn't return the value by argument. Then you can use it like

  Family myFamily("Smith", "Bob", "Mary");
  string dad = myFamily.getFather();

>>      char members[1][15] = {"Heather"};

As mentioned before, use string class instead of char arrays and if you need an array take std::list or std::vector. If you choose a fix size,  a woman's name like "Marie-Antoinette" won't fit to the buffer.

  vector<string> children;
  children.push_back("Heather");

>>     char lookUp[15], *strPtr = NULL;

First, use string instead char ...  Then lookup isn't initialized and later used. You should always initialize all variables; however you don't have to initialize a string type as it is initialized by the constructor (as an empty string).

>>      for (index=0; index <1; index++)

With string and vector you would have:

    for (index=0; index < children.size(); index++)

>>          strPtr = strstr(members[index],lookUp);
>>          if(strPtr !=NULL)
>>               break;

strstr() searches a substring in a string. You would find "John" in "Johnathan" for example. You should compare both values:
     
       vector<string> members;
       members.push_back("John");
       members.push_back("Heather");
       for (int index=0; index < members.size(); index++)
           if (members[index] == dad)
               break;

Then lookup wasn't initialized. I think you wanted to lookup for 'dad' ??? But then you had to copy 'dad' to 'lookup':

       strcpy(lookup, dad.c_str());

However, that might crash if dad's name has more than 14 characters. So, better take string ...

Hope, that helps

Alex





0
 
LVL 1

Author Comment

by:jandhb
Comment Utility
Alex, that is a lot of information for me at this point, but nonetheless very good. I think I follow class declaration code, so were good there. However, the family.cpp file where these functions are being declared I need some help and also with the family_prog.cpp file. Here is what I have in the family.cpp file. I know it is not correct, but can you show me what i need and kind of explain what is going on in the process. A lot of this is new to me, so I apologize for the beginner questions and requests.

--------------------------------
#include <iostream>
#include "family.h"
#include <string.h>
using namespace std;

string family::getFather()

{
      Family myFamily("Smith", "Bob", "Mary");
  string dad = myFamily.getFather();
   vector<string> children;
  children.push_back("Heather");
}

for (index=0; index < children.size(); index++)
{
      vector<string> members;
      members.push_back("John");
      members.push_back("Heather");
      for (int index=0; index < members.size(); index++)
      {
            if (members[index] == dad)
                  break;
      }
}
-----------------------------------------
And then in the family_prog.cpp I still have...
#include <iostream>
#include "family.h"
#include <string>
using namespace std;


void main (void)
{
      family member;
      string dad;
      cout<<"Who is the dad?";
      cin >> dad;
      cout<<"His child is then " <<member.getName(dad);
}
------------------------------------

Thanks for your help.
Justin

 
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>> #include <string.h>

string.h is old C header, you have to use

#include <string>

to get STL std::string class.

>> string family::getFather()

I changed the class name from 'family' to 'Family' as it is common to use capital letters for private classes. Also,  if variables begin with lower case letter, you may have a variable called 'family' not confusing with the class name. However, it's your choice. If you follow me the implementation is:

 string Family::getFather()
 {
      return father;   // it simply returns a copy of the data member 'father'
 }

All other get functions are as simple as the one before:

string Family::getFamilyName()
 {
      return familyName;   // it simply returns a copy of the data member familyName
 }

vector<string>& Family::getChildren()
{
     return children;   // here we return a reference of data member 'children' and not a copy      
}

You need an implementation of all member functions of class Family including the constructors:

     // default constructor
     // all data members are empty
     Family::Family()  
     {
     }
     
     // constructor taking family name, father and mother
     Family::Family(const string& name, const string& dad , const string& mom)
     : familyName(name), father(dad), mother(mom)     // That is called initializer list; the data members
                                                                                // get their initial value from the arguments
     {
     }

     // Note, that i changed argument from 'familyName' to 'name' avoiding being same as data member
     void Family::setFamilyname(const string& name)
     {
           familyName = name;
     }

     void Family::setFather(const string& dad)
     {
          // to do
     }
     void Family::setMother(const string& mom)
     {
          // to do
     }
     void Family::addChild(const string& child)
     {
           children.push_back(child);       // appends child name to end of array
     }

     string Family::getChild(int i)
     {
          if (i < 0 || i >= children.size())
              return "???";
          return children[i];
     }


All your implementation from above, you should move to main()

#include "family.h"

#include <iostream>
#include <string>
#include <vector>

using namespace std;


void main (void)
{
     Family myFamily("Smith", "Bob", "Mary");
     string dad = myFamily.getFather();    // dad = "Bob";
     myFamily.addChild("Heather");          // Heather is oldest child
     myFamily.addChild("Michael");          // Michael is 'middle'
     myFamily.addChild("Leila");               // Leila is youngest

     // have a local array to collect all family members
     vector<string> members;
     members.push_back(dad);                                      // insert father as first member
     members.push_back(myFamily.getMother());           // insert mother as second member

     vector<string>& children = myFamily.getChildren();   // we got a reference of the children member array

     // copy all children to members array
     for (int index=0; index < children.size(); index++)
     {
          members.push_back(myFamily.getChild(index));    // add child to members array
     }
     
     while (true)
     {
        string name;
        cout<< "Enter a first name [or 'quit' to exit] ";
        cin >> name;
        if (name == "quit)
           return;

         bool found = false;
         for (int index=0; index < members.size(); index++)
         {
            if (members[index] ==name)
            {
               found = true;
               break;
            }
         }

         if (found)
             cout << name << " is a member of my family " << endl;
         else
            cout << name << "???, never heard. " << endl;
       }
}

You, see in the class there are only variables and no text constants like "Heather". Real life names we use only in the test program.

You may easily improve the test prog by asking for all names of the family. Ask for the children in a separate loop that could be stopped by entering 'next'. Add new data members grandpa and grandma ... If you feel comfortable with this, create a new class FamilyMember, having data members  name, sex, age, a default constructor and a full constructor, get and set functions for all data members. If done, change all string members of class Family to FamilyMembers ...

Regards, Alex

Regards, Alex







0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 1

Author Comment

by:jandhb
Comment Utility
alex, can i send you my three files and have you take a look at what i have and why i am still getting some errors? Or do you have msn messenger?
thanks for all your help.

justin
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
If they are not too big just post them here on EE.

or send them by e-mail to info@sbsweb.info.

Regards, Alex
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
Ok, they are workingnow. You should try to get an editor that doesn't make word wrapping beyond of 80 chars/line. And some 'todos' where also missing ;-)

// ------------------- family.cpp -------------------------------------------------
#include <iostream>
#include "family.h"
#include <string>

// string.h is an old c header and i should use #include <string>
// to get the STL std::string class/to use string family::getfather()

using namespace std;


//common to use capital letters for private classes.

string Family::getFather()
{
   return father;   // it simply returns a copy of the data
                         // member 'father'
}

string Family::getMother()
{
   return mother;   // it simply returns a copy of the data
                           // member 'mother'
}

//All other get functions are as simple as the one before:

string Family::getFamilyName()
{
   return familyName;   // it simply returns a copy of the data
                                  // member familyName
}

vector<string>& Family::getChildren()
{
   return children;   // here we return a reference of data member
                            // 'children' and not a copy
}

// You need an implementation of all member functions of class
// Family including the constructors:

// default constructor
// all data members are empty
Family::Family()
{
}

// constructor taking family name, father and mother
Family::Family(const string& name, const string& dad , const string& mom)
: familyName(name), father(dad), mother(mom)    
                                    // That is called initializer list; the data members
                                    // get their initial value from the arguments
{
}

// Note, that i changed argument from 'familyName' to 'name' avoiding
// being same as data member
void Family::setFamilyname(const string& name)
{
   familyName = name;
}

void Family::setFather(const string& dad)
{
  father = dad;
}
void Family::setMother(const string& mom)
{
  mother = mom;
}
void Family::addChild(const string& child)
{
  // appends child name to end of array
   children.push_back(child);  
}

string Family::getChild(int i)
{
  if (i < 0 || i >= children.size())
      return "???";
  return children[i];
}

// ------------------------------- family.h ------------------------------------

#ifndef family_h
#define family_h
#include <string>
#include <vector>
using namespace std;

//family class declaration
class Family
{
private:
    string familyName;
    string father;
    string mother;
    vector<string> children;
public:
    Family();
    Family(const string& familyName, const string& dad , const string&
        mom);
    void setFamilyname(const string& familyName);
    void setFather(const string& dad);
    void setMother(const string& mom);
    void addChild(const string& child);
    string getFamilyName();
    string getFather();
    string getMother();
    string getChild(int i);
    vector<string>& getChildren();
};
#endif

// ----------------------------- family_prog.cpp ------------------------------------

#include "family.h"
#include <iostream>
#include <string>
#include <vector>

using namespace std;


void main (void)
{
    Family myFamily("Smith", "Bob", "Mary");
    string dad = myFamily.getFather();  
    // dad = "Bob";
    myFamily.addChild("Heather");                          
    // Heather is oldest child
    myFamily.addChild("Michael");      
    // Michael is 'middle'
    myFamily.addChild("Leila");
    // Leila is youngest
   
    // have a local array to collect all family members
    vector<string> members;
    // insert father as first member
    members.push_back(dad);                            
    // insert mother as second member
    members.push_back(myFamily.getMother());                
    // we'll get a reference of the children member array
    vector<string>& children = myFamily.getChildren();      
   
    // copy all children to members array
    for (int index=0; index < children.size(); index++)
    {
        members.push_back(myFamily.getChild(index));        // add child to members array
    }
   
    while (true)
    {
        string name;
        cout<< "\nEnter a first name [or 'quit' to exit] ";
        cin >> name;
        if (name == "quit")
            return;
       
        bool found = false;
        for (int index=0; index < members.size(); index++)
        {
            if (members[index] ==name)
            {
                found = true;
                break;
            }
        }
       
        if (found)
            cout << name << " is a member of my family " << endl;
        else
            cout << name << "???, never heard. " << endl;
    }
}

// --------------------- end of source -------------------------------------------


I would recommend you to increase points and post the questions of your mail here in EE, maybe in a new thread?

Regards, Alex


0
 
LVL 1

Author Comment

by:jandhb
Comment Utility
Alex,

1. I increased the points to 100.
2. I'm getting 7 warnings that all look similar in family.cpp, i think...
--------------------------------
c:\program files\vc98\include\vector(39) : warning C4786: 'std::reverse_iterator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const *,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char
,std::char_traits<char>,std::allocator<char> > const &,std::basic_string<char,std::char_traits<char>,std::allocator<char> > const *,int>' : identifier was truncated to '255' characters in the debug information
        c:\program files\vc98\include\vector(39) : while compiling class-template member function '__thiscall std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<cha
r>,std::allocator<char> > > >::std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >(const std::allocator<std::basic_string<char,std::
---------------------------------
3. What function(s) hold the names of the dads and the children, so I can populate them with the correct data. Now when I enter a name it simply returns not found. Where is that data being held?

Thanks.
char_traits<char>,std::allocator<char> > > &)'

0
 
LVL 1

Author Comment

by:jandhb
Comment Utility
Ok, I think I where to add the father's name - Family myFamily("Jerry", "John", "Kent");

However, it seems that the first name can't be found. For example, if I would type in "Jerry" it would say, never heard, but "John" works.

I want the program to return the children for each father. It does not seem to be doing that. Do I need to tell it to go to a certain function in order to display the children if the dad's name is found? Right now it is just saying ..... "is a member of my family."
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
You can ignore warnings as they are in debug mode only. STL names become longer than 255 characters what is the maximum VC Debugger supports.

You may suppress warnings by inserting this pragma statement as first line to your cpp files:

#pragma warning ( disable : 4786 )

Note, spaces in this statement are necessary.

The answer to your next question will come soon.

Regards, Alex
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 100 total points
Comment Utility
>> However, it seems that the first name can't be found.

That is rather a logical than a technical problem:

We filled a local array 'members' using all first names of one sample family. What you want to do, is to search for father's name only, what doesn't make much sense as we have one father only.

So for your scenario you should create some more sample families - say at least 3 -  create a new array 'families' where all these Family objects get stored. Then, when user enters a (father's) name, you may look up your families array whether either first name or last name of father matches.. If yes you may output children array.

Will you try the implementation of this? I'll help if you've posted some initial code.

Regards, Alex
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Programmer's Notepad is, one of the best free text editing tools available, simply because the developers appear to have second-guessed every weird problem or issue a programmer is likely to run into. One of these problems is selecting and deleti…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

771 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

12 Experts available now in Live!

Get 1:1 Help Now