2016-03-19 17 views
0

ファイルからの値をユーザー定義の構造体に格納できるようにします。私は、文字の名前のためのstd :: string、Character healthのfloat、Character experienceのintのような異なるタイプのデータを保持するカラムを持っています。C++ 2D構造体配列データ

struct charData 
{ 
    string charName; 
    float charHealth; 
    int charExp; 
}; 



int main() { 
    const int NUM_COLS = 3; 
    int NUM_ROWS = 6; 
    int charNumber = 0; 
    int userInput; 
    int loop = 0; 
    int i,j; 
    string line; 

    ifstream myIn; // Declare read file stream 
    myIn.open("party.dat"); // Open file  

    struct charData charArray[NUM_ROWS][NUM_COLS]; 

    while(!myIn.eof()) { 
     for (j = 0; j < NUM_COLS ; j++) { 
      for (i = 0; i < NUM_ROWS ; i++) { 
       myIn >> charArray[i][j].charName;  
       myIn >> charArray[i][j].charHealth; 
       myIn >> charArray[i][j].charExp;  
      }  
     }  
    } 

    return 0;  
} 

は、私はまた、ユーザーを許可するように計画しています:

私の所望の出力は、ここで

Alice 23.
Xander 45.3  1110 
Bernard 12.9  2024 
Yanni 23.7  1098 
Craw  50.5  980 
Zack  11.9  1024 

以下のように6×3の配列を持っていることですが、私がこれまで試してみましたものです列の種類ごとにデータをソートします。名前をアルファベット順に並べ替えるには、健康や経験を並べ替えます。私は2D配列を使うことを考えています。これが最善の選択肢でしょうか?

+0

は、なぜあなたは2次元配列と 'charData'のだけではなく配列が必要なのでしょうか? – Anedar

+0

申し訳ありませんが、私は何か変なことを言う。私はC++のnoobです。情報を一列に並べたままにしておきたいのですが – William

+0

この質問は[mcve]の要件を満たしていません。質問に[mcve]が含まれるように編集してください。あなたがこれをするまで、あなたが権威ある答えを得ることはまずありません。 –

答えて

0

私はあなたの構造内のフィールドの数をデータの列の数と混同していると思います。それぞれ3つのフィールドの6つのレコードだけのデータを表示します。 NUM_COLSを1に設定して、それがうまくいくかどうか確認してください。

または、配列の2番目の次元(j)を完全に削除します。

+0

jを1に設定すると正常に動作しました。なぜ私の頭を包み込むのかはわかりません。私が気にしていたのは、6x3アレイを持つことでした。もっと良い説明のために私のポストを編集することになっています – William

0

ファイルをバイナリ形式で読むのかテキスト形式で読むのか分かりません。私の答えでは、テキスト行の各フィールドがスペース文字で区切られたテキストファイルから読み込んでいます。私はあなたが探しているものの適切な作業プログラムをコンパイルして構築するために必要なすべてのファイルを含める予定です。これらの一部は必要ではないかもしれませんが、私が適切に構築するためにこれらに依存するより大きなプロジェクトを持っているため、私の解決策の中にあります。

stdafx.hを

#ifndef STDAFX_H 
#define STDAFX_H 

#include <Windows.h> 

#include <stdio.h> 
#include <tchar.h> 
#include <conio.h> 

#include <string> 
#include <sstream> 
#include <fstream> 
#include <iostream> 
#include <iomanip> 
#include <vector> 
#include <array> 
#include <memory> 

#include <queue> 
#include <functional> 

#include <algorithm> 

// User Application Specific 
// #include "ExceptionHandler.h" // Required For My Solution But Isn't Used In Yours 

namespace util { 

enum ReturnCode { 
    RETURN_OK = 0, 
    RETURN_ERROR = 1, 
}; // ReturnCode 

extern const unsigned INVALID_UNSIGNED; 
extern const unsigned INVALID_UNSIGNED_SHORT; 

} // namespace util 

#endif // STDAFX_H 

stdafx.cpp

の#include "stdafx.hを"

namespace util { 

const unsigned INVALID_UNSIGNED = static_cast<const unsigned>(-1); 
const unsigned INVALID_UNSIGNED_SHORT = static_cast<const unsigned short>(-1); 

} // namespace util 

Utility.h

#ifndef UTILITY_H 
#define UTILITY_H 

namespace util { 

class Utility { 
public: 

    static void pressAnyKeyToQuit(); 

    static std::string toUpper(const std::string& str); 
    static std::string toLower(const std::string& str); 
    static std::string trim(const std::string& str, const std::string elementsToTrim = " \t\n\r"); 

