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;
    }`

これらの配列を取得したら、アルファベット順に並べる方法を見つける必要がありますが、これらの最初の手順でも行き詰まっています。おそらくおわかりのように、私はプログラミングについてあまり知りません。何か助けていただければ幸いです。

編集: これまでのコメントとヘルプに感謝します。お時間をいただき、誠にありがとうございます。私の問題は、これは学校でのプロジェクト作業のためであるため、配列を使用する必要があることです (説明できない理由で)。

参考までに、入力ファイルでは、番号/名前/性別/点数がタブ('/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 は実際には signed int 内に収まらないほど大きいため、unsigned 32 または 64 ビットに格納しようとするかもしれませんが、文字列として格納する方が簡単な場合があります。

OOPアプローチでは、複数の配列を使用する代わりに、クラスを使用して各オブジェクトを格納することをお勧めします

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

そして、配列を 1 つだけ作成します

Person* database = new Person[x];

vectorなどの C++ のサイズ変更可能なコンテナーを作成することもできます。並べ替えがはるかに簡単になります。

vector<Person> database;

また、 while の代わりに for ループを使用する必要があることに注意してください。

ループ コードの場合、次のように、getline を使用して最初に 1 行を読み取り、そこから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(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 ソート アルゴリズムを使用できず、ソート アルゴリズムでのデータ スワップが必要以上に複雑になることに注意してください。

于 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 に答える