2016-02-15 46 views
0

大家下午好分隔的多個陣列,C++:解析和閱讀文本文件導入由delimters

首先,感謝您抽出時間到輸入和幫助我瞭解我的問題。我會透露這是一個作業問題,所以我想了解它,而不是給出完整的代碼。

根據問題的標題,我試圖爲我的任務設計一個程序。我已經包含了下面的信息。

Write a program to manage DVD rental in a video rental store. Create 
an abstract data type that represents a DVD in this store. Consider all 
the data and operations that may be necessary for the DVD type to 
work well within a rental management system. Include a print() 
member function that displays all the information about the DVD. Test 
your data type by creating an array of ten DVD instances and filling 
them using information read from a test input file that you create. 
Display the DVD information. 

這裏是我到目前爲止有:


#include <iostream> 
#include <fstream> 
#include <sstream> 

using namespace std; 

int main() 
{ 
    string mArrayO[10]; //create array of 10 string objects 
    string filename = "testfile.txt"; 
    ifstream file(filename.c_str()); //// open file constructor because the constructor for an ifstream takes a const char*, not a string in pre C++11 
    // go through array till index 10 
    for(int x=0; x< 10; x++) 
     { 
      getline(file, mArrayO[x]); //get line and store into array 
      cout << "Line "<< x<<":"<< mArrayO[x]<<endl; //display 
     } 


    return 0; 
} 

到目前爲止,我的輸出是:

Line:0 Lord of the rings|2005|Fantasy|126 minutes|PG-13 
Line:1 Titanic|1997|Romance|104 minutes|R 
Line:2 Shawshank Redemption|1993|Drama|120 minutes|R 
Line:3 The Lion King|1987|Cartoon|84 minutes|PG-10 
Line:4 The God Father|1988|Violence|146 minutes|R 
Line:5 Bruce Almighty|2009|Comedy|78 minutes|R 
Line:6 Spiderman|2006|Action|84 minutes|PG-13 
Line:7 Finding Nemo|2007|Cartoon|87 minutes|E 
Line:8 The Martian|2015|SciFi|104 minutes|PG-13 
Line:9 Insidious 3|2015|Horror|97 minutes|R 

所以你可以看到我已經把數據轉換成一個陣列。現在,這是我正在嘗試做的事情。我希望能夠解析這些數據並將其提供給我的DVD類。特別是作爲我的問題概述,我希望能夠將所有電影名稱放在一個數組中,日期在另一個數組中,等等,直到每個數據集匹配。一旦完成,我希望能夠提示用戶選擇一個選項並從那裏發生相應的功能。

我也做了以下模板我的DVD類:

class movie 
{ 
public: 
    /// These are our methods to get the information 

string getMovieName() 
{ 
    return moviename; 
} 

string getYear() 
{ 
    return year; 
} 

string getGenre() 
{ 
    return genre; 
} 

string getTime() 
{ 
    return time; 
} 

string getRating() 
{ 
    return rating; 
} 

私人://這是該類的成員。他們將存儲我們所需的全部信息 字符串電影名稱; 字符串年; 字符串類型; 弦時間; 字符串評分;
};

這是我的代碼的另一部分。我已經把它放在這裏櫃面看到人們需要,如果我試圖

bool done= false; // Client wants to continue. 

    while (!done) 
    { 
     cout<< "This is a test"; 
     cin.ignore(); 

    done=ask_to_continue(); 
    } 

    //finish 
    cout<< "Thank you for using the DVD rental management system"; 
    return 0; 

bool ask_to_continue() 
{ 
    char again; //using keystroke 
    cout << "Do you need more help? Y or N? " << endl; 
    cin >> again; 

    if(again == 'n') 
     return true; // Exit program 

    return false; // Still using program 
} 

回答

0

要分割字符串,請使用findfind_first_of功能從std::string得到分隔符的位置。然後使用substr獲取這些分隔符之間的子字符串。

1

您已成功讀取文本文件中的數據並填充字符串數組。現在你需要做的是寫一個解析函數來解析數組中的每個字符串或行。然後,在解析每一行時,您需要將每個內容保存到您的班級中。

我可以爲您提供一個通用函數,它將爲您解析字符串,前提是您使用的是相同的分隔符;它作爲一個靜態方法封裝在一個Utility類中,以及一些其他有用的字符串操作函數。

Utility.h

#ifndef UTILITY_H 
#define UTILITY_H 

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" 

#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 

實用程序。CPP

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

// 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 

