Member Avatar for Search_not

I am trying to overload enum types so that I can get input and show output using these enum types...
My program bombs out when I run it, please help.
Here is an example of what I am trying to do (a rock classification program):

#include <iostream>
#include "classify.h"

using namespace std;

enum RockKind{Igneous, Metamorphic, Sedimentary, KindError};

enum RockTexture{Coarse, Intermediate, Fine, TextureError};

enum RockName{Basalt, Dolomite, Granite, Limestone, Marble, Obsidian, Quartzite, Sandstone, Shale, Slate, NameError};

RockKind Kind(RockName Rock){
    switch(Rock){
        case Basalt: case Granite: case Obsidian: return Igneous;
        case Marble: case Quartzite: case Slate: return Metamorphic;
        case Dolomite: case Limestone: case Sandstone: case Shale: return Sedimentary;
        default: std::cerr << "\n*** Invalid Rock name ***\n";
    }
    return KindError;
}
RockTexture Texture(RockKind Kind){
    switch(Kind){
        case Igneous: return Coarse;
        case Metamorphic: return Intermediate;
        case Sedimentary: return Fine;
        default: std::cerr << "\n***No Kind found ***\n";
    }
    return TextureError;
}

class overload{
public:
    RockName Rock;    //create enum variable
    friend ostream& operator<<(ostream& os, RockName& Rock);   //overload ostream
    friend istream& operator>>(istream& is, RockName& Rock);   //overload istream
};

overload ov;   //create object 

istream& operator>> ( istream& is, RockName& name )   
{
   is >> ov.Rock;
   return is;
}

ostream& operator<< ( ostream& os, RockName& name )
{
   os << Kind(ov.Rock);
   return os;
}

int main()
{
    char Answr;

    do{
        cout << "Enter the name of the rock: " << endl;
        cin >> ov.Rock;

        cout << endl << ov.Rock
             << " is classified as a(n) " << Kind(ov.Rock)
             << " rock and \nits texture is "
             << Texture(Kind(ov.Rock)) << endl;

        cout << "Enter 'c' to continue, anything else to quit: ";
        cin >> Answr;
        cout << endl;

    }while(Answr == 'c');

    return 0;
}

Recommended Answers

All 7 Replies

Member Avatar for Search_not

Ignore the #include "clasify.h"

This line

cin >> ov.Rock;

in your main function calls the operator function istream& operator>> ( istream& is, RockName& name )

That function contains is >> ov.Rock; which calls the operator function istream& operator>> ( istream& is, RockName& name ) which contains is >> ov.Rock; which calls the operator function istream& operator>> ( istream& is, RockName& name ) which contains is >> ov.Rock; which calls the operator function istream& operator>> ( istream& is, RockName& name ) which contains is >> ov.Rock; which calls the operator function istream& operator>> ( istream& is, RockName& name ) which contains is >> ov.Rock; which calls the operator function istream& operator>> ( istream& is, RockName& name ) which contains is >> ov.Rock; which calls the operator function istream& operator>> ( istream& is, RockName& name ) which contains ...... to infinity.

Basically, your >> operator function is calling itself in an infinite loop.

Your operator function needs to take the input as a type OTHER than Rockname; it needs to take the input as something it already knows how to handle. For example, an int, if the user is to enter a number.

istream& operator>> ( istream& is, RockName& name )   
{
   int inputVal;
   is >> inputVal;
   switch (inputVal)
  {
    case 0:
        ov.Rock = Basalt;
        break;
   case 1:
        ov.Rock = Dolomite;
        break;
    default:
        break;
  }


   return is;
}

You could alternatively handle a string, and have the user type in a word.

Member Avatar for Search_not

My program allows the user to enter the rock name themselves, so I'm using a string value. But my compiler doesn't allow me to use a string in the switch statement. Do I have to use if and else-if statements instead of the case statement in order to assign a value to ov.Rock?

Short answer, yes. Longer answer, welcome to C++. There are lots of ways to do this a bit more elegantly that a switchyard.

