2016-02-15 47 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对象并传入所需的数据。 –