    static unsigned  convertToUnsigned(const std::string& str); 
    static int   convertToInt(const std::string& str); 
    static float  convertToFloat(const std::string& str); 

    static std::vector<std::string> splitString(const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty = true); 

private: 
    Utility(); // Private - Not A Class Object 
    Utility(const Utility& c); // Not Implemented 
    Utility& operator=(const Utility& c); // Not Implemented 

    template<typename T> 
    static bool stringToValue(const std::string& str, T* pValue, unsigned uNumValues); 

    template<typename T> 
    static T getValue(const std::string& str, std::size_t& remainder); 

}; // Utility 

#include "Utility.inl" 

} // namespace util 

#endif // UTILITY_H 

Utility.inl

// ---------------------------------------------------------------------------- 
// stringToValue() 
template<typename T> 
static bool Utility::stringToValue(const std::string& str, T* pValue, unsigned uNumValues) { 
    int numCommas = std::count(str.begin(), str.end(), ','); 
    if (numCommas != uNumValues - 1) { 
     return false; 
    } 

    std::size_t remainder; 
    pValue[0] = getValue<T>(str, remainder); 

    if (uNumValues == 1) { 
     if (str.size() != remainder) { 
      return false; 
     } 
    } 
    else { 
     std::size_t offset = remainder; 
     if (str.at(offset) != ',') { 
      return false; 
     } 

     unsigned uLastIdx = uNumValues - 1; 
     for (unsigned u = 1; u < uNumValues; ++u) { 
      pValue[u] = getValue<T>(str.substr(++offset), remainder); 
      offset += remainder; 
      if ((u < uLastIdx && str.at(offset) != ',') || 
       (u == uLastIdx && offset != str.size())) 
      { 
       return false; 
      } 
     } 
    } 
    return true; 
} // stringToValue 

Utility.cpp

#include "stdafx.h" 
#include "Utility.h" 

namespace util { 

// ---------------------------------------------------------------------------- 
// pressAnyKeyToQuit() 
void Utility::pressAnyKeyToQuit() { 
    std::cout << "Press any key to quit" << std::endl; 
    _getch(); 
} // pressAnyKeyToQuit 

// ---------------------------------------------------------------------------- 
// toUpper() 
std::string Utility::toUpper(const std::string& str) { 
    std::string result = str; 
    std::transform(str.begin(), str.end(), result.begin(), ::toupper); 
    return result; 
} // toUpper 


// ---------------------------------------------------------------------------- 
// toLower() 
std::string Utility::toLower(const std::string& str) { 
    std::string result = str; 
    std::transform(str.begin(), str.end(), result.begin(), ::tolower); 
    return result; 
} // toLower 

// ---------------------------------------------------------------------------- 
// trim() 
// Removes Elements To Trim From Left And Right Side Of The str 
std::string Utility::trim(const std::string& str, const std::string elementsToTrim) { 
    std::basic_string<char>::size_type firstIndex = str.find_first_not_of(elementsToTrim); 
    if (firstIndex == std::string::npos) { 
     return std::string(); // Nothing Left 
    } 

    std::basic_string<char>::size_type lastIndex = str.find_last_not_of(elementsToTrim); 
    return str.substr(firstIndex, lastIndex - firstIndex + 1); 
} // trim 

// ---------------------------------------------------------------------------- 
// getValue() 
template<> 
float Utility::getValue(const std::string& str, std::size_t& remainder) { 
    return std::stof(str, &remainder); 
} // getValue <float> 

// ---------------------------------------------------------------------------- 
// getValue() 
template<> 
int Utility::getValue(const std::string& str, std::size_t& remainder) { 
    return std::stoi(str, &remainder); 
} // getValue <int> 

// ---------------------------------------------------------------------------- 
// getValue() 
template<> 
unsigned Utility::getValue(const std::string& str, std::size_t& remainder) { 
    return std::stoul(str, &remainder); 
} // getValue <unsigned> 

// ---------------------------------------------------------------------------- 
// convertToUnsigned() 
unsigned Utility::convertToUnsigned(const std::string& str) { 
    unsigned u = 0; 
    if (!stringToValue(str, &u, 1)) { 
     std::ostringstream strStream; 
     strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to unsigned"; 
     throw strStream.str(); 
    } 
    return u; 
} // convertToUnsigned 

// ---------------------------------------------------------------------------- 
// convertToInt() 
int Utility::convertToInt(const std::string& str) { 
    int i = 0; 
    if (!stringToValue(str, &i, 1)) { 
     std::ostringstream strStream; 
     strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to int"; 
     throw strStream.str(); 
    } 
    return i; 
} // convertToInt 

// ---------------------------------------------------------------------------- 
// convertToFloat() 
float Utility::convertToFloat(const std::string& str) { 
    float f = 0; 
    if (!stringToValue(str, &f, 1)) { 
     std::ostringstream strStream; 
     strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to float"; 
     throw strStream.str(); 
    } 
    return f; 
} // convertToFloat 

// ---------------------------------------------------------------------------- 
// splitString() 
std::vector<std::string> Utility::splitString(const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty) { 
    std::vector<std::string> vResult; 
    if (strDelimiter.empty()) { 
     vResult.push_back(strStringToSplit); 
     return vResult; 
    } 

    std::string::const_iterator itSubStrStart = strStringToSplit.begin(), itSubStrEnd; 
    while (true) { 
     itSubStrEnd = search(itSubStrStart, strStringToSplit.end(), strDelimiter.begin(), strDelimiter.end()); 
     std::string strTemp(itSubStrStart, itSubStrEnd); 
     if (keepEmpty || !strTemp.empty()) { 
      vResult.push_back(strTemp); 
     } 

     if (itSubStrEnd == strStringToSplit.end()) { 
      break; 
     } 

     itSubStrStart = itSubStrEnd + strDelimiter.size(); 
    } 

    return vResult; 

} // splitString 

} // namspace util 

