-1

我正在尝试完成我的 C++ 课程介绍的作业,但我陷入了僵局!该程序应该是一个 VHS 视频管理器,其中电影存储在结构中。电影是从源文件夹中的 .txt 文件中获取的,包含电影的标题和年份。读入文本文件后,初始输出应如下所示:

Initializing Video Collection:
What file should I use? movies.txt
A New Hope (1977)
Empire Strikes Back (1980)
Flight of the Navigator (1986)
Goonies (1985)
Last Crusade (1989)
Raiders of the Lost Ark (1981)
Return of the Jedi (1983)
Temple of Doom (1984)
War Games (1983)

视频存储在如下结构中:

struct Video
{
    string title; //the name of the video
    int year; // the year the movie was released
    int stars; // a rating out of five stars - this will be zero until you set it
    bool watched; // starts as false until you watch the movie and flip it to true
};

似乎我不知道如何正确读取我的文件,以便将标题和年份放置在它们各自的数组位置中。这是我为此目的而拥有的功能:

void initialize(Video video_array[tapes_max], Video data)
{

    ifstream videofile;
    videofile.open("movies.txt");
    if(videofile.fail())
    {
        cout << "Could not open states file for reading!" << endl;
        exit(1);
    }
    for(int i = 0; i < tapes_max; i++)
    {
        getline(videofile, video_array[i].title);
    }

    videofile.close();
    for (int i = 0; i < tapes_max; i++)
    {
       cout << video_array[i].title << " " << video_array[i].year << endl;
    }

    cout << endl << endl;
}

这是分配给我的PDF的链接,也许你们能比我更好地理解它?在此先感谢您的帮助!

https://docs.google.com/open?id=0Bwr7dC-H4CCZUkkyUGNTRzRZdk0

4

2 回答 2

2

因此,您已将输入行读入字符串。现在,您需要将其分成两部分:标题和年份。这通常称为解析:从字符串中提取一些信息。

我假设您没有将正式语法(定义字符串格式的规则集)作为任务的一部分,但很容易做出很好的猜测:该行包含标题(可能带有空格),然后是一个空格,左括号,发行年份的十进制表示,后跟右括号。

你知道如何解析它吗?一个不错的选择是向后扫描字符串:

  1. 如果最后一个字符不是右括号,则抱怨格式错误;否则,砍掉它,你已经完成了括号的解析。
  2. 找到左括号;如果没有人,请投诉。您必须从末尾开始搜索:标题本身可能包含括号,因此我们感兴趣的左括号必须是最后一个。将文本存储在括号之间(注意索引!):它将是您的year.
  3. 将年份解析为数字(atoi或类似的,请参阅此答案或谷歌了解更多详细信息);如果解析失败,程序必须报错输入格式
  4. 砍掉前面的空格,如果找不到空格,请抱怨
  5. 字符串的其余部分必须是视频标题;至少检查它不是空的。

足够解析了,现在您的Video对象有了标题和发布年份。其他两个字段现在具有默认值;但是您的程序必须能够更改它们并可能将它们序列化(将信息保存到文件中的一个花哨的词),以便下次用户启动您的程序时,这些字段的状态会被保留。

这意味着也许您应该为磁盘上的数据发明一种格式,其中包含所有四个字段(当前.txt仅包含其中两个)。当然,您还需要该格式的解析器。在您的情况下,我个人会使用非常简单的格式:例如,每行只有一个字段。

欢迎来到软件开发的世界!

于 2012-11-16T21:47:37.980 回答
0

我认为你应该使用 boost::regex。
这是有关如何使用正则表达式处理行的演示:

#include <boost/regex.hpp>
#include <iostream>
#include <string>
#include <cstring>

int main()
{
  using namespace std;

  string line = "Hey Joe(1984) "; // an example line that you can read
  boost::smatch what;
  boost::regex e("(.*)\\(([0-9]+)\\).*"); // whatever comes before numbers in parentheses, is the title.

  if(boost::regex_match(line, what, e, boost::match_extra))
  {
    string title = what[1];
    int year = atoi(static_cast<string>(what[2]).c_str()); // perhaps there is a better code for this but it will do.
    cout<<"title: "<<title<<"\tyear: "<<year<<endl;
  }
  else
  {
    cout<<"No match"<<endl; // indicates a wrong line
  }
  return 0;
}

只需将其放入循环中即可。

如果你不知道如何使用 boost:

安装boost ——(在 Mac 上,我用 Macports 安装了 boost)

为我编译行:

g++ -I/opt/local/include -L/opt/local/lib -lboost_regex-mt boost_regex.cpp
# for testing
./a.out 

对你来说,它可能在 Windows 上是类似的。( g++ -IC:\path\to\boost\includes -LC:\path\to\boost\libs -lboost_regex-something)。在 Windows 上,我认为您应该查找一个名为“boost_regex.dll”之类的 dll 文件。您可以在 boost 安装的 lib 目录中找到该 dll。

更多信息:正则表达式文档

于 2012-11-26T20:06:40.063 回答