结构,数组和空格

时间:2012-11-16 18:52:02

标签: c++ text struct stream getline

我正在尝试完成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

2 个答案:

答案 0 :(得分:2)

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

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

你看到如何解析它吗?一个很好的选择是向后扫描字符串:

  1. 如果最后一个字符不是右括号,则抱怨格式错误;否则,把它砍掉,你已经完成了解析括号。
  2. 找到左括号;如果没有人,抱怨。你必须从最后搜索:标题可能自己包含括号,所以我们感兴趣的左括号必须是最后一个。将文本存储在括号之间(注意索引!):它将是你的year
  3. 将年份解析为数字(atoi或类似内容,有关详情,请参阅this answer或Google);如果解析失败,程序必须抱怨错误的输入格式
  4. 砍掉前面的空格并抱怨是否找不到空间
  5. 字符串的其余部分必须是视频标题;至少检查一下它是不是空的。
  6. 足以进行解析,现在您的Video对象具有标题和发布年份。其他两个字段现在具有默认值;但是你的程序必须能够更改它们并且可能序列化它们(用于将信息保存到文件中的一个奇特的词),以便下次用户启动程序时,这些字段的状态是保留。

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

    欢迎来到软件开发世界!

答案 1 :(得分: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。

更多信息:Regex docs