How do I assign a value to an enum based on input from a file in C ++?

I have a file with values ​​like: START and STOP. I also declare the following enum:

enum Type {
    START,
    STOP
};

      

I am trying to set enum equal to the first value in a file with something like this:

enum Type foo;

ifstream ifile;
ifile.open("input.txt");

ifile >> foo;

      

I get the error: There is no match for 'operator β†’ in' ifile β†’ foo.

How can I make it right?

+2


source to share


6 answers


I found for my specific situation that the following code is the best solution:

template <class T> T a2e(string c, const string a[], const int size) {
    for (int i=0; i < size; i++) {
        if (c == a[i]) {
            return static_cast<T>(i);
        }
    }
}

      

And it will be used like this:



enum StateType {START, STOP};
const int MAXVALUES = STOP+1;
const string stateNames[MAXVALUES] = {"START", "STOP"};

enum StateType state;

ifstream ifile;
ifile.open("input.txt");

ifile >> foo;
state = a2e <enum StateType> (foo, stateNames, MAXVALUES);

      

Hope this helps someone in the future. Thanks to everyone who made suggestions on how to fix this issue.

+1


source


The fastest thing to do is read into an int and cast it into your enum type.



+4


source


The stream insert operator is not overloaded for user-defined types. You can define one for your object of enum

type, Type

or use one of the existing read unsigned char

or overloads bool

and then change the value to enum

.

+1


source


http://condensedcpp.com/Enums.html

std::istream& operator >> (std::istream& i, Season& season)
{
    season = SPRING;
    std::string value;
    if (i >> value) {
        if (value == "Summer") {
            season = SUMMER;
        }
        else if (value == "Autumn") {
            season = AUTUMN;
        }
       else if (value == "Winter") {
            season = WINTER;
        }
    }
    return i;
}

      

+1


source


I think this will improve blcArmadillo template answer and navigator's output answer. In the AToE.h file:

#ifndef AToE_h
#define AToE_h

#include <string>
#include <stdexcept>
#include <cctype>

template <class T, char* A, int size, char* enumName> class AToE
{
  std::string S[size]; // to hold A as std::string
  T t;
  bool valid; // whether t holds a valid value

public:
  AToE()
  {
    initialize();
    valid = false;
  };

  AToE(T& t) : t(t)
  {
    initialize();
    valid = true;
  };

  AToE(std::string const& s)
  {
    initialize();
    valid = true;
    t = toEnum(s); // this has to be done after initialize()
  };

  void initialize()
  {
    int i = 0, j = 0;
    while (i < size)
    {
      while (A[j] != ',')
      {
        if (not isspace(A[j]))
        {
          S[i] += A[j];
        }
        ++j;
      }
      ++j; // to count skipped comma
      ++i;
    }
  };

  T get()
  {
    if (valid) return t;

    std::string e = "ERROR - IO object is not initialized to a valid ";
    e += enumName;
    throw std::runtime_error(e);
  };

  friend std::ostream& operator<<(std::ostream& os, AToE& a)
  {
    if (a.valid) return os << a.S[a.t];

    std::string e = "OUTPUT ERROR - IO object is not initialized to a valid ";
    e += enumName;
    throw std::runtime_error(e);
  };

  T toEnum(std::string const& s)
  {
    for (int i=0; i<size; ++i)
    {
      if (s == S[i])
      {
        valid = true;
        t = static_cast<T>(i);
        return t;
      }
    }

    std::string e = "CONVERSION ERROR - " + s + " is not a valid " + enumName;
    throw std::out_of_range(e);
  }

  std::string toString();
  {
    if (valid) return S[t];

    std::string e = "CONVERSION ERROR - IO object is not initialized to a valid ";
    e += enumName;
    throw std::runtime_error(e);
  }

  friend std::istream& operator>>(std::istream& is, AToE& a)
  {
    std::istream::sentry isSentry(is); // sentry for is
    if (not isSentry) return is; // stream error

    std::string s;
    if (is >> s) a.t = a.toEnum(s);

    return is;
  }
};
#endif

      

which can then be used like this in StateType.h:

#ifndef StateType_h
#define StateType_h
#include "AToE.h"

enum StateType {START, STOP, NUMBER_OF_STATE_TYPES};
char STATE_TYPE_NAMES[] = "START, STOP,"; // last comma is necessary
char STATE_TYPE_NAME = "StateType";
typedef AToE <StateType, STATE_TYPE_NAMES, NUMBER_OF_STATE_TYPES, STATE_TYPE_NAME> StateTypeIO_T;
#endif

      

and basically:

#include <cstdio>
#include <fstream>
#include <iostream>
#include "StateType.h"

int main()
{
  std::ifstream infile;
  infile.open("input.txt");

  StateTypeIO_T stateIO; // uses AToE() constructor
  //StateType t = stateIO.get(); // uncomment to test get fail condition
  //std::cout << stateIO<< std::endl; // uncomment to test << fail condition
  while (infile >> stateIO) // uses AToE >> operator
  {
    std::cout << stateIO<< std::endl; // uses AToE << operator
    StateType s = stateIO.get(); // uses AToE get method
    StateTypeIO_T stateOut(s); // uses AToE(T& t) constructor
    std::cout << stateOut << endl;
  }

  // remove DOG from input.txt in order for the program to run past here

  std::string stateString = "STOP";
  std::cout << stateString << std::endl; // prints STOP
  StateTypeIO_T stateIO2(stateString); // uses AToE(std::string const& s) constructor
  std::cout << stateIO2 << std::endl; // prints STOP
  printf("state = %s\n", stateIO2.toString().c_str()); // prints state = STOP
  stateString = "START";
  stateIO2.toEnum(stateString); // sets stateIO2.t to START
  std::cout << stateIO2 << std::endl; // prints START

  StateTypeIO_T stateIO3();
  //std::cout << stateIO3.toString() << std::endl; // uncomment to test toString fail condition

  StateType s2;
  //s2 = stateIO3.toEnum("CAT"); // uncomment to test toEnum fail condition
  s2 = stateIO3.toEnum("STOP");
  std::cout << stateIO3 << std::endl; // prints STOP
  StateTypeIO_T stateOut2(s2);
  std::cout << stateOut2 << std::endl; // prints STOP
};

      

which can be used with the file input.txt -

START
STOP
STOP
START
DOG

      

which will print each record twice until it reaches the INPUT ERROR in DOG, and if you remove the DOG from input.txt it will print each record twice, after which -

STOP
STOP
state = STOP
START
STOP
STOP

      

+1


source


@popester

I would post this as an answer, but from past experience code doesn't translate too well in SO answer posts.

I just wrote the following short program to check what you suggested:

#include <iostream>
#include <fstream>

using namespace std;

int main() {
    enum Type {
        START,
        STOP
    };

    int bar;
    enum Type foo;

    ifstream ifile;
    ifile.open("input.txt");

    ifile >> bar;

    foo = (Type) bar;
    cout << "bar: " << bar << endl;

    cout << "foo: " << foo << endl;
}

      

Below is the file input.txt:

STOP

I have compiled and run the program and it outputs the following:

bar: -1207974988
foo: -1207974988

I just don't understand what you are suggesting? If you could lead me in the right direction, that would be great. Thanks for your help.

0


source







All Articles