CharacterData.h

#ifndef CHARACTER_DATA_H 
#define CHARACTER_DATA_H 

class CharacterData { 
private: 
    std::string m_name; 
    float  m_health; 
    unsigned m_exp; 

public: 
    CharacterData(); 
    CharacterData(const std::string& name, float health, unsigned exp); 

    void setName(const std::string& name); 
    void setHealth(float health); 
    void setExperience(unsigned exp); 

    std::string getName() const; 
    float  getHealth() const; 
    unsigned getExperience() const; 

private: 
    CharacterData(const CharacterData& c); // Not Implemented 
    CharacterData& operator=(const CharacterData& c); // Not Implemented  

}; // CharacterData 

#endif // CHARACTER_DATA_H 

CharacterData.cpp

#include "stdafx.h" 
#include "CharacterData.h" 

// ---------------------------------------------------------------------------- 
// CharacterData() 
CharacterData::CharacterData() : 
m_name(std::string()), 
m_health(0.0f), 
m_exp(0) { 
} // CharacterData 

// ---------------------------------------------------------------------------- 
// CharacterData() 
CharacterData::CharacterData(const std::string& name, float health, unsigned exp) : 
m_name(name), 
m_health(health), 
m_exp(exp) { 
} // CharacterData 

// ---------------------------------------------------------------------------- 
// setName() 
void CharacterData::setName(const std::string& name) { 
    m_name = name; 
} // setName 

// ---------------------------------------------------------------------------- 
// getName() 
std::string CharacterData::getName() const { 
    return m_name; 
} // getName 

// ---------------------------------------------------------------------------- 
// setHealth() 
void CharacterData::setHealth(float health) { 
    m_health = health; 
} // setHealth 

// ---------------------------------------------------------------------------- 
// getHealth() 
float CharacterData::getHealth() const { 
    return m_health; 
} // getHealth 

// ---------------------------------------------------------------------------- 
// setExperience() 
void CharacterData::setExperience(unsigned exp) { 
    m_exp = exp; 
} // setExperience 

// ---------------------------------------------------------------------------- 
// getExperience() 
unsigned CharacterData::getExperience() const { 
    return m_exp; 
} // getExperience 

CharacterDatabase.h

#ifndef CHARACTER_DATABASE_H 
#define CHARACTER_DATABASE_H 

class CharacterData; 

class CharacterDatabase { 
private: 
    std::string m_filename; 
    std::vector<std::shared_ptr<CharacterData>> m_vpCharacters; 

public: 
    explicit CharacterDatabase(const std::string& filename); 
    // ~CharacterDatabase(); // Default Okay 

    void displayByOption(unsigned option = 0); 

private: 
    CharacterDatabase(const CharacterDatabase& c); // Not Implemented 
    CharacterDatabase& operator=(const CharacterDatabase& c); // Not Implemented 

    void parseFile(); 
    void display() const; 

    static bool sortByName(const std::shared_ptr<CharacterData>& d1, const std::shared_ptr<CharacterData>& d2); 
    static bool sortByHealth(const std::shared_ptr<CharacterData>& d1, const std::shared_ptr<CharacterData>& d2); 
    static bool sortByExperience(const std::shared_ptr<CharacterData>& d1, const std::shared_ptr<CharacterData>& d2); 

}; // CharacterDataase 

