簡體   English   中英

C ++排序分段錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM