我该如何解决这个排序错误?

时间:2015-11-08 16:21:02

标签: c++

我想编写一个程序,在命令行中用户将输入他们想要输入的名称的数量,然后他们用名字和姓氏键入这些名称,如下所示:

./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

任何人都可以帮我找到这个bug,我不知道它有什么问题。

1 个答案:

答案 0 :(得分:1)

在这种情况下的标准建议是使用调试器并弄清楚出了什么问题。

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";
}

这里最重要的一点可能是封装了所有的知识&#34; name课程中的name。这使得程序的其余部分只需读取,比较和写入name作为完整的东西,而不是处理存储名称的所有内部细节(等等)。该计划的其余部分并不关心(或需要知道)有关name内部如何运作的任何内容。

还要注意它是如何分成多个独立的功能而不是几乎所有功能都在一个巨大的功能中。在这种情况下,每个函数都是如此小而简单(其目的很简单),对于几乎所有函数而言,大多数实际问题几乎乍看之下都是非常明显的。

然后是最后一篇文章:将尽可能多的工作留给标准库。仅举一个最明显的例子,它已经有了解码的代码 - 我们不需要编写自己的代码。