输入文件中的数组

Arrays from input file

本文关键字:数组 文件 输入      更新时间:2023-10-16

我是一个非常初学c++的人,现在我需要处理来自输入文件的数据,该文件有以下几行:

2012019109 Proadan legea Coaa女65

这些是学生编号,姓名(2或3个字),性别和考试成绩。

我必须为每个属性创建一个数组。此外,我不知道输入文件可能包含多少行(最多100,000行),但输入文件中的第一个数字将是该文件中的行数。

一旦我设置了一个数组,我需要实现一个函数来按Name的字母字符串顺序(升序)对记录进行排序,然后将这些记录放入输出文件中。

我试过以以下方式做第一部分(设置数组),但似乎是错误的:

ifstream fin;
ofstream fout;
fin.open("input.txt");
fout.open("output.txt");
if (fin.fail()) {
    cout << "Fail to open inout.txt" << endl;
    exit(1);
}
int x; 
fin >> x; //this is the first number within the input text file, indicating the number of lines in the file. I would use this to determine the size of the arrays:
int UID [x];
string name [x];
string gender [x];
int score [x];
int y = 0;

// In the following part, I am trying to extract the information into the different arrays, one by one, increasing the number of the element from 0 up till x. Complier error says no matching function for call for the UID and score lines.
while (y!=x, y++) {
    getline(fin, UID [y], 't');
    getline(fin, name [y], 't');
    getline(fin, gender [y], 't');
    getline(fin, score [y], 't');
    break;
    }`

一旦我有了这些数组,我只需要找到一种按字母顺序排序的方法,但即使有了这些第一步,我还是卡住了。正如您可能会说的,我不太了解编程,并将感谢任何帮助!

编辑:谢谢你的意见和帮助,我真的很感谢你的时间。我的问题是,因为这是在学校的一个项目工作,我被要求使用数组(由于一些无法解释的原因)。

仅供参考,在输入文件中,号码/姓名/性别/分数用TAB ('/t')分隔。

是否有任何方法来解决上述问题,同时坚持数组和不使用向量或地图?

问题是你试图在int:

中读取字符串
getline(fin, UID [y], 't');

UID[y]是int类型,而getline只能存储为字符串。

所以你必须首先将其存储在一个缓冲字符串中然后使用atoi将其转换为int类型例如:

string UID_buffer;
getline(fin, UID_buffer, 't'); 
UID[y] = atoi(UID_buffer.c_str());

但是还有另一个问题,你的UID实际上太大了,无法容纳一个有符号的int,你可以尝试将它们存储在unsigned 32位或64位,但它可能更简单,只是将它们存储为字符串。

OOP方法建议您使用来存储每个对象,而不是使用多个数组:

struct Person {
    string UID;
    string name;
    string gender;
    int score;
};

然后只创建一个数组:

Person* database = new Person[x];

你也可以创建一个c++可调整大小的容器,比如vector,排序起来会容易得多:

vector<Person> database;

还要注意,应该使用for循环,而不是while

对于循环代码,您可以先使用getline读取一行,从中生成stringstream,然后在该流上使用getline读取该行的每个元素,如下所示:

for(int y = 0, y < x; y++) {
    getline(fin, line); 
    stringstream linestream(line);
    Person newPerson;
    getline(linestream, newPerson.UID, 't'); 
    getline(linestream, newPerson.name, 't'); 
    getline(linestream, newPerson.gender, 't'); 
    string buffer;
    getline(linestream, buffer, 't'); 
    newPerson.score = atoi(buffer.c_str());
    database.push_back(newPerson);
}

要对得到的向量进行排序,可以使用STL中的排序算法,它使用类的"<"操作符,因此您只需重载该操作符并对向量使用sort。

sort(database.begin(), database.end());

使用这样定义的比较运算符:

bool operator< (const Person & p1, const Person& p2)
{
    //just an example
    return p1.UID.compare(p2.UID) < 0;
}

你可以在这里了解更多重载操作符。

编辑

如果你不能使用vector,这并不会真正改变循环代码(只需将newPerson替换为相应的已经分配的Person对象(类似于database[x])。

对于排序,你仍然可以使用STL的排序算法,它应该在迭代器上工作,但它可以在指针上工作。这不是一个简洁的解决方案,也可能不是你应该做的。

否则你可以实现你自己的排序算法,这真的是一个教科书案例。

请注意,如果你不使用结构体,并且一直使用多个数组,那么你就不能使用STL排序算法,并且排序算法中的数据交换将比必要的要复杂得多。

首先,使用:

for (int y=0 ; y<x, y++)

而不是while但你可以使用矢量或地图让你的生活变得更容易。我知道,给你完整的代码不是个好主意。最好自己试一下。但是我想让你们有动力去学习STL。这真的很简单。(你可以找到更有效的方法)

例如:

int x; 
fin >> x; //this is the first number within ...    
std::multimap<std::string,std::string> rows;
std::string row;
while(getline(fin, row))
{
     std::stringstream r(row) ;
     std::string name;
     getline(row, name, 't'); // ID
     getline(row, name, 't'); // name
     rows.insert(std::make_pair(name,row));
}
fout << x << std::endl;
for (const auto& r : rows)
  fout << r << std::endl;
if (x!=rows.size())   
   //.... error?

没有地图吗?…

struct row{string ID, name, rest;};

fout << x << std::endl;
row *rows=new row[x];
for(int i=0;i<x;++i)
{
    getline(fin, rows[i].ID,   't'); // ID
    getline(fin, rows[i].name, 't'); // name
    getline(fin, rows[i].rest      ); 
}
  std::sort(rows,rows+x,[](const row& r1, const row& r2) 
                              {return r1.name<r2.name;}  );
  for( i=0;i<x;++i)
     fout<<rows[i].ID<<'t'<< rows[i].name<<'t'<< rows[i].rest<<endl; 

没有lambda ?这里有一个完整的例子

#include <string>
#include <algorithm>
#include <iostream>  
using namespace std;
struct row{string ID, name, rest;};
bool operator < (const row& r1, const row& r2) 
{  return r1.name<r2.name;} 
ostream &operator<<(ostream&o, const row&r)
{  return o<<r.ID<<'t'<< r.name<<'t'<< r.rest<<endl; }  
int main()
{ int x=2;
  row rows[]={{"1","BB","r1"},{"2","AA","r2"}};//=new row[x];
  std::sort(rows,rows+x);
  for(int i=0;i<x;++i)
    cout<<rows[i]; 
}

或者这里:(我希望你不要简单地复制代码,而是去阅读参考资料,享受学习使用标准c++库的乐趣)

#include <string>
#include <algorithm>
#include <iostream>  
#include <sstream> 
using namespace std;
struct row{string ID, name, rest;};
bool operator < (const row& r1, const row& r2) 
{  return r1.name<r2.name;} 
ostream &operator<<(ostream&o, const row&r)
{  return o<<r.ID<<'t'<< r.name<<'t'<< r.rest <<endl; }  
int main()
{ 
  stringstream fin,fout;
  fin<< "5"  << endl;
  fin<< "2012019874tZooadan Legeaf CoaatFemalet65"<<endl;
  fin<< "1111090909tZuilia PereztFemalet701"      <<endl;
  fin<< "2012019109tProadan Legeaf CoaatFemalet65"<<endl;
  fin<< "2345019176tTrroadan LegeaftFemalet98"    <<endl;
  fin<< "2012019109tAAroadan Legeaf CoaatFemalet65"<<endl;

  int x; 
  fin >> x; //this is the first number within ...   
  row *rows=new row[x];
  for(int i=0;i<x;++i)
  {
    getline(fin, rows[i].ID,   't'); // ID
    getline(fin, rows[i].name, 't'); // name
    getline(fin, rows[i].rest      ); 
  }
  std::sort(rows,rows+x);
  fout << x << std::endl;
  for(int i=0;i<x;++i)
      fout<<rows[i]; 
  delete []rows;
  cout<<"Input:n"<< fin.str()<<"nOutput:n"<< fout.str();     
}