簡體   English   中英

我該如何解決這個排序錯誤?

[英]How can I solve this sorting error?

我想編寫一個程序,在命令行中用戶將輸入他們想要輸入的姓名數量,然后他們輸入帶有名字和姓氏的名字,如下所示:

./Sort-names 5
Andrew Hawking
John Smith
Stephen Hawking
Alice Cooper
Jean Smith

然后我將獲取這些輸入並按字典順序使用姓氏對它們進行排序,因此輸出應該是:

Alice Cooper
Andrew Hawking
Stephen Hawking
Jean Smith
John Smith

這是我的代碼:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <cstdlib>
#include <cstring>
#include <ctype.h>

using namespace std;

//Identify space in a line
int locateLastName (char name[][20], int i, int j) {
    int locate = 0;

    while (name[i][j] && locate == 0) {
        if (isspace(name[i][j])) {
            locate = 1;
        }
        j++;
    }
    return j;
}

int main(int argc, const char * argv[]) {
    int x = atoi(argv[1]); //the number of names
    char name[x][20]; //names in 2d array
    char nameCopy[20]; //for bubble sort

    //get the input names
    for (int i = 0; i < x; i++) {
        cin.getline(name[i],20);
    }

    //bubble sort the last name
    for (int i = 0; i < x-1; i++) {
        for (int j = 0; j < x-1; j++) {
            int a = locateLastName(name, j, 0);
            int b = locateLastName(name, j+1, 0);

            int haveChange = 0;
            while (name[j][a] && name[j+1][b] && haveChange == 0) {
                if (name[j][a] > name[j+1][b]) {
                    strcpy(nameCopy, name[j]);
                    strcpy(name[j], name[j+1]);
                    strcpy(name[j+1], nameCopy);

                    haveChange = 1;
                }
                a++;
                b++;
            }
        }
    }

    int line = 0;
    while (line < x) {
        cout << name[line] << endl;
        line++;
    }
    return 0;
}

但是,在我的程序執行后,它會產生以下結果:

./Sort-names 5
Andrew Hawking  ->input
John Smith
Stephen Hawking
Alice Cooper
Jean Smith

John Smith      ->output
Andrew Hawking
Jean Smith
Stephen Hawking
Alice Cooper

誰能幫我找到錯誤,我不知道它有什么問題。

在這種情況下的標准建議是使用調試器並找出問題所在。

IMO,在這種情況下,這是相當糟糕的建議。 即使當您調試代碼並糾正您觀察到的問題時,它仍然是(我希望)您在幾個月左右后不會喜歡的代碼。

長話短說,你沒有很好地利用語言和標准庫——你做了很多工作來復制它已經准備好供你使用的功能,而且你正在使用一些非- 一個特定編譯器的標准(和不可移植)擴展,沒有特別好的理由。

我可能會做更多這樣的事情:

#include <string>
#include <iostream>
#include <algorithm>
#include <vector>

// We'll use this a little later: just "eat" all the leading white-space
// from a stream.
std::istream &eat_whitespace(std::istream &is) {
    char ch;
    while (isspace(is.peek()))
        is.get(ch);
    return is;
}

// define a class to store, read, write, and compare people's names:
class name {
    std::string first;
    std::string last;
public:
    // Define how to read a name from a stream:
    friend std::istream &operator>>(std::istream &is, name &n) {
        is >> n.first;
        eat_whitespace(is);
        return std::getline(is, n.last);
    }

    // likewise, how to write a name to a stream:
    friend std::ostream &operator<<(std::ostream &os, name const &n) {
        return os << n.first << ' ' << n.last;
    }

    // Define how to compare two names. This will compare first by last name,
    // then if those are equal, first names:
    bool operator<(name const &other) const {
        if (other.last < last)
            return false;
        if (last < other.last)
            return true;
        return first < other.first;
    }
};

int main() {
    // Read the names from a file into a vector:
    std::vector<name> names { std::istream_iterator<name>(std::cin),
        std::istream_iterator<name>() };

    // Sort them:
    std::sort(names.begin(), names.end());

    // Write out the results:
    for (auto const &n : names)
        std::cout << n << "\n";
}

也許這里的一個最重要的一點是具有封裝在一個所有的“知識” namename的類。 這讓程序的其余部分只是讀取、比較和寫入name作為一個完整的東西,而不是處理名稱如何存儲(等等)的所有內部細節。 程序的其余部分不關心(或需要知道)有關name在內部如何工作的任何信息。

還要注意它是如何拆分為多個單獨的功能而不是將幾乎所有功能都包含在一個巨大的功能中的。 在這種情況下,每個函數都如此小而簡單(而且其目的也足夠簡單),以至於對於幾乎所有函數來說,大多數真正的問題幾乎乍一看就很明顯了。

然后是最后一部分:將盡可能多的工作留給標准庫。 舉個最明顯的例子,它已經有代碼來排序——我們不需要編寫我們自己的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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