如何根据C ++中的文件输入为枚举赋值?

时间:2009-10-25 01:57:48

标签: c++ file-io enums

我有一个文件,其值如:START和STOP。我还声明了以下枚举:

enum Type {
    START,
    STOP
};

我正在尝试将枚举设置为等于文件中的第一个值,如下所示:

enum Type foo;

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

ifile >> foo;

我收到错误:'ifile>>中的'运营商>>'不匹配富”。

我该如何正确地做到这一点?

6 个答案:

答案 0 :(得分:5)

最快的方法是读入一个int并将其强制转换为Type枚举。

答案 1 :(得分:1)

对于用户定义的类型,不会重载流插入运算符。您可以为类型为enum的{​​{1}}对象定义一个,也可以使用其中一个现有重载来阅读Typeunsigned char,然后将值更改为{{1} }}

答案 2 :(得分:1)

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;
}

答案 3 :(得分:1)

我发现在我的特定情况下,以下代码是最佳解决方案:

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);
        }
    }
}

将使用如下:

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);

希望这可以帮助将来的某个人。感谢所有就如何解决这个问题提出建议的人。

答案 4 :(得分:1)

我认为这将是对blcArmadillo的模板的答案和导航器的输出回答的改善。在文件AToE.h中:

#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

然后可以在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

和主要内容:

#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
};
其可与一个input.txt的文件可以使用

-

START
STOP
STOP
START
DOG

这将打印出的每个条目两次,直到它碰到上DOG发生输入错误,并且如果从input.txt中除去DOG,将打印出的每个条目两次,接着 -

STOP
STOP
state = STOP
START
STOP
STOP

答案 5 :(得分:0)

@popester

我会将此作为回复发布,但过去的经验代码在SO的回复中并不能很好地转换。

我刚刚编写了以下简短程序来测试你的建议:

#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;
}

以下是我的input.txt文件:

  

STOP

我编译并运行程序并输出以下内容:

  

bar:-1207974988
foo:-1207974988

我只是误解了你的建议吗?如果你能引导我朝着正确的方向前进,那就太棒了。谢谢你的帮助。