You could create a map of string to enum and then call it with something like outputString = map[input_enum_value];, or you could use an array of strings organised so that the zeroth string corresponds to the enum value 0, and the first string corresponds to the enum value 1, and so on and then you'd convert the enum to a string with a call like outputString = stringArray[input_enum_value];, and I have no doubt there are more ways.

Member Avatar for Search_not

I tried using an integer as input but when I print out kind and texture using the Kind(ov.Rock) and Texture(Kind(ov.Rock)) functions it prints out integer values associated with the specific names in my enum types and not the actual names. How do I get it to print out one of these enum RockKind{Igneous, Metamorphic, Sedimentary, KindError} when I call the Texture(Kind(ov.Rock)) and the Kind(ov.Rock) functions? Instead of their integer values

Here's an example of my now altered code:

#include <iostream>

using namespace std;

char Instr[] = "Rock Names: \n\t1- Basalt "
               "\n\t2- Dolomite "
               "\n\t3- Granite "
               "\n\t4- Limestone "
               "\n\t5- Marble "
               "\n\t6- Obsidian "
               "\n\t7- Quartzite "
               "\n\t8- Sandstone "
               "\n\t9- Shale "
               "\n\t10- Slate";
char cErrr[] = "***Incorrect Rock Index!***";

enum RockKind{Igneous, Metamorphic, Sedimentary, KindError};

enum RockTexture{Coarse, Intermediate, Fine, TextureError};

enum RockName{Basalt, Dolomite, Granite, Limestone, Marble, Obsidian, Quartzite, Sandstone, Shale, Slate, NameError};

RockKind Kind(RockName Rock){
    switch(Rock){
        case Basalt: case Granite: case Obsidian: return Igneous;
        case Marble: case Quartzite: case Slate: return Metamorphic;
        case Dolomite: case Limestone: case Sandstone: case Shale: return Sedimentary;
        default: std::cerr << "\n*** Invalid Rock name ***\n";
    }
    return KindError;
}
RockTexture Texture(RockKind Kind){
    switch(Kind){
        case Igneous: return Coarse;
        case Metamorphic: return Intermediate;
        case Sedimentary: return Fine;
        default: std::cerr << "\n***No Kind found ***\n";
    }
    return TextureError;
}

int main();

class overload{
public:
    RockName Rock;
    friend ostream& operator<<(ostream& os, RockKind& Rock);
    friend istream& operator>>(istream& is, RockKind& Rock);
};

overload ov;

istream& operator>> ( istream& is, RockName& name )
{
   int inPut;
   is >> inPut;

   switch(inPut){
        case 1: ov.Rock = Basalt;
            break;
        case 2: ov.Rock = Dolomite;
            break;
        case 3: ov.Rock = Granite;
            break;
        case 4: ov.Rock = Limestone;
            break;
        case 5: ov.Rock = Marble;
            break;
        case 6: ov.Rock = Obsidian;
            break;
        case 7: ov.Rock = Quartzite;
            break;
        case 8: ov.Rock = Sandstone;
            break;
        case 9: ov.Rock = Shale;
            break;
        case 10: ov.Rock = Slate;
            break;
        default: cerr << cErrr << endl;
                 main();
            break;
   }

   return is;
}

ostream& operator<< ( ostream& os, RockName& name )
{
   os << Kind(ov.Rock);
   return os;
}

int main()
{
    char Answr;
    RockName rock;
    cout << Instr << endl;

    do{
        cout << "Enter the name of the rock: " << endl;
        cin >> rock;

        cout << endl << ov.Rock
             << " is classified as a(n) " << Kind(ov.Rock)  //here it prints out the integer the user entered
             << " rock and \nits texture is "
             << Texture(Kind(ov.Rock)) << endl;

        cout << "Enter 'c' to continue, anything else to quit: ";
        cin >> Answr;
        cout << endl;

    }while(Answr == 'c');

    return 0;
}

You need to pick a string based on the enum (int).

For example:

string output;
if (ov.Rock = Basalt) output = "Basalt";

and so on.

If you used an array of strings, you could do something like

return arrayOfString[ov.Rock];

Member Avatar for Search_not

Okay, thanks for the help!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.