2016-03-19 10 views
0

Değerleri bir dosyadan kullanıcı tanımlı bir yapıya depolayabilmek istiyorum. Aşağıdaki gibi farklı türde verileri barındıran sütunlar istiyorum: Karakter adları için bir std :: dizesi, Karakter sağlığı için bir float ve Karakter deneyimi için int.C++ 2D Yapı Dizisi verileri

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

Ben de izin vermek için planlıyorum:

My İstenen çıkış İşte

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

aşağıda gösterildiği gibi bir 6 3 diziye tarafından sahip olmaktır şimdiye kadar denedim budur Verileri her sütun türüne göre sıralamak için İsimleri alfabetik olarak sıralamak, sağlığa göre sıralamak ya da deneyimlemek için: Bir 2D dizi kullanmayı düşünüyorum. Bu en iyi seçenek olur mu?

+0

Neden bir "charData" dizisini değil, bir 2B dizisine mi ihtiyacınız var? – Anedar

+0

Eğer garip bir şey söylersem özür dilerim. Ben bir C++ noob'um. Bilginin bir satır ve sütunlarda tutulması istedim – William

+0

Bu soru bir [mcve] gereksinimlerini karşılayamıyor. Lütfen sorunuzu düzenleyin, böylece bir [mcve] içerir. Bunu yapana kadar yetkili bir cevap alacağınız pek olası değil. –

cevap

0

Yapınızdaki alan sayısını veri sütunlarının sayısıyla karıştırıyorsunuz. Her biri 3 alandan sadece 6 kayıt için veri gösterirsiniz. NUM_COLS değerini 1 olarak ayarlamayı deneyin ve sizin için daha iyi çalışıp çalışmadığını görün. Ya da dizininizin ikinci boyutundan (j) tamamen kurtulun.

+0

i j bir tane ve işe yaradı .. emin değilim neden kafamın etrafında sarmak için çalışıyorsun. Aklımda olan şey, 6x3 dizisine sahip olmaktı. ben daha iyi bir açıklama için benim yazı düzenlemek için gidiyorum – William

0

Dosyanızı ikili veya metin olarak okuyor musunuz bilmiyorum; ama cevabım içinde bir metin satırındaki her alanın bir boşluk karakteri ile ayrıldığı bir metin dosyasından okuyorum. Aradığınızı, uygun bir çalışma programını derlemek ve oluşturmak için gerekli tüm dosyaları ekleyeceğim. Bunlardan bazıları gerekli olmayabilir, ancak bunlar için uygun bir şekilde oluşturulmasına dayanan daha büyük bir projeye sahip olduğum çözümümün içindedir.

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 

Sadece yapmak kullanırken de doğru yoldan dosyayı çağırarak emin Utility :: splitString() yöntemi, ikinci parametre veya sınırlayıcı mat olduğundan emin olun saklanan dosyanızda sahip olduğunuz şey. SplitString() yöntemi, karakterin her göründüğünde dizenin her satırından dizeyi böler. Tek bir dize saklamak istediğiniz ilk adın ilk & soyadı gibi birden çok adı varsa, o zaman biraz daha dikkat gerekir.

+0

lol teşekkür francis ama C++ XD benim bilgi ötesinin ötesinde bir şekilde gittim .. ben senin yardımını takdir ediyorum çok geri geleceğim ve sınıfım yakaladıktan sonra derinliklerinde söylediklerine bakacağım Bazı kavramlara – William

+0

@William bir sorun değil. Yeni olsanız ve mevcut anlayışınız sınırlı olsa bile, bunu okullarda öğretilenin% 70'inin pratikte her zaman yeterli olmamasından dolayı sundum. Dilin sözdizimini ve dilin farklı yönlerini öğrenmek zaman alacaktır, ancak birçok yerin öğretmek için başarısız olduğu en büyük şey ana sizsiniz.cpp dosyası veya yürütülebilir dosyanın oluşturulduğu kod basit, kompakt ve okunması kolay olmalıdır. Buradaki kütüphane, tekrar kullanılabilen tek bir sınıftır. Bir yapı ve bir sınıf, bazı farklılıklar ile çok benzer. –

+0

@William (... devam) En azından VS2012, 13 veya 15 ile bir windows platformunda olduğunuz sürece sunduğum şeyle yapabileceğiniz en iyi şey, önceden yeni bir boş win32 konsol çözümü oluşturmaktır. derlenmiş başlıklar, bu dosyaları metin veri dosyasıyla birlikte çözüme ekleyin. Uygun içeriğin standart içerme dosyasında olduğundan emin olun. Her şeyin derlendiğinden emin olmak için derleyin, sonra her şeyin de kurulduğundan emin olun. Daha sonra programı çalıştırın ve bundan sonra, ilk yürütme satırında bir kesme noktası ayarlayın ve mantığı takip etmek için kod boyunca adım atın. –

0

Herhangi bir sütun temelinde sıralama için algorithm başlığındaki sort() başlığını kendi karşılaştırma işlevinizle kullanabilirsiniz.
bu gibi karşılaştırma işlevi tanımlayın:

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

Exp temelinde:

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

Adı temelinde:

bool MyCompName(struct charData a,struct charData b) 
{ 
    int r = a.charName.compare(b.charName); 
    return (r > 0); 
} 
Sağlık temelinde

code:

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