的包括需要這種類在stdafx.h發現是:向量,字符串,CONIO.H,也許TCHAR.H,我也用這個枚舉主的返回值這也是在發現stdafx.h

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

至於你Movie類,你定義了你的函數來獲取數據,但是你有沒有表明您已經定義的任何設置方法,也沒有構造函數。此外,你的getter應該被聲明爲const函數,因爲這些函數不會改變存儲在你的類對象中的數據。你的類應該是這樣:

Movie.h

#ifndef MOVIE_H 
#define MOVIE_H 

class Movie { 
private: 
    std::string m_strTitle; 
    std::string m_strYear; 
    std::string m_strGenre; 
    std::string m_strLength; 
    std::string m_Rating; 

public: 
    Movie(); // Default Constructor 
    Movie(const std::string& strTitle, const std::string& strYear, const std::string& strGenre, 
      const std::string& strLength, const std::string& strRating(); 

    std::string getTitle() const; 
    std::string getYear() const; 
    std::string getGenre() const; 
    std::string getLength() const; 
    std::string getRating() const; 

    void setTitle(const std::string& strTile); 
    void setYear(const std::string& strYear); 
    void setGenre(const std::string& strGenre); 
    void setLength(const std::string& strLength); 
    void setRating(const std::string& strRating); 

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

}; // Movie 

#endif // MOVIE_H 

Movie.cpp

#include "stdafx.h" 
#include "Movie.h" 

// Movie() 
Movie::Movie() { 
} // Movie 

// Movie() 
Movie::Movie(const std::string& strTitle, const std::string& strYear, const std::string& strGenre, 
       const std::string& strLength, const std::string& strRating) : 
m_strTitle(strTitle), 
m_strYear(strYear), 
m_strGenre(strGenre), 
m_strLength(strLength), 
m_strRating(strRating) { 
} // Movie 

// getTitle() 
std::string Movie::getTitle() const { 
    return m_strTitle; 
} // getTitle 

// getYear() 
std::string Movie::getYear() const { 
    return m_strYear; 
} // getYear 

// getGenre() 
std::string Movie::getGenre() const { 
    return m_strGenre; 
} // GetGenre 

// getLength() 
std::string Movie::getLength() const { 
    return m_strLength; 
} // getLength 

// getRating() 
std::string Movie::getRating() const { 
    return m_strRating; 
} // getRating 

// setTitle() 
void Movie::setTitle(const std::string& strTile) { 
    m_strTitle = strTile; 
} // setTitle 

// setYear() 
void Movie::setYear(const std::string& strYear) { 
    m_strYear = strYear; 
} // setYear 

// setGenre() 
void Movie::setGenre(const std::string& strGenre) { 
    m_strGenre = strGenre; 
} // setGenre 

// setLength() 
void Movie::setLength(const std::string& strLength) { 
    m_strLength = strLength; 
} // setLength 

// setRating() 
void Movie::setRating(const std::string& strRating) { 
    m_strRating = strRating; 
} // setRating 

現在爲您解析字符串使用功能的實用程序類Utility::splitString()您需要爲數組中的條目執行for循環,並且對於每次傳遞都必須分析該字符串,然後構造一個Movie對象ei然後使用其默認構造函數,然後填充每個成員或通過使用適當的構造函數構造對象。我將向您展示如何使用splitString()函數的示例。

的main.cpp

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

int main() { 
    std::string test("Hello World How Are You Today"); 
    std::vector<std::string>> vResults; 

    vResults = Utility::splitString(test, " "); 

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

這裏splitString將作爲第一個參數是要分析該字符串作爲其第二個參數的定界字符串或字符在你的情況下,它會是"|"字符,它會將結果保存到一個字符串向量中。從這裏開始for循環的每一遍,然後就是構造你的對象,同時爲它們分配適當的值。

+0

感謝您的深入解釋和庫。我想知道一些功能如何工作,看不到任何評論,對於我正在做的事情,我有點不適應。我是一名C++編程的初學者,目前我的知識基礎略高於 – KingShahmoo

+0

@KingShahmoo上面編寫的大部分代碼並不需要評論函數或方法做他們所說的。我提供的Utility類中唯一重要的函數是splitString()方法。 –

+0

@KingShahmoo你所做的是從文件中讀取一行文本並將其保存到一個字符串中,並且你已經完成了保存在你的數組中的所有字符串。下一步是逐個取出該數組中的每個字符串,並在每次循環中解析該字符串。我剛剛給你的實用工具類將基於分隔文本行的分隔字符解析此字符串。最後一步是創建您的Movie對象並傳入所需的數據。 –