我的程序快完成了,但是输出却没有得到正确的数字。
Baby names:
1. Reading file: "src/people.txt" ... Number of lines in text file: 258000 number of lines in file is: 15 file has been read!
2. Sorted by popularity:
BabyNames object
1: John 1880 0.081541 0
2: 0 0 0
3: 0 0 0
4: 0 0 0
5: 0 0 0
6: 0 0 0
7: 0 0 0
8: 0 0 0
9: 0 0 0
10: 0 0 0
11: 0 0 0
12: 0 0 0
13: 0 0 0
14: 0 0 0
15: 0 0 0
3. Sorted by name:
BabyNames object
1: John 1880 0.081541 0
2: 0 0 0
3: 0 0 0
4: 0 0 0
5: 0 0 0
6: 0 0 0
7: 0 0 0
8: 0 0 0
9: 0 0 0
10: 0 0 0
11: 0 0 0
12: 0 0 0
13: 0 0 0
14: 0 0 0
15: 0 0 0
4. Sorted by year:
BabyNames object
1: John 1880 0.081541 0
2: 0 0 0
3: 0 0 0
4: 0 0 0
5: 0 0 0
6: 0 0 0
7: 0 0 0
8: 0 0 0
9: 0 0 0
10: 0 0 0
11: 0 0 0
12: 0 0 0
13: 0 0 0
14: 0 0 0
15: 0 0 0
5. Original names:
BabyNames object
1: John 1880 0.081541 0
2: 0 0 0
3: 0 0 0
4: 0 0 0
5: 0 0 0
6: 0 0 0
7: 0 0 0
8: 0 0 0
9: 0 0 0
10: 0 0 0
11: 0 0 0
12: 0 0 0
13: 0 0 0
14: 0 0 0
15: 0 0 0
Destructor to deallocate memory... Done!
Destructor to deallocate memory... Done!
Destructor to deallocate memory... Done!
Destructor to deallocate memory... Done!
... all done!
这是它打印的内容。 2-15中的所有名称和统计信息都应包含在内,但由于某些原因,它们全为0。
这是我的代码
BabyNames.h
#ifndef BABYNAMES_H_
#define BABYNAMES_H_
#include <string>
#include <fstream>
using namespace std;
/**
* gender: an enum to hold types boy and girl
*/
enum gender {boy, girl};
/**
* PeopleStats: a data struct to hold year, name, double, and the enum type
* gender
*/
struct PeopleStats {
short year;
string name;
double percent;
gender sex;
};
/**
* Names: A class that reads data from a file into a PeopleStats Array
* and is capable of sorting them by name and by popularity percentage
*/
class BabyNames {
public:
BabyNames(const BabyNames& bn);
BabyNames( const int numLines);
~BabyNames();
const gender parseSex(string s);
void swap(int i);
const int getCapacity();//getter for dataSize
const PeopleStats& get(int i) const; //getter for objects of the data array
void sortByName(); //Sorts the names alphabetically
void sortByPopularity();//Sorts the names by popularity
void sortByYear();
void addArrayFillCount();
friend std::ostream& operator << (std::ostream& os, const PeopleStats& d);
friend std::ostream& operator << (std::ostream& os, const BabyNames& bn);
//friend std::istream& operator >> (std::istream& in, const PeopleStats& ac);
friend std::istream& operator >> (std::istream& in, const BabyNames& ac);
private:
PeopleStats* people;
int capacity;
int arrayFillCount; // to keep track of how many array locations have data objects in them
static const int OUT_OF_BOUNDS = -1;
};//end of class
#endif /* BABYNAMES_H */
BabyNames.cpp
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
#include "BabyNames.h"
/**
* BabyNames: A class that reads data from a file into a PeopleStats Array
* and is capable of sorting them by name and by popularity percentage
*/
BabyNames::BabyNames(const int numberOfLines) {
people = new PeopleStats[numberOfLines];
capacity = numberOfLines;
arrayFillCount = 0;
for (int i=0 ; i<capacity; i++){
people[i].year = 0;
people[i].name = "";
people[i].percent = 0;
people[i].sex = boy;
}
}
//Copy Constructor
BabyNames::BabyNames(const BabyNames& bn){
capacity = bn.capacity;
arrayFillCount = bn.arrayFillCount;
people = new PeopleStats[ bn.capacity ];
for (int i=0; i< bn.capacity ;i++)
people[i] = bn.people[i];
}
BabyNames::~BabyNames(){
cout << "Destructor to deallocate memory... Done!" << endl;
delete[]people;
}
/*
* sortByName - Sorts the entire array of people by name using the bubble
* sort algorithm. Array is sorted according to name, within the structure
* Algorithm becomes extremely slow if capacity > 3000
*/
void BabyNames::sortByName(){
//sorted is set to true if no changes were made
bool sorted = false;
//change tells the loop if we made a swap or not
bool change = false;
while (!sorted) {
for (int i = 0; i < capacity - 1; i++) {
int compare = people[i].name.compare(people[i + 1].name);
if (compare == 1) {
swap(i);
change = true;
}
}
//if the array was not changed,
//changed sorted to true and exit loop
if (change == false)
sorted = true;
//otherwise reset change and repeat the loop
else
change = false;
}
}
/**
* sortByPopularity - sorts the entire array using the bubble sort algorithm
* Method is almost exactly the same as sortByName, except the compare
* variable is a double consisting of the difference of the two popularity
* percentages.
* Algorithm becomes extremely slow if capacity > 3000
*/
void BabyNames::sortByPopularity(){
bool sorted = false;
bool change = false;
while (!sorted) {
for (int i = 0; i < capacity - 1; i++) {
double compare = people[i].percent - people[i + 1].percent;
if (compare < 0) {
swap(i);
change = true;
break;
}
}
if (change == false)
sorted = true;
change = false;
}
}
void BabyNames::sortByYear(){
bool sorted = false;
bool change = false;
while (!sorted) {
for (int i = 0; i < capacity - 1; i++) {
double compare = people[i].year - people[i + 1].year;
if (compare < 0) {
swap(i);
change = true;
break;
}
}
if (change == false)
sorted = true;
change = false;
}
}
/**
* swap - swaps the positions of people[i] and people[i + 1]
* @param i - index of the people array that will get swapped with i + 1
*/
void BabyNames::swap(int i) {
PeopleStats temp = people[i + 1];
people[i + 1] = people[i];
people[i] = temp;
}
/**
* getCapacity: returns the number of data entries stored.
* @return size of the data
*/
const int BabyNames::getCapacity(){
return capacity;
}
/**
* get: returns one PeopleStat Object
* @param i
* @require: i < capacity
* @return PeopleStat object
*/
const PeopleStats& BabyNames::get(int i) const {
if (i>=0 && i < capacity)
return people[i];
throw OUT_OF_BOUNDS;
}
/**
* << - overloads the outstream operator for PeopleStats object
* @param os
* @param d
* @return os : output stream
*/
std::ostream & operator << (std::ostream& os, const PeopleStats& d){
os << d.name << " " << d.year << " " << d.percent << " " << d.sex;
return os;
}
/**
* <<: overloads the outstream operator for the BabyNames object
* @param os
* @param bn
* @return
*/
std::ostream& operator << (std::ostream& os, const BabyNames& bn) {
os << " BabyNames object " << std::endl;
for (int i=0; i < bn.capacity; i++ )
os << " " << (i+1) <<": " << bn.get( i ) << std::endl;
return os;
}//end of operator
/*std::istream& operator >> (std::istream& in, const PeopleStats& ac){
in>>ac.year>>ac.name>>ac.percent>>ac.sex;
//struct doesnt need a loop in the operator
return in;
}*/
std::istream& operator >> (std::istream& in, const BabyNames& ac){
short tempYear;
string tempName;
double tempPercent;
string tempSex;
int arrayLocation = ac.arrayFillCount;
in >> tempYear;
in >> tempName;
in >> tempPercent;
in >> tempSex;
//gender tempGender = parseSex(tempSex);
ac.people[ arrayLocation ].year = tempYear;
ac.people[ arrayLocation ].name = tempName;
ac.people[ arrayLocation ].percent = tempPercent;
if( tempSex.compare( "boy" ) == 0 )
ac.people[ arrayLocation ].sex = boy;
else if ( tempSex.compare( "girl" ) == 0 )
ac.people[ arrayLocation ].sex = girl;
else
throw "invalid Gender";
//addArrayFillCount();
return in;
}
//Baby names extraction operator does need a loop
void BabyNames::addArrayFillCount(){
arrayFillCount++;
}
主要
#include <iostream>
#include "BabyNames.h"
/**
* main: The client function that controls the server, BabyNames
* For reasons currently unknown, the program will take forever
* to run after the * 3000-5000 line mark.
* @return 0 if successful
*/
int checkLines(string fn){
int numberOfLines = 0;
string temp;
ifstream myfile( fn.c_str(), ios::in );
while( getline( myfile, temp ) )
numberOfLines++;
std::cout << "Number of lines in text file: " << numberOfLines;
return 15;
}//make a stand alone function
int main(void) {
cout << "Baby names: " << endl;
const char filename[] = "src/people.txt";
cout << " 1. Reading file: \"" << filename << "\" ... ";
int numberOfNames = checkLines(filename);
cout << " number of lines in file is: " << numberOfNames;
BabyNames* names = new BabyNames( numberOfNames );
// read the contents of a file into names and print them
ifstream myFile( filename, ios::in );
//myfile.open(fn);
myFile >> *names;
cout << " file has been read!" << endl;
// Sort and print
cout << " 2. Sorted by popularity:" << endl;
BabyNames* namesByPop = new BabyNames( *names );
namesByPop->sortByPopularity();
cout << *namesByPop;
// Sort and print
cout << " 3. Sorted by name:" << endl;
BabyNames* namesByName = new BabyNames( *names );
namesByName->sortByName();
cout << *namesByName;
// Sort and print
cout << " 4. Sorted by year:" << endl;
BabyNames* namesByYear = new BabyNames( *names );
namesByYear->sortByYear();
cout << *namesByYear;
cout << " 5. Original names:" << endl;
cout << *names;
delete names;
delete namesByYear;
delete namesByName;
delete namesByPop;
cout << "... all done!" << endl;
}
文本文件看起来像这样,但是有250000多行
1880 Henry 0.020641 boy
1880 Robert 0.020404 boy
1880 Edward 0.019965 boy
1880 Harry 0.018175 boy
1880 Walter 0.014822 boy
1880 Arthur 0.013504 boy
1880 Fred 0.013251 boy
1880 Albert 0.012609 boy
我如何在>>运算符中获取arrayFillCount?
最佳答案
在myFile >> *names;
上,您正在调用std::istream& operator >> (std::istream&, const BabyNames&)
,它将执行以下代码:
[...] // var declarations
in >> tempYear;
in >> tempName;
in >> tempPercent;
in >> tempSex;
ac.people[ arrayLocation ].year = tempYear;
ac.people[ arrayLocation ].name = tempName;
ac.people[ arrayLocation ].percent = tempPercent;
[...] // other checks and return
它将仅正确读取文件的第一行,并且仅填充
people
对象内的BabyNames
的第一行(第一次arrayLocation
= 0)。您应该为要填充
myFile >> *names;
的行数执行*names
。您应该在填写
arrayFillCount++;
数据后立即添加ac.people[ arrayLocation ]
。