首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++:将文本文件解析并读取到由分隔符分隔的多个数组中

c++:将文本文件解析并读取到由分隔符分隔的多个数组中
EN

Stack Overflow用户
提问于 2016-02-15 19:39:21
回答 2查看 540关注 0票数 0

大家下午好,

首先,谢谢你花时间输入和帮助我理解我的问题。我会透露这是一个作业问题,所以我想了解它,而不是得到完整的代码。

根据问题的标题,我正在为我的作业设计一个程序。我已将下列资料包括在内。

代码语言:javascript
复制
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.

以下是我到目前为止所拥有的:

代码语言:javascript
复制
#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;
}

到目前为止,我的产出是:

代码语言:javascript
复制
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类中。具体来说,正如我的问题概述的那样,我希望能够将所有的电影名称放在一个数组中,在另一个数组中放置日期等等,直到完成的每个数据集都是matched.Once,我希望能够提示用户选择一个选项,并从其中产生相应的函数。

我还为我的DVD类制作了以下模板:

代码语言:javascript
复制
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;
}  

私人: //这些是这个班的成员。他们将存储我们需要的所有信息,这类字符串电影名称;字符串年份;字符串类型;字符串时间;字符串评级;

};

这是我代码的另一部分。我把它放在这里,以防人们需要看我是否尝试过

代码语言:javascript
复制
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
}
EN

回答 2

Stack Overflow用户

发布于 2016-02-15 20:47:46

您已经成功地从文本文件中读取数据并填充了字符串数组。现在您需要做的是编写一个解析函数来解析数组中的每个字符串或行。然后,在解析每一行时,您将需要将每个内容保存到类中。

我可以为您提供一个泛型函数,它将为您解析字符串,前提是您使用相同的分隔符;它与其他一些有用的字符串操作函数一起封装在一个Utility中,作为一个静态方法。

Utility.h

代码语言:javascript
复制
#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

代码语言:javascript
复制
// 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

代码语言:javascript
复制
#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中找到的该类所需的包含是: vector、string、conio.h,可能还有tchar.h,我也使用这个枚举来表示main的返回值,这在stdafx.h中也可以找到。

代码语言:javascript
复制
enum ReturnCode {
    RETURN_OK = 0,
    RETURN_ERROR = 1,
}; // ReturnCode

至于您的Movie类,您已经定义了检索数据的函数,但是还没有显示您已经定义了任何设置方法或构造函数。另外,您的getter应该声明为const函数,因为这些函数不会更改存储在类对象中的数据。你的班级应该是这样的:

Movie.h

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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中使用的函数是Utility::splitString(),您需要对数组中的条目进行for循环,每次传递时,您都必须解析该字符串,然后通过使用默认构造函数、填充每个成员或使用适当的构造函数构造对象来构造Movie对象。我将向您展示如何使用splitString()函数的示例。

main.cpp

代码语言:javascript
复制
#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将使用要解析的字符串作为其第一个参数,将分隔字符串或char作为其第二个参数,就像在您的示例中那样,它将是"|"字符,并将结果保存到字符串的向量中。从这里开始,在for循环的每一次传递中,只需构造您的Movie对象,同时为它们分配适当的值。

票数 1
EN

Stack Overflow用户

发布于 2016-02-15 20:03:46

若要拆分字符串,请使用findfind_first_of函数从std::string中获取分隔符的位置。然后使用substr获取这些分隔符之间的子字符串。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35417693

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档