1

我是 C++ 的初学者,现在我需要处理来自输入文件的数据,该文件有很多行,如下所示:

2012019109 Proadan Legeaf 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')分隔。

有什么办法可以解决上述问题,同时坚持使用数组而不使用向量或地图?

4

2 回答 2

1

问题是您正在尝试读取 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中,您可以尝试将它们存储在无符号的 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 先读取一行,从中创建一个字符串流,然后在此流上使用 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(database.begin(), database.end());

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

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

您可以在此处了解有关重载运算符的更多信息。

编辑

如果您不能使用向量,那并不会真正改变循环代码(只需将 newPerson 替换为相应的已分配的 Person 对象(类似于数据库 [x])。

现在对于排序,您仍然可以对 STL 使用排序算法,它应该适用于迭代器,但它可以适用于指针。这不是一个很好的解决方案,它可能不是你应该做的。

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

请注意,如果您不使用结构并继续使用多个数组,则不能使用 STL 排序算法,并且排序算法中的数据交换将比必要的复杂得多。

于 2013-04-12T10:11:43.880 回答
0

好吧,首先,使用:

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; 

没有拉姆达斯?这里有一个完整的例子

#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<< "2012019874\tZooadan Legeaf Coaa\tFemale\t65"<<endl;
  fin<< "1111090909\tZuilia Perez\tFemale\t701"      <<endl;
  fin<< "2012019109\tProadan Legeaf Coaa\tFemale\t65"<<endl;
  fin<< "2345019176\tTrroadan Legeaf\tFemale\t98"    <<endl;
  fin<< "2012019109\tAAroadan Legeaf Coaa\tFemale\t65"<<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();     
}
于 2013-04-12T10:05:04.023 回答