#endif // CHARACTER_DATABASE_H 

CharacterDatabase。CPP

#include "stdafx.h" 
#include "CharacterDatabase.h" 

#include "CharacterData.h" 
#include "Utility.h" 

// ---------------------------------------------------------------------------- 
// CharacterDatabase() 
CharacterDatabase::CharacterDatabase(const std::string& filename) : 
m_filename(filename) { 
    parseFile(); 
} // CharacterDatabase 

// ---------------------------------------------------------------------------- 
// parseFile() 
void CharacterDatabase::parseFile() { 
    using namespace util; 

    if (m_filename.empty()) { 
     std::cout << "Missing or invalid filename." << std::endl; 
     return; 
    } 

    std::string line; 
    std::vector<std::string> results; 
    std::ifstream in; 

    // Try To Open File For Reading 
    in.open(m_filename.c_str(), std::ios_base::in); 
    if (!in.is_open()) { 
     std::cout << "Can not open file(" << m_filename << ") for reading."; 
     return; 
    } 

    // Read Line By Line And Store Contents Into String & Parse Each Line One At A Time. 
    while (!in.eof()) { 
     std::getline(in, line); 
     results = Utility::splitString(line, " "); 

     // On Each Pass We Want To Construct A CharacterData Object & Save It Into Our Container 
     m_vpCharacters.push_back(std::make_shared<CharacterData>(results[0], Utility::convertToFloat(results[1]), Utility::convertToUnsigned(results[2]))); 
    } 

    // Close File Pointer 
    in.close(); 

} // parseFile 

// ---------------------------------------------------------------------------- 
// display() 
void CharacterDatabase::display() const { 
    for (unsigned u = 0; u < m_vpCharacters.size(); u++) { 
     std::cout << m_vpCharacters[u]->getName() << "\t" 
      << m_vpCharacters[u]->getHealth() << "\t" 
      << m_vpCharacters[u]->getExperience() << std::endl; 
    } 
    std::cout << std::endl; 
} // display 

// ---------------------------------------------------------------------------- 
// displayByOption() Default 0 = Order In Which File Is Read In, 
// 1 = Sorted By Name, 2 = Sorted By Health, 3 = Sorted By Experience 
void CharacterDatabase::displayByOption(unsigned option) { 

    switch (option) { 
     case 1: { // Sorted By Name 
      std::sort(m_vpCharacters.begin(), m_vpCharacters.end(), sortByName); 
      display(); 
      break; 
     } 
     case 2: { // Sorted By Health 
      std::sort(m_vpCharacters.begin(), m_vpCharacters.end(), sortByHealth); 
      display(); 
      break; 
     } 
     case 3: { // Sorted By Experience 
      std::sort(m_vpCharacters.begin(), m_vpCharacters.end(), sortByExperience); 
      display(); 
      break; 
     } 
     default: { // Unsorted - Order Read In By File 
      display(); 
     } 
    } 

} // displayByOption 

// ---------------------------------------------------------------------------- 
// sortByName() 
bool CharacterDatabase::sortByName(const std::shared_ptr<CharacterData>& d1, const std::shared_ptr<CharacterData>& d2) { 
    return d1->getName() < d2->getName(); 
} // sortByName 

// ---------------------------------------------------------------------------- 
// sortByHealth() 
bool CharacterDatabase::sortByHealth(const std::shared_ptr<CharacterData>& d1, const std::shared_ptr<CharacterData>& d2) { 
    return d1->getHealth() < d2->getHealth(); 
} // sortByHealth 

// ---------------------------------------------------------------------------- 
// sortByExperience() 
bool CharacterDatabase::sortByExperience(const std::shared_ptr<CharacterData>& d1, const std::shared_ptr<CharacterData>& d2) { 
    return d1->getExperience() < d2->getExperience(); 
} // sortByExperience 

characterData.txt

Alice 23.
Xander 45.3 1110 
Bernard 12.9 2024 
Yanni 23.7 1098 
Craw 50.5 980 
Zack 11.9 1024 

main.cppに

#include "stdafx.h" 
#include "Utility.h"  
#include "CharacterDatabase.h" 

int main() { 
    using namespace util; 

    CharacterDatabase cd("characterData.txt"); 

    cd.displayByOption(); 
    cd.displayByOption(1); 
    cd.displayByOption(2); 
    cd.displayByOption(3); 

    Utility::pressAnyKeyToQuit(); 
    return RETURN_OK; 
} // main 

