c++ - 从文件导入数据时遇到问题。我得到一个无限循环
问题描述
我可以让我的文件加载 1 个完整的结构。但是当我尝试遍历文件时,我有一个无限循环并且没有加载任何数据。我附上了我的代码和平面文件。
#include <iostream>
#include <string.h>
#include <vector>
#include <fstream>
using namespace std;
typedef struct video_items{
string Title;
int YOP;
string Category;
float Gross;
}video;
void LoadMovies (vector<video> &v);
void SearchMovies (vector <video> &v, string s);
int main()
{
vector <video> v;
LoadMovies(v);
cout<<"Total number of movies: "<<v.size()<<endl;
for (unsigned int i=0; i<v.size(); ++i) {
cout<<"----------------------------------------------------"<<endl;
cout<<v[i].Title<<endl;
cout<<"Category: "<<v[i].Category<<endl;
cout<<"Year of Publication: "<<v[i].YOP<<endl;
cout<<"Gross: "<<v[i].Gross<<endl;
cout<<"----------------------------------------------------"<<endl<<endl;
}
string WantMovie;
cout<<"Please type in what movie you want."<<endl;
cin>>WantMovie;
SearchMovies(v,WantMovie);
return 0;
}
void LoadMovies (vector<video> &v)
{
video L;
ifstream myfile;
myfile.open ("Movies.txt");
if (myfile.is_open())
{
cout <<"Loading Movie Catalog..."<<endl<<endl;
int i=0;
while (!myfile.eof())
{
myfile.ignore();
//cout<<i<<endl<<endl;
v.push_back(L);
getline(myfile,v[i].Title);
getline(myfile,v[i].Category);
myfile>>v[i].YOP;
myfile>>v[i].Gross;
i++;
}
myfile.close();
}
else cout<<"Unable to open file."<<endl;
}
void SearchMovies (vector <video> &v, string s)
{
s[0] = toupper(s[0]);
unsigned int i;
for (i=0; i<v.size(); i++)
{
if (v[i].Title.compare(0,s.size(),s)==0)
{
break;
}
}
if (i >=v.size()){
i =0;
}
switch(i)
{
case 1:cout<<"You have chosen "<<s<<endl;
break;
default:
cout<<"That movie is not currently in the library, please choose a different one."<<endl;
break;
}
}
平面文件中忽略的第一个字符。
=========数据文件==========
Captain America: The First Avenger
Action, Adventure, Sci-Fi
2011
1786.65
Iron Man
Action, Adventure, Sci-Fi
2008
585.2
The Incredible Hulk
Action, Adventure, Sci-Fi
2008
134.52
Iron Man 2
Action, Adventure, Sci-Fi
2010
312.43
Thor
Action, Adventure, Fantasy
2011
181.03
The Avengers
Action, Adventure, Sci-Fi
2012
623.28
Iron Man 3
Action, Adventure, Sci-Fi
2013
409.01
解决方案
如果您仍然被卡住,那么请考虑从数据文件中读取每个结构您必须完成的工作。您需要阅读 4 条信息,2 个字符串,1 个整数,1 个浮点数。您正在正确地考虑读入一个临时 struct L
,但您想要做的是验证您L
在添加L
到您的向量之前已正确填充了所有四个成员。
要成功阅读所有四个成员,您必须首先阅读第一个成员。在读取第一个成员时调整您的读取循环,例如:
while (getline (myfile, L.Title)) { /* validate each read */
读取第一个成员后,验证接下来读取的三个成员中的每一个:
if (getline (myfile, L.Category) &&
myfile >> L.YOP && myfile >> L.Gross) {
v.push_back(L); /* before adding temp struct to vector */
i++;
}
假设您的输入文件中只有一个'\n'
关注Gross
者并使您的阅读变得脆弱,这是有风险的。忽略所有字符到行尾,例如
/* ignore all characters to \n */
myfile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
不要在代码中使用幻数或硬编码文件名。main()
接受允许您传递文件名以从命令行读取数据的参数(或者您可以将其作为输入),但不要将硬编码的文件名埋在函数中:
myfile.open ("Movies.txt");
相反,在命令行上传递文件名,例如
int main (int argc, char **argv)
{
if (argc < 2) { /* validate at least 1 argument given for filename */
std::cerr << "usage: " << argv[0] << " filename\n";
return 1;
}
...
LoadMovies(v, argv[1]); /* pass filename to open to LoadMovies */
没有理由六次调用std::cout
来显示每部电影。一个会做:
for (unsigned int i=0; i<v.size(); ++i)
std::cout << "----------------------------------------------------\n"
<< v[i].Title << '\n'
<< "Category: " << v[i].Category << '\n'
<< "Year of Publication: " << v[i].YOP << '\n'
<< "Gross: " << v[i].Gross << '\n'
<< "----------------------------------------------------\n\n";
已SearchMovies()
提供有意义的返回以指示调用者返回成功/失败。理想情况下,您希望将您的实现(您的逻辑/计算)与您的界面(您的输出给用户)分开。如果您提供有意义的返回类型,SearchMovies()
则可以完全从函数中删除输出,并main()
根据您的返回将其提供回来。一个简单的类型返回int
就可以了。-1
表示在库中未找到,或在成功时返回向量中的索引。例子:
int SearchMovies (std::vector<video>& v, const std::string& s)
{
int i;
std::string slower (s); /* string s to lowercase */
std::transform (slower.begin(), slower.end(),
slower.begin(),
[](unsigned char c){ return std::tolower(c); });
for (i = 0; i < (int)v.size(); i++) { /* movie title to lowercase */
std::string mlower (v[i].Title);
std::transform (mlower.begin(), mlower.end(),
mlower.begin(),
[](unsigned char c){ return std::tolower(c); });
if (mlower == slower) /* compare lowercase movie and string */
return i;
}
return -1; /* if not found, return -1 (cannot be an index) */
}
(注意:您可以循环将每个字符转换为小写,或者您可以只使用std::transform
转换所有字符。)
通过转换电影标题和WantMovie
搜索字符串,您可以在搜索功能中进行比较。
然后,main()
您可以简单地在向量中的该索引处输出电影标题v
,例如
std::cout << "Please type in what movie you want.\n";
if (getline (std::cin, WantMovie)) {
int index = SearchMovies (v, WantMovie);
if (index != -1) /* validate search and output here */
std::cout << "You have chosen: " << v.at(index).Title << '\n';
else
std::cout << WantMovie << " is not currently in the library.\n";
}
无论用户使用哪种情况输入搜索词,您的搜索都将起作用,例如
...
Please type in what movie you want.
iron man 3
You have chosen: Iron Man 3
或者
...
Please type in what movie you want.
thor
You have chosen: Thor
这应该让你指出正确的方向。如果您遇到其他绊脚石,请告诉我,我很乐意提供进一步帮助。
推荐阅读
- python-3.x - 使用客户转换器中的智能函数向数据框添加功能
- r - 将 DALEX 解释函数应用于 xgboost 模型以进行 what_if / centerisParibus 分析
- javascript - 在 JavaScript 中,有没有办法在不使用 toLocaleString 的情况下将日期转换为时区?
- python - 如果我在 __exit__ 方法中返回 self,为什么异常会消失?
- javascript - 为什么 keyDown 事件监听器似乎随机触发了错误的功能?
- swap - QuantLib:面值掉期率计算
- gatsby - GatsbyJS - 解析带有和不带有“.html”后缀的页面 URL
- wpf - 鼠标悬停时带有内容模板更改背景的 wpf 控件
- c++ - 从文件中读取会导致 C++ 中出现空行
- angular - Angular - 一旦在订阅中更改其值,变量就不会在视图中更新