[英]C++ Sort Segmentation Fault
我正在為一個班級的一個編碼項目工作,在該項目中,我得到了一個隨機選擇的姓,名和ssns(隨機生成)的列表,需要盡快對其進行排序。 老師提供了一些我們無法更改的代碼,我們應該只填寫排序功能。 我已經創建了鏈表,將其轉換為數組,並嘗試使用C ++ std::sortc++
函數。 提供我的代碼,請注意該數組已初始化為1010001個空格,因為它剛好大於實際數據集的大小。
在執行排序時,出現分段錯誤。 我相信這與以某種方式超調數組中的位置有關,但是我似乎找不到我應該使用的實際末端。
碼:
#include <iostream>
#include <fstream>
#include <sstream>
#include <list>
#include <vector>
#include <string>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <array>
using namespace std;
// A simple class; each object holds four public fields
class Data {
public:
string lastName;
string firstName;
string ssn;
};
// Load the data from a specified input file
void loadDataList(list<Data*>& l, const string& filename) {
ifstream input(filename);
if (!input) {
cerr << "Error: could not open " << filename << "\n";
exit(1);
}
// The first line indicates the size
string line;
getline(input, line);
stringstream ss(line);
int size;
ss >> size;
// Load the data
for (int i = 0; i < size; i++) {
getline(input, line);
stringstream ss2(line);
Data* pData = new Data();
ss2 >> pData->lastName >> pData->firstName >> pData->ssn;
l.push_back(pData);
}
input.close();
}
// Output the data to a specified output file
void writeDataList(const list<Data*>& l, const string& filename) {
ofstream output(filename);
if (!output) {
cerr << "Error: could not open " << filename << "\n";
exit(1);
}
// Write the size first
int size = l.size();
output << size << "\n";
// Write the data
for (auto pData : l) {
output << pData->lastName << " "
<< pData->firstName << " "
<< pData->ssn << "\n";
}
output.close();
}
// Sort the data according to a specified field
// (Implementation of this function will be later in this file)
void sortDataList(list<Data*>&);
// The main function calls routines to get the data, sort the data,
// and output the data. The sort is timed according to CPU time.
int main() {
string filename;
cout << "Enter name of input file: ";
cin >> filename;
list<Data*> theList;
loadDataList(theList, filename);
cout << "Data loaded.\n";
cout << "Executing sort...\n";
clock_t t1 = clock();
sortDataList(theList);
clock_t t2 = clock();
double timeDiff = ((double)(t2 - t1)) / CLOCKS_PER_SEC;
cout << "Sort finished. CPU time was " << timeDiff << " seconds.\n";
cout << "Enter name of output file: ";
cin >> filename;
writeDataList(theList, filename);
return 0;
}
// -------------------------------------------------
// YOU MAY NOT CHANGE OR ADD ANY CODE ABOVE HERE !!!
// -------------------------------------------------
// You may add global variables, functions, and/or
// class defintions here if you wish.
class T1Member {
public:
Data* pointer;
const char* lName;
const char* fName;
const char* ssn;
char lNamefl, lNamesl, fNamefl, fNamesl; // lastname first letter, second letter, first name first letter, second letter
T1Member(Data* d, const char* lN, const char* fN, const char* ssnum, char lNfl, char lNsl, char fNfl, char fNsl) :
pointer(d), lName(lN), fName(fN), ssn(ssnum), lNamefl(lNfl), lNamesl(lNsl), fNamefl(fNfl), fNamesl(fNsl) {}
T1Member() {};
};
array<T1Member*, 1010001> T1pt;
bool compare(T1Member* (x), T1Member* (y)) {
if (x->lNamefl == y->lNamefl) {
if (x->lNamesl == y->lNamesl) {
if (strcmp(x->lName, y->lName) == 0) {
if (x->fNamefl == y->fNamefl) {
if (x->fNamesl == y->fNamesl) {
if (strcmp(x->fName, y->fName) == 0) {
return (strcmp(x->ssn, y->ssn) < 0);
}
else {
return (strcmp(x->fName, y->fName) < 0);
}
}
else {
return (x->fNamesl < y->fNamesl);
}
}
else {
return (x->fNamefl < y->fNamefl);
}
}
else {
return (strcmp(x->lName, y->lName) < 0); // <0 if x->lName is smaller than y->lName
}
}
else (x->lNamesl < y->lNamesl);
}
else {
return (x->lNamefl < y->lNamefl);
}
}
void sortDataList(list<Data*>& l) {
int j = 0, n = 0, m = 0;
// copying linked list into an array
for (auto i = l.begin(); i != l.end(); i++, j++) {
auto tmp = new T1Member((*i), ((*i)->lastName.data()), ((*i)->firstName.data()),
((*i)->ssn.data()), (*i)->lastName[0], (*i)->lastName[1], (*i)->firstName[0], (*i)->firstName[1]);
T1pt[j] = tmp;
}
int diff = T1pt.size() - l.size();
sort(T1pt.begin(), (T1pt.end() - diff - 1), compare);
// sorting the linked list
for (auto p = l.begin(); p != l.end(); p++, m++) {
(*p) = (*T1pt[m]).pointer;
}
}
鏈接到我正在測試的示例數據集: https : //gofile.io/?c=ggL1RE
考慮到我無法修改上面的部分,這是一個粗略的示例(未經測試),外觀如何。 (盡管講師的代碼已經有問題。):
void sortDataList(list<Data*>& l) {
l.sort([](Data* x, Data* y){
if(x->lastName != y->lastName) {
return x->lastName < y->lastName;
}
if(x->firstName != y->firstName) {
return x->firstName < y->firstName;
}
return x->ssn < y->ssn;
});
}
這沒有以任何方式進行特別優化,但是您需要先編寫正確的代碼,然后才能嘗試提高其性能。
例如,您可能會注意到,您實際上將字符串進行了兩次比較,一次是對!=
比較,一次是對==
,您將希望將其合並為一次比較。 您一直試圖為此使用strcmp
,但是strcmp
是C庫函數。 看一下std::string
的引用及其提供的內容,您將看到它確實具有compare
方法,該方法與C語言中的strcmp
等效。因此,我們可以使用它來提高性能:
void sortDataList(list<Data*>& l) {
l.sort([](Data* x, Data* y){
auto r = x->lastName.compare(y->lastName);
if(r != 0) {
return r < 0;
}
r = x->firstName.compare(y->firstName);
if(r != 0) {
return r < 0;
}
return x->ssn < y->ssn;
});
}
依此類推,逐步進行改進(並始終在每次更改時進行基准測試和配置文件!)。
您需要使用std::list
的成員函數l.sort
,而不是免費的std::sort
,因為后者僅適用於std::list
缺少的隨機訪問迭代器。 除此之外,它具有基本相同的效果。
[](Data* x, Data* y){ ... }
是lambda表達式。 如果您不熟悉它們,則可以改用適當的函數,然后將其傳遞給l.sort
:
bool compare(Data* x, Data* y) {
...
}
void sortDataList(list<Data*>& l) {
l.sort(compare);
}
在lambda(或compare
函數)中,如果指針x
指向的元素小於y
指向的元素,則需要返回true。 從您的代碼中,我假設排序順序應該是按字典順序,從lastName
開始,然后是firstName
然后是ssn
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.