【问题标题】:Reading a file and making a vector of objects based on that info读取文件并根据该信息制作对象向量
【发布时间】:2015-01-25 15:32:41
【问题描述】:

我有 2 个扑克牌值的枚举,它们的等级和花色。我想获取一个包含如下数据的文件:

2C 6D 7h 10s JC

这个信息决定了一张扑克牌。

6c 是俱乐部的 6。

JC 是俱乐部的杰克,等等。 (大小写无关紧要)。

如何获取输入的字符并使用它们制作新的扑克牌?每个可能的字符串都有一个案例似乎有很多代码行。可以以某种方式简化吗?

#include "header1card.h"
#include "stdafx.h"
#include <string>
#include <vector>
#include <iostream> 
#include <fstream>

using namespace std;

int main() {
  Card card;
}

class Card {
private:
 enum struct ranks {two, three, four, five, six, seven, eight, 
             nine, ten, jack, queen, king, ace };
 enum struct suits {diamonds, clubs, hearts, spades };
 suits su; //do what with these two?
 ranks ra;
    };



int fileparser(vector<Card> & readcards, char * filename) {
 ifstream filereading;
 filereading.open(filename, ios::in);

 if (filereading.is_open()) {
   //while read the file here. save what is read to a string.
  char temp;

  while (!filereading.eof()) {
   //how make a card based off of the inputtedr chars?
   char readchar = filereading.get(temp );

   switch (readchar) {
   case '2' :

    break;
   case '3' :

    break;

//and so on to make every card? Seems like a lot of lines of code.
   }
   readcards.pop_back( /*After making the card, put it in vector*/   );

  } 
    filereading.close();
 }
 else {
  //throw error, cannot find file.
  cout << "Could not find file " + filename << endl; //error on ' + filename'. Says Expression must have integral or unscoped enum type.
  cerr << "COuld not find file " << endl;
     }
    }

【问题讨论】:

    标签: c++ file stream playing-cards


    【解决方案1】:

    首先,我建议您将输入代码重写为如下所示:

    Card temp;
    while (filereading >> temp) {
        readcards.push_back(temp); // note: push_back, not pop_back
    }
    

    请参阅this question,了解为什么不检查eof()

    因此,我们只需要为我们的班级写一个operator&gt;&gt;

    class Card {
    public:
        friend istream& operator>>(istream& is, Card& c) {
            std::string name;
            if (is >> name) {
                if (name.size() == 2) {
                    // rank is name[0], suit is name[1]
                    // go process
                }
                else {
                    // set fail state
                    is.setstate(std::ios::failbit);
                }
            }
            return is;
        }
    };
    

    那么我们如何获得军衔和花色呢?这是你问题的主要部分。对于西装,最简单的就是一个开关:

    switch (toupper(name[1])) {
    case 'D':
        c.suit = Card::diamonds;
        break;
    case 'S':
        // etc.
    default:
        // set fail state, maybe log some error too
        is.setstate(std::ios::failbit);
    }
    

    对于排名,我们可以将2, 3, ..., 9 部分简化为:

    if (name[0] >= '2' && name[0] <= '9') {
        int idx = name[0] - '2'; // now it's an int, with value 0 through 7
        c.rank = Card::two + idx; // because enums are ordered
    }
    else {
        // fallback to switch
        switch (toupper(name[0])) {
        case 'T':
            c.rank = Card::ten;
            break;
        case 'J':
            // etc
        default:
            // set fail state
            is.setstate(std::ios::failbit);
    }
    

    【讨论】:

    • operator&gt;&gt; 的真正问题是错误处理。您的代码采用空格分隔符,这是合理的,但确实需要验证提取的字符串是否正好是两个字符。当然,operator&gt;&gt; 永远不应该扔;如果输入有格式错误,应该在流中设置std::ios_base::failbit
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-07
    • 1970-01-01
    • 2012-10-05
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多