[英]Order files with MergeSort in c++
我正在尝试实现自己的MergeSort,但遇到了一些问题,看看是否有人可以帮助我。
我有一个很大的文件,其中一些信息用逗号分隔(名称,城市,邮件,电话)。 我想应用mergesort对其进行排序,因为我认为客户端计算机一次尝试将没有足够的内存来进行排序。
因此,我将其拆分为MAX_CUSTOMERS行的文件,并分别对其进行排序,直到此处都正确为止,但是当我想获取前两个文件并对其进行排序时,我遇到了所有问题,我遇到了重复的问题和其他问题消失,这是我的代码:
void MergeSort(string file1Name, string file2Name,string name){
printf("Enter MERGE SORT %s AND %s\n",file1Name.c_str(),file2Name.c_str());
string temp;
string fileName;
string lineFile1, lineFile2;
bool endFil1 = false, endFil2 = false;
int numCust1 = 0;
int numCust2 = 0;
int x1 = 0, x2 = 0;
ifstream file1;
file1.open(file1Name.c_str());
ifstream file2;
file2.open(file2Name.c_str());
ofstream mergeFile;
fileName = "customers_" +name +".txt";
cout << "Result file " << fileName << endl;
mergeFile.open("temp.txt");
getline(file1,lineFile1);
getline(file2,lineFile2);
while(!endFil1 && !endFil2){
if(CompareTelf(lineFile1,lineFile2)==1){
mergeFile << lineFile1 << endl;
if(!getline(file1,lineFile1)){
cout << lineFile1 << endl;
cout << "1st file end" << endl;
endFil1 = true;
}
}else{
mergeFile << lineFile2 << endl;
if(!getline(file2,lineFile2)){
cout << lineFile2 << endl;
cout << "2nd file end" << endl;
endFil2 = true;
}
}
}
if(endFil1){
//mergeFile << lineFile2 << endl;
while(getline(file2,lineFile2)){
mergeFile << lineFile2 << endl;
}
}else{
//mergeFile << lineFile1 << endl;
while(getline(file1,lineFile1)){
mergeFile << lineFile1 << endl;
}
}
file1.close();
file2.close();
mergeFile.close();
rename("temp.txt",fileName.c_str());
return;
}
Customer SplitLine(string line){
string splitLine;
string temp;
Customer cust;
int actProp = 0;
int number;
istringstream readLineStream(line); //convert String readLine to Stream readLine
while(getline(readLineStream,splitLine,',')){
if (actProp == 0)cust.name = splitLine;
else if (actProp == 1)cust.city = splitLine;
else if (actProp == 2)cust.mail = splitLine;
else if (actProp == 3)cust.telf = atoi(splitLine.c_str());
actProp++;
}
//printf("Customer read: %s, %s, %s, %i\n",cust.name.c_str(), cust.city.c_str(), cust.mail.c_str(), cust.telf);
return cust;
}
int CompareTelf(string str1, string str2){
Customer c1 = SplitLine(str1);
Customer c2 = SplitLine(str2);
if(c1.telf<c2.telf)return 1; //return 1 if 1st string its more important than second, otherwise, return -1
else return -1;
}
struct Customer{
string name;
string city;
string mail;
long telf;
};
如果对代码有疑问,请说出来! 我尝试使用varNames尽可能描述性!
非常感谢。
您的代码看起来不错,但是它有一些缺陷和一个重要的遗漏。
较小的缺陷之一是缺少对Customer
结构的初始化-您没有为该结构提供构造函数,也没有对cust
变量进行显式初始化。 希望字符串成员可以由字符串类构造函数正确初始化,但是long telf
可以获取任何初始值。
另一个是在分割输入行时缺少格式检查。 您确定每个输入行都具有相同的格式吗? 如果行中的逗号过多(例如,名称中的逗号),则循环可能会错误地尝试将“电子邮件”数据分配给“电话”成员...
OTOH如果逗号太少,则'telf'成员可能会保持未初始化状态,初始值是随机的...
与第一个缺陷一起,该缺陷可能会导致输出数据的顺序不正确。
使用atoi
函数时也会出现类似的问题:它返回int
但变量为long
。 我想您是因为期望的值范围而选择了long
类型-如果是这样,将输入数据转换为int
可能会截断大部分数据! 我不确定atoi
在这种情况下会做什么,它可能返回转换输入字符串的某些初始部分的结果,也可能只是返回零。 这两个值都是错误的,并导致不正确的排序,因此最好改用atol
。
下一个问题是从两个输入文件中读取第一行。 您无需检查getline()
成功。 如果输入文件为空,则相应的lineFile_num
字符串将为空,但endFil_num
不会反映该内容-仍为false
。 因此,您再次进入比较无效数据的过程。
最后是主要问题。 假设file1的内容“大于”整个file2的内容(即:大于)。 然后,存储在lineFile1
的第一行lineFile1
导致CompareTelf()
始终返回-1
。 主循环将整个file2复制到输出中,然后...? 最后的while()
循环从getline(file1,lineFile1)
开始,从而丢弃了file1的第一行!
由记录(A,C)和(B)组成的文件将发生类似的结果,这些文件将合并为(A,B,C):首先读取A和B,然后保存A并读取C,然后再读取B保存并检测到文件2的结尾。 然后while(getline(...))
取消内存中的C并找到文件1的结尾,从而终止了循环。 记录C丢失。
通常,当主合并循环while(!endFil1 && !endFil2)
耗尽一个文件时,另一个文件的第一未保存行将被丢弃。 为了避免这种情况,您需要存储第一次读取的结果:
endFil1 = ! getline(file1,lineFile1);
endFil2 = ! getline(file2,lineFile2);
然后,在主循环之后,开始使用未保存的行复制输入文件的尾部:
while(!endFil1) {
mergeFile << lineFile1 << endl;
endFil1 = !getline(file1,lineFile1);
}
while(!endFil2) {
mergeFile << lineFile2 << endl;
endFil2 = !getline(file2,lineFile2);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.