だけで作る使用しているときにも、正しいパスからファイルを呼び出していることを確認してくださいUtility :: splitString()メソッドは、2番目のパラメータまたは区切り文字マットあなたの格納ファイルにあなたが持っているものをチェスします。 splitString()メソッドは、その文字を見るたびにファイルの各行から文字列を分割します。最初の&の姓のように複数の名前がある場合は、1つの文字列に格納する必要があります。少し注意を払う必要があります。あなたがあなた自身の比較機能をalgorithmヘッダにsort()を使用することができます任意の鞍部に基づいてソートするための

+0

Lol thanks francisしかし、あなたはC++ XDの知識を超えてしまいました。あなたの助けてくれてありがとう、私のクラスがキャッチアップしたら、いくつかの概念に – William

+0

@ウィリアムは問題ありません。あなたが新しく、現在の理解が限られていても、私は学校で教えられている時間の70%が実際には必ずしも十分ではないという事実のためにこれを提示しました。言語の構文や言語のさまざまな側面を学ぶには時間がかかりますが、多くの場所で教えることができない最大のものは、あなたが主であるということです。cppファイルまたは実行ファイルが生成されるコードは、シンプルでコンパクトで読みやすいものにする必要があります。ここのライブラリは再利用可能な単なるクラスです。構造体とクラスは、いくつかの違いと非常によく似ています。 –

+0

@ウィリアム(...続き)少なくともVS2012,13、または15のWindowsプラットフォームを使用している限り、私が提示したものでおそらく最善のことは、preで新しい空のwin32コンソールソリューションを作成することですコンパイルされたヘッダーで、これらのファイルをテキストデータファイルと共にソリューションに追加します。適切なインクルードが標準インクルードファイルにあることを確認してください。コンパイルしてすべてがコンパイルされていることを確認し、すべてがビルドされていることを確認します。その後、プログラムを実行し、その後、実行の最初の行にブレークポイントを設定し、コードをステップ実行してロジックに従います。 –

0


はこのようにあなたの比較関数を定義します。

bool MyCompHealth(struct charData a,struct charData b) 
{ 
    return (a.charHealth>b.charHealth); 
} 

経験に基づいて:

bool MyCompExp(struct charData a,struct charData b) 
{ 
    return (a.charExp > b.charExp); 
} 

名前に基づいて:

bool MyCompName(struct charData a,struct charData b) 
{ 
    int r = a.charName.compare(b.charName); 
    return (r > 0); 
} 
健康に基づいて

コード:

#include<algorithm> 
#include<iostream> 
#include<fstream> 
using namespace std; 

struct charData 
{ 
    string charName; 
    float charHealth; 
    int charExp; 
}; 

bool MyCompHealth(struct charData a,struct charData b) 
{ 
    return (a.charHealth<b.charHealth); 
} 

//on the basis of Exp: 

bool MyCompExp(struct charData a,struct charData b) 
{ 
    return (a.charExp < b.charExp); 
} 

//on the basis of Name: 

bool MyCompName(struct charData a,struct charData b) 
{ 
    int r = a.charName.compare(b.charName); 
    return !(r > 0); 
} 

int main() { 
    const int NUM_COLS = 3; 
    int NUM_ROWS = 6; 
    int charNumber = 0; 
    int userInput; 
    int loop = 0; 
    int i,j; 
    string line; 

    ifstream myIn; // Declare read file stream 
    myIn.open("party.dat",ios::in); // Open file  

    struct charData charArray[NUM_ROWS]; 

    while(!myIn.eof()) //taking input 
    { 
     for (i = 0; i < NUM_ROWS ; i++) 
     { 
      myIn >> charArray[i].charName;  
      myIn >> charArray[i].charHealth; 
      myIn >> charArray[i].charExp;  
     }  
    } 
    cout<<"How you want to sort?(1:health 2:Exp 3:Name)\n"; 
    cin>>userInput; //input from user how he wants to sort 

    if(userInput==1) 
    { 
     //sorting on the basis of health 
     sort(charArray,charArray+NUM_ROWS,MyCompHealth); 
    } 
    else if(userInput==1) 
    { 
     //sorting on the basis of Experience 
     sort(charArray,charArray+NUM_ROWS,MyCompExp); 
    } 
    else 
    { 
     //sorting on the basis of Name 
     sort(charArray,charArray+NUM_ROWS,MyCompName); 
    } 

    //display result 

     for (i = 0; i < NUM_ROWS ; i++) 
     { 
      cout<<charArray[i].charName<<" ";  
      cout<<charArray[i].charHealth<<" "; 
      cout<<charArray[i].charExp<<endl;  
     }  

    return 0;  
}